@github/copilot-sdk
Advanced tools
+2
-0
@@ -12,2 +12,3 @@ import { createServerRpc } from "./generated/rpc.js"; | ||
| private sessions; | ||
| private stderrBuffer; | ||
| private options; | ||
@@ -21,2 +22,3 @@ private isExternalServer; | ||
| private _rpc; | ||
| private processExitPromise; | ||
| /** | ||
@@ -23,0 +25,0 @@ * Typed server-scoped RPC methods. |
+61
-3
@@ -37,2 +37,4 @@ import { spawn } from "node:child_process"; | ||
| sessions = /* @__PURE__ */ new Map(); | ||
| stderrBuffer = ""; | ||
| // Captures CLI stderr for error messages | ||
| options; | ||
@@ -46,2 +48,4 @@ isExternalServer = false; | ||
| _rpc = null; | ||
| processExitPromise = null; | ||
| // Rejects when CLI process exits | ||
| /** | ||
@@ -256,2 +260,4 @@ * Typed server-scoped RPC methods. | ||
| this.actualPort = null; | ||
| this.stderrBuffer = ""; | ||
| this.processExitPromise = null; | ||
| return errors; | ||
@@ -312,2 +318,4 @@ } | ||
| this.actualPort = null; | ||
| this.stderrBuffer = ""; | ||
| this.processExitPromise = null; | ||
| } | ||
@@ -369,2 +377,3 @@ /** | ||
| mcpServers: config.mcpServers, | ||
| envValueMode: "direct", | ||
| customAgents: config.customAgents, | ||
@@ -442,2 +451,3 @@ configDir: config.configDir, | ||
| mcpServers: config.mcpServers, | ||
| envValueMode: "direct", | ||
| customAgents: config.customAgents, | ||
@@ -554,3 +564,8 @@ skillDirectories: config.skillDirectories, | ||
| const expectedVersion = getSdkProtocolVersion(); | ||
| const pingResult = await this.ping(); | ||
| let pingResult; | ||
| if (this.processExitPromise) { | ||
| pingResult = await Promise.race([this.ping(), this.processExitPromise]); | ||
| } else { | ||
| pingResult = await this.ping(); | ||
| } | ||
| const serverVersion = pingResult.protocolVersion; | ||
@@ -724,2 +739,3 @@ if (serverVersion === void 0) { | ||
| return new Promise((resolve, reject) => { | ||
| this.stderrBuffer = ""; | ||
| const args = [ | ||
@@ -787,2 +803,3 @@ ...this.options.cliArgs, | ||
| this.cliProcess.stderr?.on("data", (data) => { | ||
| this.stderrBuffer += data.toString(); | ||
| const lines = data.toString().split("\n"); | ||
@@ -799,9 +816,50 @@ for (const line of lines) { | ||
| resolved = true; | ||
| reject(new Error(`Failed to start CLI server: ${error.message}`)); | ||
| const stderrOutput = this.stderrBuffer.trim(); | ||
| if (stderrOutput) { | ||
| reject( | ||
| new Error( | ||
| `Failed to start CLI server: ${error.message} | ||
| stderr: ${stderrOutput}` | ||
| ) | ||
| ); | ||
| } else { | ||
| reject(new Error(`Failed to start CLI server: ${error.message}`)); | ||
| } | ||
| } | ||
| }); | ||
| this.processExitPromise = new Promise((_, rejectProcessExit) => { | ||
| this.cliProcess.on("exit", (code) => { | ||
| setTimeout(() => { | ||
| const stderrOutput = this.stderrBuffer.trim(); | ||
| if (stderrOutput) { | ||
| rejectProcessExit( | ||
| new Error( | ||
| `CLI server exited with code ${code} | ||
| stderr: ${stderrOutput}` | ||
| ) | ||
| ); | ||
| } else { | ||
| rejectProcessExit( | ||
| new Error(`CLI server exited unexpectedly with code ${code}`) | ||
| ); | ||
| } | ||
| }, 50); | ||
| }); | ||
| }); | ||
| this.processExitPromise.catch(() => { | ||
| }); | ||
| this.cliProcess.on("exit", (code) => { | ||
| if (!resolved) { | ||
| resolved = true; | ||
| reject(new Error(`CLI server exited with code ${code}`)); | ||
| const stderrOutput = this.stderrBuffer.trim(); | ||
| if (stderrOutput) { | ||
| reject( | ||
| new Error( | ||
| `CLI server exited with code ${code} | ||
| stderr: ${stderrOutput}` | ||
| ) | ||
| ); | ||
| } else { | ||
| reject(new Error(`CLI server exited with code ${code}`)); | ||
| } | ||
| } else if (this.options.autoRestart && this.state === "connected") { | ||
@@ -808,0 +866,0 @@ void this.reconnect(); |
+141
-0
@@ -166,2 +166,126 @@ /** | ||
| } | ||
| export interface SessionModeGetResult { | ||
| /** | ||
| * The current agent mode. | ||
| */ | ||
| mode: "interactive" | "plan" | "autopilot"; | ||
| } | ||
| export interface SessionModeGetParams { | ||
| /** | ||
| * Target session identifier | ||
| */ | ||
| sessionId: string; | ||
| } | ||
| export interface SessionModeSetResult { | ||
| /** | ||
| * The agent mode after switching. | ||
| */ | ||
| mode: "interactive" | "plan" | "autopilot"; | ||
| } | ||
| export interface SessionModeSetParams { | ||
| /** | ||
| * Target session identifier | ||
| */ | ||
| sessionId: string; | ||
| /** | ||
| * The mode to switch to. Valid values: "interactive", "plan", "autopilot". | ||
| */ | ||
| mode: "interactive" | "plan" | "autopilot"; | ||
| } | ||
| export interface SessionPlanReadResult { | ||
| /** | ||
| * Whether plan.md exists in the workspace | ||
| */ | ||
| exists: boolean; | ||
| /** | ||
| * The content of plan.md, or null if it does not exist | ||
| */ | ||
| content: string | null; | ||
| } | ||
| export interface SessionPlanReadParams { | ||
| /** | ||
| * Target session identifier | ||
| */ | ||
| sessionId: string; | ||
| } | ||
| export interface SessionPlanUpdateResult { | ||
| } | ||
| export interface SessionPlanUpdateParams { | ||
| /** | ||
| * Target session identifier | ||
| */ | ||
| sessionId: string; | ||
| /** | ||
| * The new content for plan.md | ||
| */ | ||
| content: string; | ||
| } | ||
| export interface SessionPlanDeleteResult { | ||
| } | ||
| export interface SessionPlanDeleteParams { | ||
| /** | ||
| * Target session identifier | ||
| */ | ||
| sessionId: string; | ||
| } | ||
| export interface SessionWorkspaceListFilesResult { | ||
| /** | ||
| * Relative file paths in the workspace files directory | ||
| */ | ||
| files: string[]; | ||
| } | ||
| export interface SessionWorkspaceListFilesParams { | ||
| /** | ||
| * Target session identifier | ||
| */ | ||
| sessionId: string; | ||
| } | ||
| export interface SessionWorkspaceReadFileResult { | ||
| /** | ||
| * File content as a UTF-8 string | ||
| */ | ||
| content: string; | ||
| } | ||
| export interface SessionWorkspaceReadFileParams { | ||
| /** | ||
| * Target session identifier | ||
| */ | ||
| sessionId: string; | ||
| /** | ||
| * Relative path within the workspace files directory | ||
| */ | ||
| path: string; | ||
| } | ||
| export interface SessionWorkspaceCreateFileResult { | ||
| } | ||
| export interface SessionWorkspaceCreateFileParams { | ||
| /** | ||
| * Target session identifier | ||
| */ | ||
| sessionId: string; | ||
| /** | ||
| * Relative path within the workspace files directory | ||
| */ | ||
| path: string; | ||
| /** | ||
| * File content to write as a UTF-8 string | ||
| */ | ||
| content: string; | ||
| } | ||
| export interface SessionFleetStartResult { | ||
| /** | ||
| * Whether fleet mode was successfully activated | ||
| */ | ||
| started: boolean; | ||
| } | ||
| export interface SessionFleetStartParams { | ||
| /** | ||
| * Target session identifier | ||
| */ | ||
| sessionId: string; | ||
| /** | ||
| * Optional user prompt to combine with fleet instructions | ||
| */ | ||
| prompt?: string; | ||
| } | ||
| /** Create typed server-scoped RPC methods (no session required). */ | ||
@@ -186,2 +310,19 @@ export declare function createServerRpc(connection: MessageConnection): { | ||
| }; | ||
| mode: { | ||
| get: () => Promise<SessionModeGetResult>; | ||
| set: (params: Omit<SessionModeSetParams, "sessionId">) => Promise<SessionModeSetResult>; | ||
| }; | ||
| plan: { | ||
| read: () => Promise<SessionPlanReadResult>; | ||
| update: (params: Omit<SessionPlanUpdateParams, "sessionId">) => Promise<SessionPlanUpdateResult>; | ||
| delete: () => Promise<SessionPlanDeleteResult>; | ||
| }; | ||
| workspace: { | ||
| listFiles: () => Promise<SessionWorkspaceListFilesResult>; | ||
| readFile: (params: Omit<SessionWorkspaceReadFileParams, "sessionId">) => Promise<SessionWorkspaceReadFileResult>; | ||
| createFile: (params: Omit<SessionWorkspaceCreateFileParams, "sessionId">) => Promise<SessionWorkspaceCreateFileResult>; | ||
| }; | ||
| fleet: { | ||
| start: (params: Omit<SessionFleetStartParams, "sessionId">) => Promise<SessionFleetStartResult>; | ||
| }; | ||
| }; |
@@ -20,2 +20,19 @@ function createServerRpc(connection) { | ||
| switchTo: async (params) => connection.sendRequest("session.model.switchTo", { sessionId, ...params }) | ||
| }, | ||
| mode: { | ||
| get: async () => connection.sendRequest("session.mode.get", { sessionId }), | ||
| set: async (params) => connection.sendRequest("session.mode.set", { sessionId, ...params }) | ||
| }, | ||
| plan: { | ||
| read: async () => connection.sendRequest("session.plan.read", { sessionId }), | ||
| update: async (params) => connection.sendRequest("session.plan.update", { sessionId, ...params }), | ||
| delete: async () => connection.sendRequest("session.plan.delete", { sessionId }) | ||
| }, | ||
| workspace: { | ||
| listFiles: async () => connection.sendRequest("session.workspace.listFiles", { sessionId }), | ||
| readFile: async (params) => connection.sendRequest("session.workspace.readFile", { sessionId, ...params }), | ||
| createFile: async (params) => connection.sendRequest("session.workspace.createFile", { sessionId, ...params }) | ||
| }, | ||
| fleet: { | ||
| start: async (params) => connection.sendRequest("session.fleet.start", { sessionId, ...params }) | ||
| } | ||
@@ -22,0 +39,0 @@ }; |
@@ -105,2 +105,34 @@ /** | ||
| ephemeral?: boolean; | ||
| type: "session.mode_changed"; | ||
| data: { | ||
| previousMode: string; | ||
| newMode: string; | ||
| }; | ||
| } | { | ||
| id: string; | ||
| timestamp: string; | ||
| parentId: string | null; | ||
| ephemeral?: boolean; | ||
| type: "session.plan_changed"; | ||
| data: { | ||
| operation: "create" | "update" | "delete"; | ||
| }; | ||
| } | { | ||
| id: string; | ||
| timestamp: string; | ||
| parentId: string | null; | ||
| ephemeral?: boolean; | ||
| type: "session.workspace_file_changed"; | ||
| data: { | ||
| /** | ||
| * Relative path within the workspace files directory | ||
| */ | ||
| path: string; | ||
| operation: "create" | "update"; | ||
| }; | ||
| } | { | ||
| id: string; | ||
| timestamp: string; | ||
| parentId: string | null; | ||
| ephemeral?: boolean; | ||
| type: "session.handoff"; | ||
@@ -107,0 +139,0 @@ data: { |
+2
-2
@@ -7,3 +7,3 @@ { | ||
| }, | ||
| "version": "0.1.24", | ||
| "version": "0.1.25-preview.0", | ||
| "description": "TypeScript SDK for programmatic control of GitHub Copilot CLI via JSON-RPC", | ||
@@ -44,3 +44,3 @@ "main": "./dist/index.js", | ||
| "dependencies": { | ||
| "@github/copilot": "^0.0.409", | ||
| "@github/copilot": "^0.0.411-1", | ||
| "vscode-jsonrpc": "^8.2.1", | ||
@@ -47,0 +47,0 @@ "zod": "^4.3.6" |
+13
-0
@@ -13,2 +13,15 @@ # Copilot SDK for Node.js/TypeScript | ||
| ## Run the Sample | ||
| Try the interactive chat sample (from the repo root): | ||
| ```bash | ||
| cd nodejs | ||
| npm ci | ||
| npm run build | ||
| cd samples | ||
| npm install | ||
| npm start | ||
| ``` | ||
| ## Quick Start | ||
@@ -15,0 +28,0 @@ |
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
Found 1 instance in 1 package
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
Found 1 instance in 1 package
149687
5.11%4086
6.52%682
1.94%+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
Updated