@github/copilot-sdk 0.1.30 → 0.1.31-unstable.0

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/dist/client.d.ts CHANGED
@@ -361,9 +361,13 @@ export declare class CopilotClient {
361
361
  */
362
362
  private connectToServer;
363
363
  /**
364
- * Connect via stdio pipes
364
+ * Connect to child via stdio pipes
365
365
  */
366
- private connectViaStdio;
366
+ private connectToChildProcessViaStdio;
367
+ /**
368
+ * Connect to parent via stdio pipes
369
+ */
370
+ private connectToParentProcessViaStdio;
367
371
  /**
368
372
  * Connect to the CLI server via TCP socket
369
373
  */
@@ -371,14 +375,8 @@ export declare class CopilotClient {
371
375
  private attachConnectionHandlers;
372
376
  private handleSessionEventNotification;
373
377
  private handleSessionLifecycleNotification;
374
- private handleToolCallRequest;
375
- private executeToolCall;
376
- private handlePermissionRequest;
377
378
  private handleUserInputRequest;
378
379
  private handleHooksInvoke;
379
- private normalizeToolResult;
380
- private isToolResultObject;
381
- private buildUnsupportedToolResult;
382
380
  /**
383
381
  * Attempt to reconnect to the server
384
382
  */
package/dist/client.js CHANGED
@@ -90,6 +90,11 @@ class CopilotClient {
90
90
  if (options.cliUrl && (options.useStdio === true || options.cliPath)) {
91
91
  throw new Error("cliUrl is mutually exclusive with useStdio and cliPath");
92
92
  }
93
+ if (options.isChildProcess && (options.cliUrl || options.useStdio === false)) {
94
+ throw new Error(
95
+ "isChildProcess must be used in conjunction with useStdio and not with cliUrl"
96
+ );
97
+ }
93
98
  if (options.cliUrl && (options.githubToken || options.useLoggedInUser !== void 0)) {
94
99
  throw new Error(
95
100
  "githubToken and useLoggedInUser cannot be used with cliUrl (external server manages its own auth)"
@@ -101,6 +106,9 @@ class CopilotClient {
101
106
  this.actualPort = port;
102
107
  this.isExternalServer = true;
103
108
  }
109
+ if (options.isChildProcess) {
110
+ this.isExternalServer = true;
111
+ }
104
112
  this.options = {
105
113
  cliPath: options.cliPath || getBundledCliPath(),
106
114
  cliArgs: options.cliArgs ?? [],
@@ -108,6 +116,7 @@ class CopilotClient {
108
116
  port: options.port || 0,
109
117
  useStdio: options.cliUrl ? false : options.useStdio ?? true,
110
118
  // Default to stdio unless cliUrl is provided
119
+ isChildProcess: options.isChildProcess ?? false,
111
120
  cliUrl: options.cliUrl,
112
121
  logLevel: options.logLevel || "debug",
113
122
  autoStart: options.autoStart ?? true,
@@ -886,16 +895,18 @@ stderr: ${stderrOutput}`
886
895
  * Connect to the CLI server (via socket or stdio)
887
896
  */
888
897
  async connectToServer() {
889
- if (this.options.useStdio) {
890
- return this.connectViaStdio();
898
+ if (this.options.isChildProcess) {
899
+ return this.connectToParentProcessViaStdio();
900
+ } else if (this.options.useStdio) {
901
+ return this.connectToChildProcessViaStdio();
891
902
  } else {
892
903
  return this.connectViaTcp();
893
904
  }
894
905
  }
895
906
  /**
896
- * Connect via stdio pipes
907
+ * Connect to child via stdio pipes
897
908
  */
898
- async connectViaStdio() {
909
+ async connectToChildProcessViaStdio() {
899
910
  if (!this.cliProcess) {
900
911
  throw new Error("CLI process not started");
901
912
  }
@@ -911,6 +922,20 @@ stderr: ${stderrOutput}`
911
922
  this.attachConnectionHandlers();
912
923
  this.connection.listen();
913
924
  }
925
+ /**
926
+ * Connect to parent via stdio pipes
927
+ */
928
+ async connectToParentProcessViaStdio() {
929
+ if (this.cliProcess) {
930
+ throw new Error("CLI child process was unexpectedly started in parent process mode");
931
+ }
932
+ this.connection = createMessageConnection(
933
+ new StreamMessageReader(process.stdin),
934
+ new StreamMessageWriter(process.stdout)
935
+ );
936
+ this.attachConnectionHandlers();
937
+ this.connection.listen();
938
+ }
914
939
  /**
915
940
  * Connect to the CLI server via TCP socket
916
941
  */
@@ -944,14 +969,6 @@ stderr: ${stderrOutput}`
944
969
  this.connection.onNotification("session.lifecycle", (notification) => {
945
970
  this.handleSessionLifecycleNotification(notification);
946
971
  });
947
- this.connection.onRequest(
948
- "tool.call",
949
- async (params) => await this.handleToolCallRequest(params)
950
- );
951
- this.connection.onRequest(
952
- "permission.request",
953
- async (params) => await this.handlePermissionRequest(params)
954
- );
955
972
  this.connection.onRequest(
956
973
  "userInput.request",
957
974
  async (params) => await this.handleUserInputRequest(params)
@@ -998,62 +1015,6 @@ stderr: ${stderrOutput}`
998
1015
  }
999
1016
  }
1000
1017
  }
1001
- async handleToolCallRequest(params) {
1002
- if (!params || typeof params.sessionId !== "string" || typeof params.toolCallId !== "string" || typeof params.toolName !== "string") {
1003
- throw new Error("Invalid tool call payload");
1004
- }
1005
- const session = this.sessions.get(params.sessionId);
1006
- if (!session) {
1007
- throw new Error(`Unknown session ${params.sessionId}`);
1008
- }
1009
- const handler = session.getToolHandler(params.toolName);
1010
- if (!handler) {
1011
- return { result: this.buildUnsupportedToolResult(params.toolName) };
1012
- }
1013
- return await this.executeToolCall(handler, params);
1014
- }
1015
- async executeToolCall(handler, request) {
1016
- try {
1017
- const invocation = {
1018
- sessionId: request.sessionId,
1019
- toolCallId: request.toolCallId,
1020
- toolName: request.toolName,
1021
- arguments: request.arguments
1022
- };
1023
- const result = await handler(request.arguments, invocation);
1024
- return { result: this.normalizeToolResult(result) };
1025
- } catch (error) {
1026
- const message = error instanceof Error ? error.message : String(error);
1027
- return {
1028
- result: {
1029
- // Don't expose detailed error information to the LLM for security reasons
1030
- textResultForLlm: "Invoking this tool produced an error. Detailed information is not available.",
1031
- resultType: "failure",
1032
- error: message,
1033
- toolTelemetry: {}
1034
- }
1035
- };
1036
- }
1037
- }
1038
- async handlePermissionRequest(params) {
1039
- if (!params || typeof params.sessionId !== "string" || !params.permissionRequest) {
1040
- throw new Error("Invalid permission request payload");
1041
- }
1042
- const session = this.sessions.get(params.sessionId);
1043
- if (!session) {
1044
- throw new Error(`Session not found: ${params.sessionId}`);
1045
- }
1046
- try {
1047
- const result = await session._handlePermissionRequest(params.permissionRequest);
1048
- return { result };
1049
- } catch (_error) {
1050
- return {
1051
- result: {
1052
- kind: "denied-no-approval-rule-and-could-not-request-from-user"
1053
- }
1054
- };
1055
- }
1056
- }
1057
1018
  async handleUserInputRequest(params) {
1058
1019
  if (!params || typeof params.sessionId !== "string" || typeof params.question !== "string") {
1059
1020
  throw new Error("Invalid user input request payload");
@@ -1080,36 +1041,6 @@ stderr: ${stderrOutput}`
1080
1041
  const output = await session._handleHooksInvoke(params.hookType, params.input);
1081
1042
  return { output };
1082
1043
  }
1083
- normalizeToolResult(result) {
1084
- if (result === void 0 || result === null) {
1085
- return {
1086
- textResultForLlm: "Tool returned no result",
1087
- resultType: "failure",
1088
- error: "tool returned no result",
1089
- toolTelemetry: {}
1090
- };
1091
- }
1092
- if (this.isToolResultObject(result)) {
1093
- return result;
1094
- }
1095
- const textResult = typeof result === "string" ? result : JSON.stringify(result);
1096
- return {
1097
- textResultForLlm: textResult,
1098
- resultType: "success",
1099
- toolTelemetry: {}
1100
- };
1101
- }
1102
- isToolResultObject(value) {
1103
- return typeof value === "object" && value !== null && "textResultForLlm" in value && typeof value.textResultForLlm === "string" && "resultType" in value;
1104
- }
1105
- buildUnsupportedToolResult(toolName) {
1106
- return {
1107
- textResultForLlm: `Tool '${toolName}' is not supported by this client instance.`,
1108
- resultType: "failure",
1109
- error: `tool '${toolName}' not supported`,
1110
- toolTelemetry: {}
1111
- };
1112
- }
1113
1044
  /**
1114
1045
  * Attempt to reconnect to the server
1115
1046
  */
@@ -0,0 +1,2 @@
1
+ import { CopilotClient } from "./client.js";
2
+ export declare const extension: CopilotClient;
@@ -0,0 +1,5 @@
1
+ import { CopilotClient } from "./client.js";
2
+ const extension = new CopilotClient({ isChildProcess: true });
3
+ export {
4
+ extension
5
+ };
@@ -193,13 +193,17 @@ export interface SessionModeSetParams {
193
193
  }
194
194
  export interface SessionPlanReadResult {
195
195
  /**
196
- * Whether plan.md exists in the workspace
196
+ * Whether the plan file exists in the workspace
197
197
  */
198
198
  exists: boolean;
199
199
  /**
200
- * The content of plan.md, or null if it does not exist
200
+ * The content of the plan file, or null if it does not exist
201
201
  */
202
202
  content: string | null;
203
+ /**
204
+ * Absolute file path of the plan file, or null if workspace is not enabled
205
+ */
206
+ path: string | null;
203
207
  }
204
208
  export interface SessionPlanReadParams {
205
209
  /**
@@ -215,7 +219,7 @@ export interface SessionPlanUpdateParams {
215
219
  */
216
220
  sessionId: string;
217
221
  /**
218
- * The new content for plan.md
222
+ * The new content for the plan file
219
223
  */
220
224
  content: string;
221
225
  }
@@ -394,6 +398,32 @@ export interface SessionCompactionCompactParams {
394
398
  */
395
399
  sessionId: string;
396
400
  }
401
+ export interface SessionToolsHandlePendingToolCallResult {
402
+ success: boolean;
403
+ }
404
+ export interface SessionToolsHandlePendingToolCallParams {
405
+ /**
406
+ * Target session identifier
407
+ */
408
+ sessionId: string;
409
+ requestId: string;
410
+ result?: string;
411
+ error?: string;
412
+ }
413
+ export interface SessionPermissionsHandlePendingPermissionRequestResult {
414
+ success: boolean;
415
+ }
416
+ export interface SessionPermissionsHandlePendingPermissionRequestParams {
417
+ /**
418
+ * Target session identifier
419
+ */
420
+ sessionId: string;
421
+ requestId: string;
422
+ result: {
423
+ kind: "approved" | "denied-by-rules" | "denied-no-approval-rule-and-could-not-request-from-user" | "denied-interactively-by-user";
424
+ rules?: unknown[];
425
+ };
426
+ }
397
427
  /** Create typed server-scoped RPC methods (no session required). */
398
428
  export declare function createServerRpc(connection: MessageConnection): {
399
429
  ping: (params: PingParams) => Promise<PingResult>;
@@ -439,4 +469,10 @@ export declare function createSessionRpc(connection: MessageConnection, sessionI
439
469
  compaction: {
440
470
  compact: () => Promise<SessionCompactionCompactResult>;
441
471
  };
472
+ tools: {
473
+ handlePendingToolCall: (params: Omit<SessionToolsHandlePendingToolCallParams, "sessionId">) => Promise<SessionToolsHandlePendingToolCallResult>;
474
+ };
475
+ permissions: {
476
+ handlePendingPermissionRequest: (params: Omit<SessionPermissionsHandlePendingPermissionRequestParams, "sessionId">) => Promise<SessionPermissionsHandlePendingPermissionRequestResult>;
477
+ };
442
478
  };
@@ -43,6 +43,12 @@ function createSessionRpc(connection, sessionId) {
43
43
  },
44
44
  compaction: {
45
45
  compact: async () => connection.sendRequest("session.compaction.compact", { sessionId })
46
+ },
47
+ tools: {
48
+ handlePendingToolCall: async (params) => connection.sendRequest("session.tools.handlePendingToolCall", { sessionId, ...params })
49
+ },
50
+ permissions: {
51
+ handlePendingPermissionRequest: async (params) => connection.sendRequest("session.permissions.handlePendingPermissionRequest", { sessionId, ...params })
46
52
  }
47
53
  };
48
54
  }