@github/copilot-sdk 0.1.32 → 0.1.33-preview.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -82,7 +82,6 @@ new CopilotClient(options?: CopilotClientOptions)
82
82
  - `useStdio?: boolean` - Use stdio transport instead of TCP (default: true)
83
83
  - `logLevel?: string` - Log level (default: "info")
84
84
  - `autoStart?: boolean` - Auto-start server (default: true)
85
- - `autoRestart?: boolean` - Auto-restart on crash (default: true)
86
85
  - `githubToken?: string` - GitHub token for authentication. When provided, takes priority over other auth methods.
87
86
  - `useLoggedInUser?: boolean` - Whether to use logged-in user for authentication (default: true, but false when `githubToken` is provided). Cannot be used with `cliUrl`.
88
87
 
@@ -426,6 +425,19 @@ defineTool("edit_file", {
426
425
  })
427
426
  ```
428
427
 
428
+ #### Skipping Permission Prompts
429
+
430
+ Set `skipPermission: true` on a tool definition to allow it to execute without triggering a permission prompt:
431
+
432
+ ```ts
433
+ defineTool("safe_lookup", {
434
+ description: "A read-only lookup that needs no confirmation",
435
+ parameters: z.object({ id: z.string() }),
436
+ skipPermission: true,
437
+ handler: async ({ id }) => { /* your logic */ },
438
+ })
439
+ ```
440
+
429
441
  ### System Message Customization
430
442
 
431
443
  Control the system prompt using `systemMessage` in session config:
package/dist/client.d.ts CHANGED
@@ -1,6 +1,39 @@
1
1
  import { createServerRpc } from "./generated/rpc.js";
2
2
  import { CopilotSession } from "./session.js";
3
3
  import type { ConnectionState, CopilotClientOptions, GetAuthStatusResponse, GetStatusResponse, ModelInfo, ResumeSessionConfig, SessionConfig, SessionLifecycleEventType, SessionLifecycleHandler, SessionListFilter, SessionMetadata, TypedSessionLifecycleHandler } from "./types.js";
4
+ /**
5
+ * Main client for interacting with the Copilot CLI.
6
+ *
7
+ * The CopilotClient manages the connection to the Copilot CLI server and provides
8
+ * methods to create and manage conversation sessions. It can either spawn a CLI
9
+ * server process or connect to an existing server.
10
+ *
11
+ * @example
12
+ * ```typescript
13
+ * import { CopilotClient } from "@github/copilot-sdk";
14
+ *
15
+ * // Create a client with default options (spawns CLI server)
16
+ * const client = new CopilotClient();
17
+ *
18
+ * // Or connect to an existing server
19
+ * const client = new CopilotClient({ cliUrl: "localhost:3000" });
20
+ *
21
+ * // Create a session
22
+ * const session = await client.createSession({ onPermissionRequest: approveAll, model: "gpt-4" });
23
+ *
24
+ * // Send messages and handle responses
25
+ * session.on((event) => {
26
+ * if (event.type === "assistant.message") {
27
+ * console.log(event.data.content);
28
+ * }
29
+ * });
30
+ * await session.send({ prompt: "Hello!" });
31
+ *
32
+ * // Clean up
33
+ * await session.disconnect();
34
+ * await client.stop();
35
+ * ```
36
+ */
4
37
  export declare class CopilotClient {
5
38
  private cliProcess;
6
39
  private connection;
@@ -13,6 +46,7 @@ export declare class CopilotClient {
13
46
  private options;
14
47
  private isExternalServer;
15
48
  private forceStopping;
49
+ private onListModels?;
16
50
  private modelsCache;
17
51
  private modelsCacheLock;
18
52
  private sessionLifecycleHandlers;
@@ -218,10 +252,13 @@ export declare class CopilotClient {
218
252
  /**
219
253
  * List available models with their metadata.
220
254
  *
255
+ * If an `onListModels` handler was provided in the client options,
256
+ * it is called instead of querying the CLI server.
257
+ *
221
258
  * Results are cached after the first successful call to avoid rate limiting.
222
259
  * The cache is cleared when the client disconnects.
223
260
  *
224
- * @throws Error if not authenticated
261
+ * @throws Error if not connected (when no custom handler is set)
225
262
  */
226
263
  listModels(): Promise<ModelInfo[]>;
227
264
  /**
@@ -397,8 +434,4 @@ export declare class CopilotClient {
397
434
  private handlePermissionRequestV2;
398
435
  private normalizeToolResultV2;
399
436
  private isToolResultObject;
400
- /**
401
- * Attempt to reconnect to the server
402
- */
403
- private reconnect;
404
437
  }
package/dist/client.js CHANGED
@@ -1,4 +1,5 @@
1
1
  import { spawn } from "node:child_process";
2
+ import { randomUUID } from "node:crypto";
2
3
  import { existsSync } from "node:fs";
3
4
  import { Socket } from "node:net";
4
5
  import { dirname, join } from "node:path";
@@ -10,7 +11,7 @@ import {
10
11
  } from "vscode-jsonrpc/node.js";
11
12
  import { createServerRpc } from "./generated/rpc.js";
12
13
  import { getSdkProtocolVersion } from "./sdkProtocolVersion.js";
13
- import { CopilotSession } from "./session.js";
14
+ import { CopilotSession, NO_RESULT_PERMISSION_V2_ERROR } from "./session.js";
14
15
  const MIN_PROTOCOL_VERSION = 2;
15
16
  function isZodSchema(value) {
16
17
  return value != null && typeof value === "object" && "toJSONSchema" in value && typeof value.toJSONSchema === "function";
@@ -46,6 +47,7 @@ class CopilotClient {
46
47
  options;
47
48
  isExternalServer = false;
48
49
  forceStopping = false;
50
+ onListModels;
49
51
  modelsCache = null;
50
52
  modelsCacheLock = Promise.resolve();
51
53
  sessionLifecycleHandlers = /* @__PURE__ */ new Set();
@@ -111,8 +113,9 @@ class CopilotClient {
111
113
  if (options.isChildProcess) {
112
114
  this.isExternalServer = true;
113
115
  }
116
+ this.onListModels = options.onListModels;
114
117
  this.options = {
115
- cliPath: options.cliPath || getBundledCliPath(),
118
+ cliPath: options.cliUrl ? void 0 : options.cliPath || getBundledCliPath(),
116
119
  cliArgs: options.cliArgs ?? [],
117
120
  cwd: options.cwd ?? process.cwd(),
118
121
  port: options.port || 0,
@@ -122,7 +125,7 @@ class CopilotClient {
122
125
  cliUrl: options.cliUrl,
123
126
  logLevel: options.logLevel || "debug",
124
127
  autoStart: options.autoStart ?? true,
125
- autoRestart: options.autoRestart ?? true,
128
+ autoRestart: false,
126
129
  env: options.env ?? process.env,
127
130
  githubToken: options.githubToken,
128
131
  // Default useLoggedInUser to false when githubToken is provided, otherwise true
@@ -378,36 +381,8 @@ class CopilotClient {
378
381
  throw new Error("Client not connected. Call start() first.");
379
382
  }
380
383
  }
381
- const response = await this.connection.sendRequest("session.create", {
382
- model: config.model,
383
- sessionId: config.sessionId,
384
- clientName: config.clientName,
385
- reasoningEffort: config.reasoningEffort,
386
- tools: config.tools?.map((tool) => ({
387
- name: tool.name,
388
- description: tool.description,
389
- parameters: toJsonSchema(tool.parameters),
390
- overridesBuiltInTool: tool.overridesBuiltInTool
391
- })),
392
- systemMessage: config.systemMessage,
393
- availableTools: config.availableTools,
394
- excludedTools: config.excludedTools,
395
- provider: config.provider,
396
- requestPermission: true,
397
- requestUserInput: !!config.onUserInputRequest,
398
- hooks: !!(config.hooks && Object.values(config.hooks).some(Boolean)),
399
- workingDirectory: config.workingDirectory,
400
- streaming: config.streaming,
401
- mcpServers: config.mcpServers,
402
- envValueMode: "direct",
403
- customAgents: config.customAgents,
404
- configDir: config.configDir,
405
- skillDirectories: config.skillDirectories,
406
- disabledSkills: config.disabledSkills,
407
- infiniteSessions: config.infiniteSessions
408
- });
409
- const { sessionId, workspacePath } = response;
410
- const session = new CopilotSession(sessionId, this.connection, workspacePath);
384
+ const sessionId = config.sessionId ?? randomUUID();
385
+ const session = new CopilotSession(sessionId, this.connection);
411
386
  session.registerTools(config.tools);
412
387
  session.registerPermissionHandler(config.onPermissionRequest);
413
388
  if (config.onUserInputRequest) {
@@ -416,7 +391,47 @@ class CopilotClient {
416
391
  if (config.hooks) {
417
392
  session.registerHooks(config.hooks);
418
393
  }
394
+ if (config.onEvent) {
395
+ session.on(config.onEvent);
396
+ }
419
397
  this.sessions.set(sessionId, session);
398
+ try {
399
+ const response = await this.connection.sendRequest("session.create", {
400
+ model: config.model,
401
+ sessionId,
402
+ clientName: config.clientName,
403
+ reasoningEffort: config.reasoningEffort,
404
+ tools: config.tools?.map((tool) => ({
405
+ name: tool.name,
406
+ description: tool.description,
407
+ parameters: toJsonSchema(tool.parameters),
408
+ overridesBuiltInTool: tool.overridesBuiltInTool,
409
+ skipPermission: tool.skipPermission
410
+ })),
411
+ systemMessage: config.systemMessage,
412
+ availableTools: config.availableTools,
413
+ excludedTools: config.excludedTools,
414
+ provider: config.provider,
415
+ requestPermission: true,
416
+ requestUserInput: !!config.onUserInputRequest,
417
+ hooks: !!(config.hooks && Object.values(config.hooks).some(Boolean)),
418
+ workingDirectory: config.workingDirectory,
419
+ streaming: config.streaming,
420
+ mcpServers: config.mcpServers,
421
+ envValueMode: "direct",
422
+ customAgents: config.customAgents,
423
+ agent: config.agent,
424
+ configDir: config.configDir,
425
+ skillDirectories: config.skillDirectories,
426
+ disabledSkills: config.disabledSkills,
427
+ infiniteSessions: config.infiniteSessions
428
+ });
429
+ const { workspacePath } = response;
430
+ session["_workspacePath"] = workspacePath;
431
+ } catch (e) {
432
+ this.sessions.delete(sessionId);
433
+ throw e;
434
+ }
420
435
  return session;
421
436
  }
422
437
  /**
@@ -456,37 +471,7 @@ class CopilotClient {
456
471
  throw new Error("Client not connected. Call start() first.");
457
472
  }
458
473
  }
459
- const response = await this.connection.sendRequest("session.resume", {
460
- sessionId,
461
- clientName: config.clientName,
462
- model: config.model,
463
- reasoningEffort: config.reasoningEffort,
464
- systemMessage: config.systemMessage,
465
- availableTools: config.availableTools,
466
- excludedTools: config.excludedTools,
467
- tools: config.tools?.map((tool) => ({
468
- name: tool.name,
469
- description: tool.description,
470
- parameters: toJsonSchema(tool.parameters),
471
- overridesBuiltInTool: tool.overridesBuiltInTool
472
- })),
473
- provider: config.provider,
474
- requestPermission: true,
475
- requestUserInput: !!config.onUserInputRequest,
476
- hooks: !!(config.hooks && Object.values(config.hooks).some(Boolean)),
477
- workingDirectory: config.workingDirectory,
478
- configDir: config.configDir,
479
- streaming: config.streaming,
480
- mcpServers: config.mcpServers,
481
- envValueMode: "direct",
482
- customAgents: config.customAgents,
483
- skillDirectories: config.skillDirectories,
484
- disabledSkills: config.disabledSkills,
485
- infiniteSessions: config.infiniteSessions,
486
- disableResume: config.disableResume
487
- });
488
- const { sessionId: resumedSessionId, workspacePath } = response;
489
- const session = new CopilotSession(resumedSessionId, this.connection, workspacePath);
474
+ const session = new CopilotSession(sessionId, this.connection);
490
475
  session.registerTools(config.tools);
491
476
  session.registerPermissionHandler(config.onPermissionRequest);
492
477
  if (config.onUserInputRequest) {
@@ -495,7 +480,48 @@ class CopilotClient {
495
480
  if (config.hooks) {
496
481
  session.registerHooks(config.hooks);
497
482
  }
498
- this.sessions.set(resumedSessionId, session);
483
+ if (config.onEvent) {
484
+ session.on(config.onEvent);
485
+ }
486
+ this.sessions.set(sessionId, session);
487
+ try {
488
+ const response = await this.connection.sendRequest("session.resume", {
489
+ sessionId,
490
+ clientName: config.clientName,
491
+ model: config.model,
492
+ reasoningEffort: config.reasoningEffort,
493
+ systemMessage: config.systemMessage,
494
+ availableTools: config.availableTools,
495
+ excludedTools: config.excludedTools,
496
+ tools: config.tools?.map((tool) => ({
497
+ name: tool.name,
498
+ description: tool.description,
499
+ parameters: toJsonSchema(tool.parameters),
500
+ overridesBuiltInTool: tool.overridesBuiltInTool,
501
+ skipPermission: tool.skipPermission
502
+ })),
503
+ provider: config.provider,
504
+ requestPermission: true,
505
+ requestUserInput: !!config.onUserInputRequest,
506
+ hooks: !!(config.hooks && Object.values(config.hooks).some(Boolean)),
507
+ workingDirectory: config.workingDirectory,
508
+ configDir: config.configDir,
509
+ streaming: config.streaming,
510
+ mcpServers: config.mcpServers,
511
+ envValueMode: "direct",
512
+ customAgents: config.customAgents,
513
+ agent: config.agent,
514
+ skillDirectories: config.skillDirectories,
515
+ disabledSkills: config.disabledSkills,
516
+ infiniteSessions: config.infiniteSessions,
517
+ disableResume: config.disableResume
518
+ });
519
+ const { workspacePath } = response;
520
+ session["_workspacePath"] = workspacePath;
521
+ } catch (e) {
522
+ this.sessions.delete(sessionId);
523
+ throw e;
524
+ }
499
525
  return session;
500
526
  }
501
527
  /**
@@ -556,15 +582,15 @@ class CopilotClient {
556
582
  /**
557
583
  * List available models with their metadata.
558
584
  *
585
+ * If an `onListModels` handler was provided in the client options,
586
+ * it is called instead of querying the CLI server.
587
+ *
559
588
  * Results are cached after the first successful call to avoid rate limiting.
560
589
  * The cache is cleared when the client disconnects.
561
590
  *
562
- * @throws Error if not authenticated
591
+ * @throws Error if not connected (when no custom handler is set)
563
592
  */
564
593
  async listModels() {
565
- if (!this.connection) {
566
- throw new Error("Client not connected");
567
- }
568
594
  await this.modelsCacheLock;
569
595
  let resolveLock;
570
596
  this.modelsCacheLock = new Promise((resolve) => {
@@ -574,10 +600,18 @@ class CopilotClient {
574
600
  if (this.modelsCache !== null) {
575
601
  return [...this.modelsCache];
576
602
  }
577
- const result = await this.connection.sendRequest("models.list", {});
578
- const response = result;
579
- const models = response.models;
580
- this.modelsCache = models;
603
+ let models;
604
+ if (this.onListModels) {
605
+ models = await this.onListModels();
606
+ } else {
607
+ if (!this.connection) {
608
+ throw new Error("Client not connected");
609
+ }
610
+ const result = await this.connection.sendRequest("models.list", {});
611
+ const response = result;
612
+ models = response.models;
613
+ }
614
+ this.modelsCache = [...models];
581
615
  return [...models];
582
616
  } finally {
583
617
  resolveLock();
@@ -790,6 +824,11 @@ class CopilotClient {
790
824
  if (this.options.githubToken) {
791
825
  envWithoutNodeDebug.COPILOT_SDK_AUTH_TOKEN = this.options.githubToken;
792
826
  }
827
+ if (!this.options.cliPath) {
828
+ throw new Error(
829
+ "Path to Copilot CLI is required. Please provide it via the cliPath option, or use cliUrl to rely on a remote CLI."
830
+ );
831
+ }
793
832
  if (!existsSync(this.options.cliPath)) {
794
833
  throw new Error(
795
834
  `Copilot CLI not found at ${this.options.cliPath}. Ensure @github/copilot is installed.`
@@ -889,8 +928,6 @@ stderr: ${stderrOutput}`
889
928
  } else {
890
929
  reject(new Error(`CLI server exited with code ${code}`));
891
930
  }
892
- } else if (this.options.autoRestart && this.state === "connected") {
893
- void this.reconnect();
894
931
  }
895
932
  });
896
933
  setTimeout(() => {
@@ -996,11 +1033,10 @@ stderr: ${stderrOutput}`
996
1033
  async (params) => await this.handleHooksInvoke(params)
997
1034
  );
998
1035
  this.connection.onClose(() => {
999
- if (this.state === "connected" && this.options.autoRestart) {
1000
- void this.reconnect();
1001
- }
1036
+ this.state = "disconnected";
1002
1037
  });
1003
1038
  this.connection.onError((_error) => {
1039
+ this.state = "disconnected";
1004
1040
  });
1005
1041
  }
1006
1042
  handleSessionEventNotification(notification) {
@@ -1121,7 +1157,10 @@ stderr: ${stderrOutput}`
1121
1157
  try {
1122
1158
  const result = await session._handlePermissionRequestV2(params.permissionRequest);
1123
1159
  return { result };
1124
- } catch (_error) {
1160
+ } catch (error) {
1161
+ if (error instanceof Error && error.message === NO_RESULT_PERMISSION_V2_ERROR) {
1162
+ throw error;
1163
+ }
1125
1164
  return {
1126
1165
  result: {
1127
1166
  kind: "denied-no-approval-rule-and-could-not-request-from-user"
@@ -1151,17 +1190,6 @@ stderr: ${stderrOutput}`
1151
1190
  isToolResultObject(value) {
1152
1191
  return typeof value === "object" && value !== null && "textResultForLlm" in value && typeof value.textResultForLlm === "string" && "resultType" in value;
1153
1192
  }
1154
- /**
1155
- * Attempt to reconnect to the server
1156
- */
1157
- async reconnect() {
1158
- this.state = "disconnected";
1159
- try {
1160
- await this.stop();
1161
- await this.start();
1162
- } catch (_error) {
1163
- }
1164
- }
1165
1193
  }
1166
1194
  export {
1167
1195
  CopilotClient
@@ -1,2 +1,19 @@
1
- import { CopilotClient } from "./client.js";
2
- export declare const extension: CopilotClient;
1
+ import type { CopilotSession } from "./session.js";
2
+ import type { PermissionHandler, ResumeSessionConfig } from "./types.js";
3
+ export type JoinSessionConfig = Omit<ResumeSessionConfig, "onPermissionRequest"> & {
4
+ onPermissionRequest?: PermissionHandler;
5
+ };
6
+ /**
7
+ * Joins the current foreground session.
8
+ *
9
+ * @param config - Configuration to add to the session
10
+ * @returns A promise that resolves with the joined session
11
+ *
12
+ * @example
13
+ * ```typescript
14
+ * import { joinSession } from "@github/copilot-sdk/extension";
15
+ *
16
+ * const session = await joinSession({ tools: [myTool] });
17
+ * ```
18
+ */
19
+ export declare function joinSession(config?: JoinSessionConfig): Promise<CopilotSession>;
package/dist/extension.js CHANGED
@@ -1,5 +1,21 @@
1
1
  import { CopilotClient } from "./client.js";
2
- const extension = new CopilotClient({ isChildProcess: true });
2
+ const defaultJoinSessionPermissionHandler = () => ({
3
+ kind: "no-result"
4
+ });
5
+ async function joinSession(config = {}) {
6
+ const sessionId = process.env.SESSION_ID;
7
+ if (!sessionId) {
8
+ throw new Error(
9
+ "joinSession() is intended for extensions running as child processes of the Copilot CLI."
10
+ );
11
+ }
12
+ const client = new CopilotClient({ isChildProcess: true });
13
+ return client.resumeSession(sessionId, {
14
+ ...config,
15
+ onPermissionRequest: config.onPermissionRequest ?? defaultJoinSessionPermissionHandler,
16
+ disableResume: config.disableResume ?? true
17
+ });
18
+ }
3
19
  export {
4
- extension
20
+ joinSession
5
21
  };
@@ -40,16 +40,34 @@ export interface ModelsListResult {
40
40
  * Model capabilities and limits
41
41
  */
42
42
  capabilities: {
43
+ /**
44
+ * Feature flags indicating what the model supports
45
+ */
43
46
  supports: {
47
+ /**
48
+ * Whether this model supports vision/image input
49
+ */
44
50
  vision?: boolean;
45
51
  /**
46
52
  * Whether this model supports reasoning effort configuration
47
53
  */
48
54
  reasoningEffort?: boolean;
49
55
  };
56
+ /**
57
+ * Token limits for prompts, outputs, and context window
58
+ */
50
59
  limits: {
60
+ /**
61
+ * Maximum number of prompt/input tokens
62
+ */
51
63
  max_prompt_tokens?: number;
64
+ /**
65
+ * Maximum number of output/completion tokens
66
+ */
52
67
  max_output_tokens?: number;
68
+ /**
69
+ * Maximum total context window size in tokens
70
+ */
53
71
  max_context_window_tokens: number;
54
72
  };
55
73
  };
@@ -57,13 +75,22 @@ export interface ModelsListResult {
57
75
  * Policy state (if applicable)
58
76
  */
59
77
  policy?: {
78
+ /**
79
+ * Current policy state for this model
80
+ */
60
81
  state: string;
82
+ /**
83
+ * Usage terms or conditions for this model
84
+ */
61
85
  terms: string;
62
86
  };
63
87
  /**
64
88
  * Billing information
65
89
  */
66
90
  billing?: {
91
+ /**
92
+ * Billing cost multiplier relative to the base rate
93
+ */
67
94
  multiplier: number;
68
95
  };
69
96
  /**
@@ -145,6 +172,9 @@ export interface AccountGetQuotaResult {
145
172
  };
146
173
  }
147
174
  export interface SessionModelGetCurrentResult {
175
+ /**
176
+ * Currently active model identifier
177
+ */
148
178
  modelId?: string;
149
179
  }
150
180
  export interface SessionModelGetCurrentParams {
@@ -154,6 +184,9 @@ export interface SessionModelGetCurrentParams {
154
184
  sessionId: string;
155
185
  }
156
186
  export interface SessionModelSwitchToResult {
187
+ /**
188
+ * Currently active model identifier after the switch
189
+ */
157
190
  modelId?: string;
158
191
  }
159
192
  export interface SessionModelSwitchToParams {
@@ -161,7 +194,14 @@ export interface SessionModelSwitchToParams {
161
194
  * Target session identifier
162
195
  */
163
196
  sessionId: string;
197
+ /**
198
+ * Model identifier to switch to
199
+ */
164
200
  modelId: string;
201
+ /**
202
+ * Reasoning effort level to use for the model
203
+ */
204
+ reasoningEffort?: string;
165
205
  }
166
206
  export interface SessionModeGetResult {
167
207
  /**
@@ -399,6 +439,9 @@ export interface SessionCompactionCompactParams {
399
439
  sessionId: string;
400
440
  }
401
441
  export interface SessionToolsHandlePendingToolCallResult {
442
+ /**
443
+ * Whether the tool call result was handled successfully
444
+ */
402
445
  success: boolean;
403
446
  }
404
447
  export interface SessionToolsHandlePendingToolCallParams {
@@ -418,6 +461,9 @@ export interface SessionToolsHandlePendingToolCallParams {
418
461
  error?: string;
419
462
  }
420
463
  export interface SessionPermissionsHandlePendingPermissionRequestResult {
464
+ /**
465
+ * Whether the permission request was handled successfully
466
+ */
421
467
  success: boolean;
422
468
  }
423
469
  export interface SessionPermissionsHandlePendingPermissionRequestParams {
@@ -442,6 +488,74 @@ export interface SessionPermissionsHandlePendingPermissionRequestParams {
442
488
  message: string;
443
489
  };
444
490
  }
491
+ export interface SessionLogResult {
492
+ /**
493
+ * The unique identifier of the emitted session event
494
+ */
495
+ eventId: string;
496
+ }
497
+ export interface SessionLogParams {
498
+ /**
499
+ * Target session identifier
500
+ */
501
+ sessionId: string;
502
+ /**
503
+ * Human-readable message
504
+ */
505
+ message: string;
506
+ /**
507
+ * Log severity level. Determines how the message is displayed in the timeline. Defaults to "info".
508
+ */
509
+ level?: "info" | "warning" | "error";
510
+ /**
511
+ * When true, the message is transient and not persisted to the session event log on disk
512
+ */
513
+ ephemeral?: boolean;
514
+ }
515
+ export interface SessionShellExecResult {
516
+ /**
517
+ * Unique identifier for tracking streamed output
518
+ */
519
+ processId: string;
520
+ }
521
+ export interface SessionShellExecParams {
522
+ /**
523
+ * Target session identifier
524
+ */
525
+ sessionId: string;
526
+ /**
527
+ * Shell command to execute
528
+ */
529
+ command: string;
530
+ /**
531
+ * Working directory (defaults to session working directory)
532
+ */
533
+ cwd?: string;
534
+ /**
535
+ * Timeout in milliseconds (default: 30000)
536
+ */
537
+ timeout?: number;
538
+ }
539
+ export interface SessionShellKillResult {
540
+ /**
541
+ * Whether the signal was sent successfully
542
+ */
543
+ killed: boolean;
544
+ }
545
+ export interface SessionShellKillParams {
546
+ /**
547
+ * Target session identifier
548
+ */
549
+ sessionId: string;
550
+ /**
551
+ * Process identifier returned by shell.exec
552
+ */
553
+ processId: string;
554
+ /**
555
+ * Signal to send (default: SIGTERM)
556
+ */
557
+ signal?: "SIGTERM" | "SIGKILL" | "SIGINT";
558
+ }
445
559
  /** Create typed server-scoped RPC methods (no session required). */
446
560
  export declare function createServerRpc(connection: MessageConnection): {
447
561
  ping: (params: PingParams) => Promise<PingResult>;
@@ -493,4 +607,9 @@ export declare function createSessionRpc(connection: MessageConnection, sessionI
493
607
  permissions: {
494
608
  handlePendingPermissionRequest: (params: Omit<SessionPermissionsHandlePendingPermissionRequestParams, "sessionId">) => Promise<SessionPermissionsHandlePendingPermissionRequestResult>;
495
609
  };
610
+ log: (params: Omit<SessionLogParams, "sessionId">) => Promise<SessionLogResult>;
611
+ shell: {
612
+ exec: (params: Omit<SessionShellExecParams, "sessionId">) => Promise<SessionShellExecResult>;
613
+ kill: (params: Omit<SessionShellKillParams, "sessionId">) => Promise<SessionShellKillResult>;
614
+ };
496
615
  };
@@ -49,6 +49,11 @@ function createSessionRpc(connection, sessionId) {
49
49
  },
50
50
  permissions: {
51
51
  handlePendingPermissionRequest: async (params) => connection.sendRequest("session.permissions.handlePendingPermissionRequest", { sessionId, ...params })
52
+ },
53
+ log: async (params) => connection.sendRequest("session.log", { sessionId, ...params }),
54
+ shell: {
55
+ exec: async (params) => connection.sendRequest("session.shell.exec", { sessionId, ...params }),
56
+ kill: async (params) => connection.sendRequest("session.shell.kill", { sessionId, ...params })
52
57
  }
53
58
  };
54
59
  }