🚀 Socket Launch Week Day 5:Introducing Repository Access Permissions and Custom Roles.Learn more
Sign In

@github/copilot-sdk

Package Overview
Dependencies
Maintainers
20
Versions
71
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@github/copilot-sdk - npm Package Compare versions

Comparing version
0.1.11
to
0.1.12
+306
dist/client.d.ts
import { CopilotSession } from "./session.js";
import type { ConnectionState, CopilotClientOptions, ResumeSessionConfig, SessionConfig, SessionMetadata } from "./types.js";
/**
* Main client for interacting with the Copilot CLI.
*
* The CopilotClient manages the connection to the Copilot CLI server and provides
* methods to create and manage conversation sessions. It can either spawn a CLI
* server process or connect to an existing server.
*
* @example
* ```typescript
* import { CopilotClient } from "@github/copilot-sdk";
*
* // Create a client with default options (spawns CLI server)
* const client = new CopilotClient();
*
* // Or connect to an existing server
* const client = new CopilotClient({ cliUrl: "localhost:3000" });
*
* // Create a session
* const session = await client.createSession({ model: "gpt-4" });
*
* // Send messages and handle responses
* session.on((event) => {
* if (event.type === "assistant.message") {
* console.log(event.data.content);
* }
* });
* await session.send({ prompt: "Hello!" });
*
* // Clean up
* await session.destroy();
* await client.stop();
* ```
*/
export declare class CopilotClient {
private cliProcess;
private connection;
private socket;
private actualPort;
private actualHost;
private state;
private sessions;
private options;
private isExternalServer;
private forceStopping;
/**
* Creates a new CopilotClient instance.
*
* @param options - Configuration options for the client
* @throws Error if mutually exclusive options are provided (e.g., cliUrl with useStdio or cliPath)
*
* @example
* ```typescript
* // Default options - spawns CLI server using stdio
* const client = new CopilotClient();
*
* // Connect to an existing server
* const client = new CopilotClient({ cliUrl: "localhost:3000" });
*
* // Custom CLI path with specific log level
* const client = new CopilotClient({
* cliPath: "/usr/local/bin/copilot",
* logLevel: "debug"
* });
* ```
*/
constructor(options?: CopilotClientOptions);
/**
* Parse CLI URL into host and port
* Supports formats: "host:port", "http://host:port", "https://host:port", or just "port"
*/
private parseCliUrl;
/**
* Starts the CLI server and establishes a connection.
*
* If connecting to an external server (via cliUrl), only establishes the connection.
* Otherwise, spawns the CLI server process and then connects.
*
* This method is called automatically when creating a session if `autoStart` is true (default).
*
* @returns A promise that resolves when the connection is established
* @throws Error if the server fails to start or the connection fails
*
* @example
* ```typescript
* const client = new CopilotClient({ autoStart: false });
* await client.start();
* // Now ready to create sessions
* ```
*/
start(): Promise<void>;
/**
* Stops the CLI server and closes all active sessions.
*
* This method performs graceful cleanup:
* 1. Destroys all active sessions with retry logic
* 2. Closes the JSON-RPC connection
* 3. Terminates the CLI server process (if spawned by this client)
*
* @returns A promise that resolves with an array of errors encountered during cleanup.
* An empty array indicates all cleanup succeeded.
*
* @example
* ```typescript
* const errors = await client.stop();
* if (errors.length > 0) {
* console.error("Cleanup errors:", errors);
* }
* ```
*/
stop(): Promise<Error[]>;
/**
* Forcefully stops the CLI server without graceful cleanup.
*
* Use this when {@link stop} fails or takes too long. This method:
* - Clears all sessions immediately without destroying them
* - Force closes the connection
* - Sends SIGKILL to the CLI process (if spawned by this client)
*
* @returns A promise that resolves when the force stop is complete
*
* @example
* ```typescript
* // If normal stop hangs, force stop
* const stopPromise = client.stop();
* const timeout = new Promise((_, reject) =>
* setTimeout(() => reject(new Error("Timeout")), 5000)
* );
*
* try {
* await Promise.race([stopPromise, timeout]);
* } catch {
* await client.forceStop();
* }
* ```
*/
forceStop(): Promise<void>;
/**
* Creates a new conversation session with the Copilot CLI.
*
* Sessions maintain conversation state, handle events, and manage tool execution.
* If the client is not connected and `autoStart` is enabled, this will automatically
* start the connection.
*
* @param config - Optional configuration for the session
* @returns A promise that resolves with the created session
* @throws Error if the client is not connected and autoStart is disabled
*
* @example
* ```typescript
* // Basic session
* const session = await client.createSession();
*
* // Session with model and tools
* const session = await client.createSession({
* model: "gpt-4",
* tools: [{
* name: "get_weather",
* description: "Get weather for a location",
* parameters: { type: "object", properties: { location: { type: "string" } } },
* handler: async (args) => ({ temperature: 72 })
* }]
* });
* ```
*/
createSession(config?: SessionConfig): Promise<CopilotSession>;
/**
* Resumes an existing conversation session by its ID.
*
* This allows you to continue a previous conversation, maintaining all
* conversation history. The session must have been previously created
* and not deleted.
*
* @param sessionId - The ID of the session to resume
* @param config - Optional configuration for the resumed session
* @returns A promise that resolves with the resumed session
* @throws Error if the session does not exist or the client is not connected
*
* @example
* ```typescript
* // Resume a previous session
* const session = await client.resumeSession("session-123");
*
* // Resume with new tools
* const session = await client.resumeSession("session-123", {
* tools: [myNewTool]
* });
* ```
*/
resumeSession(sessionId: string, config?: ResumeSessionConfig): Promise<CopilotSession>;
/**
* Gets the current connection state of the client.
*
* @returns The current connection state: "disconnected", "connecting", "connected", or "error"
*
* @example
* ```typescript
* if (client.getState() === "connected") {
* const session = await client.createSession();
* }
* ```
*/
getState(): ConnectionState;
/**
* Sends a ping request to the server to verify connectivity.
*
* @param message - Optional message to include in the ping
* @returns A promise that resolves with the ping response containing the message and timestamp
* @throws Error if the client is not connected
*
* @example
* ```typescript
* const response = await client.ping("health check");
* console.log(`Server responded at ${new Date(response.timestamp)}`);
* ```
*/
ping(message?: string): Promise<{
message: string;
timestamp: number;
protocolVersion?: number;
}>;
/**
* Verify that the server's protocol version matches the SDK's expected version
*/
private verifyProtocolVersion;
/**
* Gets the ID of the most recently updated session.
*
* This is useful for resuming the last conversation when the session ID
* was not stored.
*
* @returns A promise that resolves with the session ID, or undefined if no sessions exist
* @throws Error if the client is not connected
*
* @example
* ```typescript
* const lastId = await client.getLastSessionId();
* if (lastId) {
* const session = await client.resumeSession(lastId);
* }
* ```
*/
getLastSessionId(): Promise<string | undefined>;
/**
* Deletes a session and its data from disk.
*
* This permanently removes the session and all its conversation history.
* The session cannot be resumed after deletion.
*
* @param sessionId - The ID of the session to delete
* @returns A promise that resolves when the session is deleted
* @throws Error if the session does not exist or deletion fails
*
* @example
* ```typescript
* await client.deleteSession("session-123");
* ```
*/
deleteSession(sessionId: string): Promise<void>;
/**
* Lists all available sessions known to the server.
*
* Returns metadata about each session including ID, timestamps, and summary.
*
* @returns A promise that resolves with an array of session metadata
* @throws Error if the client is not connected
*
* @example
* ```typescript
* const sessions = await client.listSessions();
* for (const session of sessions) {
* console.log(`${session.sessionId}: ${session.summary}`);
* }
* ```
*/
listSessions(): Promise<SessionMetadata[]>;
/**
* Start the CLI server process
*/
private startCLIServer;
/**
* Connect to the CLI server (via socket or stdio)
*/
private connectToServer;
/**
* Connect via stdio pipes
*/
private connectViaStdio;
/**
* Connect to the CLI server via TCP socket
*/
private connectViaTcp;
private attachConnectionHandlers;
private handleSessionEventNotification;
private handleToolCallRequest;
private executeToolCall;
private handlePermissionRequest;
private normalizeToolResult;
private isToolResultObject;
private buildUnsupportedToolResult;
/**
* Attempt to reconnect to the server
*/
private reconnect;
}
/**
* AUTO-GENERATED FILE - DO NOT EDIT
*
* Generated from: @github/copilot/session-events.schema.json
* Generated by: scripts/generate-session-types.ts
* Generated at: 2026-01-13T00:08:20.716Z
*
* To update these types:
* 1. Update the schema in copilot-agent-runtime
* 2. Run: npm run generate:session-types
*/
export type SessionEvent = {
id: string;
timestamp: string;
parentId: string | null;
ephemeral?: boolean;
type: "session.start";
data: {
sessionId: string;
version: number;
producer: string;
copilotVersion: string;
startTime: string;
selectedModel?: string;
};
} | {
id: string;
timestamp: string;
parentId: string | null;
ephemeral?: boolean;
type: "session.resume";
data: {
resumeTime: string;
eventCount: number;
};
} | {
id: string;
timestamp: string;
parentId: string | null;
ephemeral?: boolean;
type: "session.error";
data: {
errorType: string;
message: string;
stack?: string;
};
} | {
id: string;
timestamp: string;
parentId: string | null;
ephemeral: true;
type: "session.idle";
data: {};
} | {
id: string;
timestamp: string;
parentId: string | null;
ephemeral?: boolean;
type: "session.info";
data: {
infoType: string;
message: string;
};
} | {
id: string;
timestamp: string;
parentId: string | null;
ephemeral?: boolean;
type: "session.model_change";
data: {
previousModel?: string;
newModel: string;
};
} | {
id: string;
timestamp: string;
parentId: string | null;
ephemeral?: boolean;
type: "session.handoff";
data: {
handoffTime: string;
sourceType: "remote" | "local";
repository?: {
owner: string;
name: string;
branch?: string;
};
context?: string;
summary?: string;
remoteSessionId?: string;
};
} | {
id: string;
timestamp: string;
parentId: string | null;
ephemeral?: boolean;
type: "session.truncation";
data: {
tokenLimit: number;
preTruncationTokensInMessages: number;
preTruncationMessagesLength: number;
postTruncationTokensInMessages: number;
postTruncationMessagesLength: number;
tokensRemovedDuringTruncation: number;
messagesRemovedDuringTruncation: number;
performedBy: string;
};
} | {
id: string;
timestamp: string;
parentId: string | null;
ephemeral?: boolean;
type: "user.message";
data: {
content: string;
transformedContent?: string;
attachments?: {
type: "file" | "directory";
path: string;
displayName: string;
}[];
source?: string;
};
} | {
id: string;
timestamp: string;
parentId: string | null;
ephemeral: true;
type: "pending_messages.modified";
data: {};
} | {
id: string;
timestamp: string;
parentId: string | null;
ephemeral?: boolean;
type: "assistant.turn_start";
data: {
turnId: string;
};
} | {
id: string;
timestamp: string;
parentId: string | null;
ephemeral: true;
type: "assistant.intent";
data: {
intent: string;
};
} | {
id: string;
timestamp: string;
parentId: string | null;
ephemeral?: boolean;
type: "assistant.reasoning";
data: {
reasoningId: string;
content: string;
chunkContent?: string;
};
} | {
id: string;
timestamp: string;
parentId: string | null;
ephemeral?: true;
type: "assistant.reasoning_delta";
data: {
reasoningId: string;
deltaContent: string;
};
} | {
id: string;
timestamp: string;
parentId: string | null;
ephemeral?: boolean;
type: "assistant.message";
data: {
messageId: string;
content: string;
chunkContent?: string;
totalResponseSizeBytes?: number;
toolRequests?: {
toolCallId: string;
name: string;
arguments?: unknown;
}[];
parentToolCallId?: string;
};
} | {
id: string;
timestamp: string;
parentId: string | null;
ephemeral?: true;
type: "assistant.message_delta";
data: {
messageId: string;
deltaContent: string;
totalResponseSizeBytes?: number;
parentToolCallId?: string;
};
} | {
id: string;
timestamp: string;
parentId: string | null;
ephemeral?: boolean;
type: "assistant.turn_end";
data: {
turnId: string;
};
} | {
id: string;
timestamp: string;
parentId: string | null;
ephemeral: true;
type: "assistant.usage";
data: {
model?: string;
inputTokens?: number;
outputTokens?: number;
cacheReadTokens?: number;
cacheWriteTokens?: number;
cost?: number;
duration?: number;
initiator?: string;
apiCallId?: string;
providerCallId?: string;
quotaSnapshots?: {
[k: string]: {
isUnlimitedEntitlement: boolean;
entitlementRequests: number;
usedRequests: number;
usageAllowedWithExhaustedQuota: boolean;
overage: number;
overageAllowedWithExhaustedQuota: boolean;
remainingPercentage: number;
resetDate?: string;
};
};
};
} | {
id: string;
timestamp: string;
parentId: string | null;
ephemeral?: boolean;
type: "abort";
data: {
reason: string;
};
} | {
id: string;
timestamp: string;
parentId: string | null;
ephemeral?: boolean;
type: "tool.user_requested";
data: {
toolCallId: string;
toolName: string;
arguments?: unknown;
};
} | {
id: string;
timestamp: string;
parentId: string | null;
ephemeral?: boolean;
type: "tool.execution_start";
data: {
toolCallId: string;
toolName: string;
arguments?: unknown;
parentToolCallId?: string;
};
} | {
id: string;
timestamp: string;
parentId: string | null;
ephemeral: true;
type: "tool.execution_partial_result";
data: {
toolCallId: string;
partialOutput: string;
};
} | {
id: string;
timestamp: string;
parentId: string | null;
ephemeral?: boolean;
type: "tool.execution_complete";
data: {
toolCallId: string;
success: boolean;
isUserRequested?: boolean;
result?: {
content: string;
};
error?: {
message: string;
code?: string;
};
toolTelemetry?: {
[k: string]: unknown;
};
parentToolCallId?: string;
};
} | {
id: string;
timestamp: string;
parentId: string | null;
ephemeral?: boolean;
type: "custom_agent.started";
data: {
toolCallId: string;
agentName: string;
agentDisplayName: string;
agentDescription: string;
};
} | {
id: string;
timestamp: string;
parentId: string | null;
ephemeral?: boolean;
type: "custom_agent.completed";
data: {
toolCallId: string;
agentName: string;
};
} | {
id: string;
timestamp: string;
parentId: string | null;
ephemeral?: boolean;
type: "custom_agent.failed";
data: {
toolCallId: string;
agentName: string;
error: string;
};
} | {
id: string;
timestamp: string;
parentId: string | null;
ephemeral?: boolean;
type: "custom_agent.selected";
data: {
agentName: string;
agentDisplayName: string;
tools: string[] | null;
};
} | {
id: string;
timestamp: string;
parentId: string | null;
ephemeral?: boolean;
type: "hook.start";
data: {
hookInvocationId: string;
hookType: string;
input?: unknown;
};
} | {
id: string;
timestamp: string;
parentId: string | null;
ephemeral?: boolean;
type: "hook.end";
data: {
hookInvocationId: string;
hookType: string;
output?: unknown;
success: boolean;
error?: {
message: string;
stack?: string;
};
};
} | {
id: string;
timestamp: string;
parentId: string | null;
ephemeral?: boolean;
type: "system.message";
data: {
content: string;
role: "system" | "developer";
name?: string;
metadata?: {
promptVersion?: string;
variables?: {
[k: string]: unknown;
};
};
};
};
/**
* Copilot SDK - TypeScript/Node.js Client
*
* JSON-RPC based SDK for programmatic control of GitHub Copilot CLI
*/
export { CopilotClient } from "./client.js";
export { CopilotSession } from "./session.js";
export { defineTool } from "./types.js";
export type { ConnectionState, CopilotClientOptions, CustomAgentConfig, MCPLocalServerConfig, MCPRemoteServerConfig, MCPServerConfig, MessageOptions, PermissionHandler, PermissionRequest, PermissionRequestResult, ResumeSessionConfig, SessionConfig, SessionEvent, SessionEventHandler, SessionMetadata, SystemMessageAppendConfig, SystemMessageConfig, SystemMessageReplaceConfig, Tool, ToolHandler, ToolInvocation, ToolResultObject, ZodSchema, } from "./types.js";
/**
* The SDK protocol version.
* This must match the version expected by the copilot-agent-runtime server.
*/
export declare const SDK_PROTOCOL_VERSION = 1;
/**
* Gets the SDK protocol version.
* @returns The protocol version number
*/
export declare function getSdkProtocolVersion(): number;
/**
* Copilot Session - represents a single conversation session with the Copilot CLI.
* @module session
*/
import type { MessageConnection } from "vscode-jsonrpc/node";
import type { MessageOptions, PermissionHandler, PermissionRequestResult, SessionEvent, SessionEventHandler, Tool, ToolHandler } from "./types.js";
/**
* Represents a single conversation session with the Copilot CLI.
*
* A session maintains conversation state, handles events, and manages tool execution.
* Sessions are created via {@link CopilotClient.createSession} or resumed via
* {@link CopilotClient.resumeSession}.
*
* @example
* ```typescript
* const session = await client.createSession({ model: "gpt-4" });
*
* // Subscribe to events
* const unsubscribe = session.on((event) => {
* if (event.type === "assistant.message") {
* console.log(event.data.content);
* }
* });
*
* // Send a message
* await session.send({ prompt: "Hello, world!" });
*
* // Clean up
* unsubscribe();
* await session.destroy();
* ```
*/
export declare class CopilotSession {
readonly sessionId: string;
private connection;
private eventHandlers;
private toolHandlers;
private permissionHandler?;
/**
* Creates a new CopilotSession instance.
*
* @param sessionId - The unique identifier for this session
* @param connection - The JSON-RPC message connection to the Copilot CLI
* @internal This constructor is internal. Use {@link CopilotClient.createSession} to create sessions.
*/
constructor(sessionId: string, connection: MessageConnection);
/**
* Sends a message to this session and waits for the response.
*
* The message is processed asynchronously. Subscribe to events via {@link on}
* to receive streaming responses and other session events.
*
* @param options - The message options including the prompt and optional attachments
* @returns A promise that resolves with the message ID of the response
* @throws Error if the session has been destroyed or the connection fails
*
* @example
* ```typescript
* const messageId = await session.send({
* prompt: "Explain this code",
* attachments: [{ type: "file", path: "./src/index.ts" }]
* });
* ```
*/
send(options: MessageOptions): Promise<string>;
/**
* Subscribes to events from this session.
*
* Events include assistant messages, tool executions, errors, and session state changes.
* Multiple handlers can be registered and will all receive events.
*
* @param handler - A callback function that receives session events
* @returns A function that, when called, unsubscribes the handler
*
* @example
* ```typescript
* const unsubscribe = session.on((event) => {
* switch (event.type) {
* case "assistant.message":
* console.log("Assistant:", event.data.content);
* break;
* case "session.error":
* console.error("Error:", event.data.message);
* break;
* }
* });
*
* // Later, to stop receiving events:
* unsubscribe();
* ```
*/
on(handler: SessionEventHandler): () => void;
/**
* Dispatches an event to all registered handlers.
*
* @param event - The session event to dispatch
* @internal This method is for internal use by the SDK.
*/
_dispatchEvent(event: SessionEvent): void;
/**
* Registers custom tool handlers for this session.
*
* Tools allow the assistant to execute custom functions. When the assistant
* invokes a tool, the corresponding handler is called with the tool arguments.
*
* @param tools - An array of tool definitions with their handlers, or undefined to clear all tools
* @internal This method is typically called internally when creating a session with tools.
*/
registerTools(tools?: Tool[]): void;
/**
* Retrieves a registered tool handler by name.
*
* @param name - The name of the tool to retrieve
* @returns The tool handler if found, or undefined
* @internal This method is for internal use by the SDK.
*/
getToolHandler(name: string): ToolHandler | undefined;
/**
* Registers a handler for permission requests.
*
* When the assistant needs permission to perform certain actions (e.g., file operations),
* this handler is called to approve or deny the request.
*
* @param handler - The permission handler function, or undefined to remove the handler
* @internal This method is typically called internally when creating a session.
*/
registerPermissionHandler(handler?: PermissionHandler): void;
/**
* Handles a permission request from the Copilot CLI.
*
* @param request - The permission request data from the CLI
* @returns A promise that resolves with the permission decision
* @internal This method is for internal use by the SDK.
*/
_handlePermissionRequest(request: unknown): Promise<PermissionRequestResult>;
/**
* Retrieves all events and messages from this session's history.
*
* This returns the complete conversation history including user messages,
* assistant responses, tool executions, and other session events.
*
* @returns A promise that resolves with an array of all session events
* @throws Error if the session has been destroyed or the connection fails
*
* @example
* ```typescript
* const events = await session.getMessages();
* for (const event of events) {
* if (event.type === "assistant.message") {
* console.log("Assistant:", event.data.content);
* }
* }
* ```
*/
getMessages(): Promise<SessionEvent[]>;
/**
* Destroys this session and releases all associated resources.
*
* After calling this method, the session can no longer be used. All event
* handlers and tool handlers are cleared. To continue the conversation,
* use {@link CopilotClient.resumeSession} with the session ID.
*
* @returns A promise that resolves when the session is destroyed
* @throws Error if the connection fails
*
* @example
* ```typescript
* // Clean up when done
* await session.destroy();
* ```
*/
destroy(): Promise<void>;
/**
* Aborts the currently processing message in this session.
*
* Use this to cancel a long-running request. The session remains valid
* and can continue to be used for new messages.
*
* @returns A promise that resolves when the abort request is acknowledged
* @throws Error if the session has been destroyed or the connection fails
*
* @example
* ```typescript
* // Start a long-running request
* const messagePromise = session.send({ prompt: "Write a very long story..." });
*
* // Abort after 5 seconds
* setTimeout(async () => {
* await session.abort();
* }, 5000);
* ```
*/
abort(): Promise<void>;
}
/**
* Type definitions for the Copilot SDK
*/
import type { SessionEvent as GeneratedSessionEvent } from "./generated/session-events.js";
export type SessionEvent = GeneratedSessionEvent;
/**
* Options for creating a CopilotClient
*/
export interface CopilotClientOptions {
/**
* Path to the Copilot CLI executable
* @default "copilot" (searches PATH)
*/
cliPath?: string;
/**
* Extra arguments to pass to the CLI executable (inserted before SDK-managed args)
*/
cliArgs?: string[];
/**
* Working directory for the CLI process
* If not set, inherits the current process's working directory
*/
cwd?: string;
/**
* Port for the CLI server (TCP mode only)
* @default 0 (random available port)
*/
port?: number;
/**
* Use stdio transport instead of TCP
* When true, communicates with CLI via stdin/stdout pipes
* @default true
*/
useStdio?: boolean;
/**
* URL of an existing Copilot CLI server to connect to over TCP
* When provided, the client will not spawn a CLI process
* Format: "host:port" or "http://host:port" or just "port" (defaults to localhost)
* Examples: "localhost:8080", "http://127.0.0.1:9000", "8080"
* Mutually exclusive with cliPath, useStdio
*/
cliUrl?: string;
/**
* Log level for the CLI server
*/
logLevel?: "none" | "error" | "warning" | "info" | "debug" | "all";
/**
* Auto-start the CLI server on first use
* @default true
*/
autoStart?: boolean;
/**
* Auto-restart the CLI server if it crashes
* @default true
*/
autoRestart?: boolean;
/**
* Environment variables to pass to the CLI process. If not set, inherits process.env.
*/
env?: Record<string, string | undefined>;
}
/**
* Configuration for creating a session
*/
export type ToolResultType = "success" | "failure" | "rejected" | "denied";
export type ToolBinaryResult = {
data: string;
mimeType: string;
type: string;
description?: string;
};
export type ToolResultObject = {
textResultForLlm: string;
binaryResultsForLlm?: ToolBinaryResult[];
resultType: ToolResultType;
error?: string;
sessionLog?: string;
toolTelemetry?: Record<string, unknown>;
};
export type ToolResult = string | ToolResultObject;
export interface ToolInvocation {
sessionId: string;
toolCallId: string;
toolName: string;
arguments: unknown;
}
export type ToolHandler<TArgs = unknown> = (args: TArgs, invocation: ToolInvocation) => Promise<unknown> | unknown;
/**
* Zod-like schema interface for type inference.
* Any object with `toJSONSchema()` method is treated as a Zod schema.
*/
export interface ZodSchema<T = unknown> {
_output: T;
toJSONSchema(): Record<string, unknown>;
}
/**
* Tool definition. Parameters can be either:
* - A Zod schema (provides type inference for handler)
* - A raw JSON schema object
* - Omitted (no parameters)
*/
export interface Tool<TArgs = unknown> {
name: string;
description?: string;
parameters?: ZodSchema<TArgs> | Record<string, unknown>;
handler: ToolHandler<TArgs>;
}
/**
* Helper to define a tool with Zod schema and get type inference for the handler.
* Without this helper, TypeScript cannot infer handler argument types from Zod schemas.
*/
export declare function defineTool<T = unknown>(name: string, config: {
description?: string;
parameters?: ZodSchema<T> | Record<string, unknown>;
handler: ToolHandler<T>;
}): Tool<T>;
export interface ToolCallRequestPayload {
sessionId: string;
toolCallId: string;
toolName: string;
arguments: unknown;
}
export interface ToolCallResponsePayload {
result: ToolResult;
}
/**
* Append mode: Use CLI foundation with optional appended content (default).
*/
export interface SystemMessageAppendConfig {
mode?: "append";
/**
* Additional instructions appended after SDK-managed sections.
*/
content?: string;
}
/**
* Replace mode: Use caller-provided system message entirely.
* Removes all SDK guardrails including security restrictions.
*/
export interface SystemMessageReplaceConfig {
mode: "replace";
/**
* Complete system message content.
* Replaces the entire SDK-managed system message.
*/
content: string;
}
/**
* System message configuration for session creation.
* - Append mode (default): SDK foundation + optional custom content
* - Replace mode: Full control, caller provides entire system message
*/
export type SystemMessageConfig = SystemMessageAppendConfig | SystemMessageReplaceConfig;
/**
* Permission request types from the server
*/
export interface PermissionRequest {
kind: "shell" | "write" | "mcp" | "read" | "url";
toolCallId?: string;
[key: string]: unknown;
}
export interface PermissionRequestResult {
kind: "approved" | "denied-by-rules" | "denied-no-approval-rule-and-could-not-request-from-user" | "denied-interactively-by-user";
rules?: unknown[];
}
export type PermissionHandler = (request: PermissionRequest, invocation: {
sessionId: string;
}) => Promise<PermissionRequestResult> | PermissionRequestResult;
/**
* Base interface for MCP server configuration.
*/
interface MCPServerConfigBase {
/**
* List of tools to include from this server. [] means none. "*" means all.
*/
tools: string[];
/**
* Indicates "remote" or "local" server type.
* If not specified, defaults to "local".
*/
type?: string;
/**
* Optional timeout in milliseconds for tool calls to this server.
*/
timeout?: number;
}
/**
* Configuration for a local/stdio MCP server.
*/
export interface MCPLocalServerConfig extends MCPServerConfigBase {
type?: "local" | "stdio";
command: string;
args: string[];
/**
* Environment variables to pass to the server.
*/
env?: Record<string, string>;
cwd?: string;
}
/**
* Configuration for a remote MCP server (HTTP or SSE).
*/
export interface MCPRemoteServerConfig extends MCPServerConfigBase {
type: "http" | "sse";
/**
* URL of the remote server.
*/
url: string;
/**
* Optional HTTP headers to include in requests.
*/
headers?: Record<string, string>;
}
/**
* Union type for MCP server configurations.
*/
export type MCPServerConfig = MCPLocalServerConfig | MCPRemoteServerConfig;
/**
* Configuration for a custom agent.
*/
export interface CustomAgentConfig {
/**
* Unique name of the custom agent.
*/
name: string;
/**
* Display name for UI purposes.
*/
displayName?: string;
/**
* Description of what the agent does.
*/
description?: string;
/**
* List of tool names the agent can use.
* Use null or undefined for all tools.
*/
tools?: string[] | null;
/**
* The prompt content for the agent.
*/
prompt: string;
/**
* MCP servers specific to this agent.
*/
mcpServers?: Record<string, MCPServerConfig>;
/**
* Whether the agent should be available for model inference.
* @default true
*/
infer?: boolean;
}
export interface SessionConfig {
/**
* Optional custom session ID
* If not provided, server will generate one
*/
sessionId?: string;
/**
* Model to use for this session
*/
model?: string;
/**
* Tools exposed to the CLI server
*/
tools?: Tool<any>[];
/**
* System message configuration
* Controls how the system prompt is constructed
*/
systemMessage?: SystemMessageConfig;
/**
* List of tool names to allow. When specified, only these tools will be available.
* Takes precedence over excludedTools.
*/
availableTools?: string[];
/**
* List of tool names to disable. All other tools remain available.
* Ignored if availableTools is specified.
*/
excludedTools?: string[];
/**
* Custom provider configuration (BYOK - Bring Your Own Key).
* When specified, uses the provided API endpoint instead of the Copilot API.
*/
provider?: ProviderConfig;
/**
* Handler for permission requests from the server.
* When provided, the server will call this handler to request permission for operations.
*/
onPermissionRequest?: PermissionHandler;
streaming?: boolean;
/**
* MCP server configurations for the session.
* Keys are server names, values are server configurations.
*/
mcpServers?: Record<string, MCPServerConfig>;
/**
* Custom agent configurations for the session.
*/
customAgents?: CustomAgentConfig[];
}
/**
* Configuration for resuming a session
*/
export type ResumeSessionConfig = Pick<SessionConfig, "tools" | "provider" | "streaming" | "onPermissionRequest" | "mcpServers" | "customAgents">;
/**
* Configuration for a custom API provider.
*/
export interface ProviderConfig {
/**
* Provider type. Defaults to "openai" for generic OpenAI-compatible APIs.
*/
type?: "openai" | "azure" | "anthropic";
/**
* API format (openai/azure only). Defaults to "completions".
*/
wireApi?: "completions" | "responses";
/**
* API endpoint URL
*/
baseUrl: string;
/**
* API key. Optional for local providers like Ollama.
*/
apiKey?: string;
/**
* Bearer token for authentication. Sets the Authorization header directly.
* Use this for services requiring bearer token auth instead of API key.
* Takes precedence over apiKey when both are set.
*/
bearerToken?: string;
/**
* Azure-specific options
*/
azure?: {
/**
* API version. Defaults to "2024-10-21".
*/
apiVersion?: string;
};
}
/**
* Options for sending a message to a session
*/
export interface MessageOptions {
/**
* The prompt/message to send
*/
prompt: string;
/**
* File or directory attachments
*/
attachments?: Array<{
type: "file" | "directory";
path: string;
displayName?: string;
}>;
/**
* Message delivery mode
* - "enqueue": Add to queue (default)
* - "immediate": Send immediately
*/
mode?: "enqueue" | "immediate";
}
/**
* Event handler callback type
*/
export type SessionEventHandler = (event: SessionEvent) => void;
/**
* Connection state
*/
export type ConnectionState = "disconnected" | "connecting" | "connected" | "error";
/**
* Metadata about a session
*/
export interface SessionMetadata {
sessionId: string;
startTime: Date;
modifiedTime: Date;
summary?: string;
isRemote: boolean;
}
export {};
+3
-2

@@ -1,7 +0,8 @@

import sdkProtocolVersion from "../../sdk-protocol-version.json";
const SDK_PROTOCOL_VERSION = 1;
function getSdkProtocolVersion() {
return sdkProtocolVersion.version;
return SDK_PROTOCOL_VERSION;
}
export {
SDK_PROTOCOL_VERSION,
getSdkProtocolVersion
};
+2
-2

@@ -7,3 +7,3 @@ {

},
"version": "0.1.11",
"version": "0.1.12",
"description": "TypeScript SDK for programmatic control of GitHub Copilot CLI via JSON-RPC",

@@ -30,3 +30,3 @@ "main": "./dist/index.js",

"generate:session-types": "tsx scripts/generate-session-types.ts",
"update:protocol-version": "tsx scripts/generate-protocol-version.ts",
"update:protocol-version": "tsx scripts/update-protocol-version.ts",
"prepublishOnly": "npm run build",

@@ -33,0 +33,0 @@ "package": "npm run clean && npm run build && node scripts/set-version.js && npm pack && npm version 0.1.0 --no-git-tag-version --allow-same-version"

import { CopilotSession } from "./session.js";
import type { ConnectionState, CopilotClientOptions, ResumeSessionConfig, SessionConfig, SessionMetadata } from "./types.js";
/**
* Main client for interacting with the Copilot CLI.
*
* The CopilotClient manages the connection to the Copilot CLI server and provides
* methods to create and manage conversation sessions. It can either spawn a CLI
* server process or connect to an existing server.
*
* @example
* ```typescript
* import { CopilotClient } from "@github/copilot-sdk";
*
* // Create a client with default options (spawns CLI server)
* const client = new CopilotClient();
*
* // Or connect to an existing server
* const client = new CopilotClient({ cliUrl: "localhost:3000" });
*
* // Create a session
* const session = await client.createSession({ model: "gpt-4" });
*
* // Send messages and handle responses
* session.on((event) => {
* if (event.type === "assistant.message") {
* console.log(event.data.content);
* }
* });
* await session.send({ prompt: "Hello!" });
*
* // Clean up
* await session.destroy();
* await client.stop();
* ```
*/
export declare class CopilotClient {
private cliProcess;
private connection;
private socket;
private actualPort;
private actualHost;
private state;
private sessions;
private options;
private isExternalServer;
private forceStopping;
/**
* Creates a new CopilotClient instance.
*
* @param options - Configuration options for the client
* @throws Error if mutually exclusive options are provided (e.g., cliUrl with useStdio or cliPath)
*
* @example
* ```typescript
* // Default options - spawns CLI server using stdio
* const client = new CopilotClient();
*
* // Connect to an existing server
* const client = new CopilotClient({ cliUrl: "localhost:3000" });
*
* // Custom CLI path with specific log level
* const client = new CopilotClient({
* cliPath: "/usr/local/bin/copilot",
* logLevel: "debug"
* });
* ```
*/
constructor(options?: CopilotClientOptions);
/**
* Parse CLI URL into host and port
* Supports formats: "host:port", "http://host:port", "https://host:port", or just "port"
*/
private parseCliUrl;
/**
* Starts the CLI server and establishes a connection.
*
* If connecting to an external server (via cliUrl), only establishes the connection.
* Otherwise, spawns the CLI server process and then connects.
*
* This method is called automatically when creating a session if `autoStart` is true (default).
*
* @returns A promise that resolves when the connection is established
* @throws Error if the server fails to start or the connection fails
*
* @example
* ```typescript
* const client = new CopilotClient({ autoStart: false });
* await client.start();
* // Now ready to create sessions
* ```
*/
start(): Promise<void>;
/**
* Stops the CLI server and closes all active sessions.
*
* This method performs graceful cleanup:
* 1. Destroys all active sessions with retry logic
* 2. Closes the JSON-RPC connection
* 3. Terminates the CLI server process (if spawned by this client)
*
* @returns A promise that resolves with an array of errors encountered during cleanup.
* An empty array indicates all cleanup succeeded.
*
* @example
* ```typescript
* const errors = await client.stop();
* if (errors.length > 0) {
* console.error("Cleanup errors:", errors);
* }
* ```
*/
stop(): Promise<Error[]>;
/**
* Forcefully stops the CLI server without graceful cleanup.
*
* Use this when {@link stop} fails or takes too long. This method:
* - Clears all sessions immediately without destroying them
* - Force closes the connection
* - Sends SIGKILL to the CLI process (if spawned by this client)
*
* @returns A promise that resolves when the force stop is complete
*
* @example
* ```typescript
* // If normal stop hangs, force stop
* const stopPromise = client.stop();
* const timeout = new Promise((_, reject) =>
* setTimeout(() => reject(new Error("Timeout")), 5000)
* );
*
* try {
* await Promise.race([stopPromise, timeout]);
* } catch {
* await client.forceStop();
* }
* ```
*/
forceStop(): Promise<void>;
/**
* Creates a new conversation session with the Copilot CLI.
*
* Sessions maintain conversation state, handle events, and manage tool execution.
* If the client is not connected and `autoStart` is enabled, this will automatically
* start the connection.
*
* @param config - Optional configuration for the session
* @returns A promise that resolves with the created session
* @throws Error if the client is not connected and autoStart is disabled
*
* @example
* ```typescript
* // Basic session
* const session = await client.createSession();
*
* // Session with model and tools
* const session = await client.createSession({
* model: "gpt-4",
* tools: [{
* name: "get_weather",
* description: "Get weather for a location",
* parameters: { type: "object", properties: { location: { type: "string" } } },
* handler: async (args) => ({ temperature: 72 })
* }]
* });
* ```
*/
createSession(config?: SessionConfig): Promise<CopilotSession>;
/**
* Resumes an existing conversation session by its ID.
*
* This allows you to continue a previous conversation, maintaining all
* conversation history. The session must have been previously created
* and not deleted.
*
* @param sessionId - The ID of the session to resume
* @param config - Optional configuration for the resumed session
* @returns A promise that resolves with the resumed session
* @throws Error if the session does not exist or the client is not connected
*
* @example
* ```typescript
* // Resume a previous session
* const session = await client.resumeSession("session-123");
*
* // Resume with new tools
* const session = await client.resumeSession("session-123", {
* tools: [myNewTool]
* });
* ```
*/
resumeSession(sessionId: string, config?: ResumeSessionConfig): Promise<CopilotSession>;
/**
* Gets the current connection state of the client.
*
* @returns The current connection state: "disconnected", "connecting", "connected", or "error"
*
* @example
* ```typescript
* if (client.getState() === "connected") {
* const session = await client.createSession();
* }
* ```
*/
getState(): ConnectionState;
/**
* Sends a ping request to the server to verify connectivity.
*
* @param message - Optional message to include in the ping
* @returns A promise that resolves with the ping response containing the message and timestamp
* @throws Error if the client is not connected
*
* @example
* ```typescript
* const response = await client.ping("health check");
* console.log(`Server responded at ${new Date(response.timestamp)}`);
* ```
*/
ping(message?: string): Promise<{
message: string;
timestamp: number;
protocolVersion?: number;
}>;
/**
* Verify that the server's protocol version matches the SDK's expected version
*/
private verifyProtocolVersion;
/**
* Gets the ID of the most recently updated session.
*
* This is useful for resuming the last conversation when the session ID
* was not stored.
*
* @returns A promise that resolves with the session ID, or undefined if no sessions exist
* @throws Error if the client is not connected
*
* @example
* ```typescript
* const lastId = await client.getLastSessionId();
* if (lastId) {
* const session = await client.resumeSession(lastId);
* }
* ```
*/
getLastSessionId(): Promise<string | undefined>;
/**
* Deletes a session and its data from disk.
*
* This permanently removes the session and all its conversation history.
* The session cannot be resumed after deletion.
*
* @param sessionId - The ID of the session to delete
* @returns A promise that resolves when the session is deleted
* @throws Error if the session does not exist or deletion fails
*
* @example
* ```typescript
* await client.deleteSession("session-123");
* ```
*/
deleteSession(sessionId: string): Promise<void>;
/**
* Lists all available sessions known to the server.
*
* Returns metadata about each session including ID, timestamps, and summary.
*
* @returns A promise that resolves with an array of session metadata
* @throws Error if the client is not connected
*
* @example
* ```typescript
* const sessions = await client.listSessions();
* for (const session of sessions) {
* console.log(`${session.sessionId}: ${session.summary}`);
* }
* ```
*/
listSessions(): Promise<SessionMetadata[]>;
/**
* Start the CLI server process
*/
private startCLIServer;
/**
* Connect to the CLI server (via socket or stdio)
*/
private connectToServer;
/**
* Connect via stdio pipes
*/
private connectViaStdio;
/**
* Connect to the CLI server via TCP socket
*/
private connectViaTcp;
private attachConnectionHandlers;
private handleSessionEventNotification;
private handleToolCallRequest;
private executeToolCall;
private handlePermissionRequest;
private normalizeToolResult;
private isToolResultObject;
private buildUnsupportedToolResult;
/**
* Attempt to reconnect to the server
*/
private reconnect;
}
/**
* AUTO-GENERATED FILE - DO NOT EDIT
*
* Generated from: @github/copilot/session-events.schema.json
* Generated by: scripts/generate-session-types.ts
* Generated at: 2026-01-13T00:08:20.716Z
*
* To update these types:
* 1. Update the schema in copilot-agent-runtime
* 2. Run: npm run generate:session-types
*/
export type SessionEvent = {
id: string;
timestamp: string;
parentId: string | null;
ephemeral?: boolean;
type: "session.start";
data: {
sessionId: string;
version: number;
producer: string;
copilotVersion: string;
startTime: string;
selectedModel?: string;
};
} | {
id: string;
timestamp: string;
parentId: string | null;
ephemeral?: boolean;
type: "session.resume";
data: {
resumeTime: string;
eventCount: number;
};
} | {
id: string;
timestamp: string;
parentId: string | null;
ephemeral?: boolean;
type: "session.error";
data: {
errorType: string;
message: string;
stack?: string;
};
} | {
id: string;
timestamp: string;
parentId: string | null;
ephemeral: true;
type: "session.idle";
data: {};
} | {
id: string;
timestamp: string;
parentId: string | null;
ephemeral?: boolean;
type: "session.info";
data: {
infoType: string;
message: string;
};
} | {
id: string;
timestamp: string;
parentId: string | null;
ephemeral?: boolean;
type: "session.model_change";
data: {
previousModel?: string;
newModel: string;
};
} | {
id: string;
timestamp: string;
parentId: string | null;
ephemeral?: boolean;
type: "session.handoff";
data: {
handoffTime: string;
sourceType: "remote" | "local";
repository?: {
owner: string;
name: string;
branch?: string;
};
context?: string;
summary?: string;
remoteSessionId?: string;
};
} | {
id: string;
timestamp: string;
parentId: string | null;
ephemeral?: boolean;
type: "session.truncation";
data: {
tokenLimit: number;
preTruncationTokensInMessages: number;
preTruncationMessagesLength: number;
postTruncationTokensInMessages: number;
postTruncationMessagesLength: number;
tokensRemovedDuringTruncation: number;
messagesRemovedDuringTruncation: number;
performedBy: string;
};
} | {
id: string;
timestamp: string;
parentId: string | null;
ephemeral?: boolean;
type: "user.message";
data: {
content: string;
transformedContent?: string;
attachments?: {
type: "file" | "directory";
path: string;
displayName: string;
}[];
source?: string;
};
} | {
id: string;
timestamp: string;
parentId: string | null;
ephemeral: true;
type: "pending_messages.modified";
data: {};
} | {
id: string;
timestamp: string;
parentId: string | null;
ephemeral?: boolean;
type: "assistant.turn_start";
data: {
turnId: string;
};
} | {
id: string;
timestamp: string;
parentId: string | null;
ephemeral: true;
type: "assistant.intent";
data: {
intent: string;
};
} | {
id: string;
timestamp: string;
parentId: string | null;
ephemeral?: boolean;
type: "assistant.reasoning";
data: {
reasoningId: string;
content: string;
chunkContent?: string;
};
} | {
id: string;
timestamp: string;
parentId: string | null;
ephemeral?: true;
type: "assistant.reasoning_delta";
data: {
reasoningId: string;
deltaContent: string;
};
} | {
id: string;
timestamp: string;
parentId: string | null;
ephemeral?: boolean;
type: "assistant.message";
data: {
messageId: string;
content: string;
chunkContent?: string;
totalResponseSizeBytes?: number;
toolRequests?: {
toolCallId: string;
name: string;
arguments?: unknown;
}[];
parentToolCallId?: string;
};
} | {
id: string;
timestamp: string;
parentId: string | null;
ephemeral?: true;
type: "assistant.message_delta";
data: {
messageId: string;
deltaContent: string;
totalResponseSizeBytes?: number;
parentToolCallId?: string;
};
} | {
id: string;
timestamp: string;
parentId: string | null;
ephemeral?: boolean;
type: "assistant.turn_end";
data: {
turnId: string;
};
} | {
id: string;
timestamp: string;
parentId: string | null;
ephemeral: true;
type: "assistant.usage";
data: {
model?: string;
inputTokens?: number;
outputTokens?: number;
cacheReadTokens?: number;
cacheWriteTokens?: number;
cost?: number;
duration?: number;
initiator?: string;
apiCallId?: string;
providerCallId?: string;
quotaSnapshots?: {
[k: string]: {
isUnlimitedEntitlement: boolean;
entitlementRequests: number;
usedRequests: number;
usageAllowedWithExhaustedQuota: boolean;
overage: number;
overageAllowedWithExhaustedQuota: boolean;
remainingPercentage: number;
resetDate?: string;
};
};
};
} | {
id: string;
timestamp: string;
parentId: string | null;
ephemeral?: boolean;
type: "abort";
data: {
reason: string;
};
} | {
id: string;
timestamp: string;
parentId: string | null;
ephemeral?: boolean;
type: "tool.user_requested";
data: {
toolCallId: string;
toolName: string;
arguments?: unknown;
};
} | {
id: string;
timestamp: string;
parentId: string | null;
ephemeral?: boolean;
type: "tool.execution_start";
data: {
toolCallId: string;
toolName: string;
arguments?: unknown;
parentToolCallId?: string;
};
} | {
id: string;
timestamp: string;
parentId: string | null;
ephemeral: true;
type: "tool.execution_partial_result";
data: {
toolCallId: string;
partialOutput: string;
};
} | {
id: string;
timestamp: string;
parentId: string | null;
ephemeral?: boolean;
type: "tool.execution_complete";
data: {
toolCallId: string;
success: boolean;
isUserRequested?: boolean;
result?: {
content: string;
};
error?: {
message: string;
code?: string;
};
toolTelemetry?: {
[k: string]: unknown;
};
parentToolCallId?: string;
};
} | {
id: string;
timestamp: string;
parentId: string | null;
ephemeral?: boolean;
type: "custom_agent.started";
data: {
toolCallId: string;
agentName: string;
agentDisplayName: string;
agentDescription: string;
};
} | {
id: string;
timestamp: string;
parentId: string | null;
ephemeral?: boolean;
type: "custom_agent.completed";
data: {
toolCallId: string;
agentName: string;
};
} | {
id: string;
timestamp: string;
parentId: string | null;
ephemeral?: boolean;
type: "custom_agent.failed";
data: {
toolCallId: string;
agentName: string;
error: string;
};
} | {
id: string;
timestamp: string;
parentId: string | null;
ephemeral?: boolean;
type: "custom_agent.selected";
data: {
agentName: string;
agentDisplayName: string;
tools: string[] | null;
};
} | {
id: string;
timestamp: string;
parentId: string | null;
ephemeral?: boolean;
type: "hook.start";
data: {
hookInvocationId: string;
hookType: string;
input?: unknown;
};
} | {
id: string;
timestamp: string;
parentId: string | null;
ephemeral?: boolean;
type: "hook.end";
data: {
hookInvocationId: string;
hookType: string;
output?: unknown;
success: boolean;
error?: {
message: string;
stack?: string;
};
};
} | {
id: string;
timestamp: string;
parentId: string | null;
ephemeral?: boolean;
type: "system.message";
data: {
content: string;
role: "system" | "developer";
name?: string;
metadata?: {
promptVersion?: string;
variables?: {
[k: string]: unknown;
};
};
};
};
/**
* Copilot SDK - TypeScript/Node.js Client
*
* JSON-RPC based SDK for programmatic control of GitHub Copilot CLI
*/
export { CopilotClient } from "./client.js";
export { CopilotSession } from "./session.js";
export { defineTool } from "./types.js";
export type { ConnectionState, CopilotClientOptions, CustomAgentConfig, MCPLocalServerConfig, MCPRemoteServerConfig, MCPServerConfig, MessageOptions, PermissionHandler, PermissionRequest, PermissionRequestResult, ResumeSessionConfig, SessionConfig, SessionEvent, SessionEventHandler, SessionMetadata, SystemMessageAppendConfig, SystemMessageConfig, SystemMessageReplaceConfig, Tool, ToolHandler, ToolInvocation, ToolResultObject, ZodSchema, } from "./types.js";
/**
* Gets the SDK protocol version from sdk-protocol-version.json.
* @returns The protocol version number
*/
export declare function getSdkProtocolVersion(): number;
/**
* Copilot Session - represents a single conversation session with the Copilot CLI.
* @module session
*/
import type { MessageConnection } from "vscode-jsonrpc/node";
import type { MessageOptions, PermissionHandler, PermissionRequestResult, SessionEvent, SessionEventHandler, Tool, ToolHandler } from "./types.js";
/**
* Represents a single conversation session with the Copilot CLI.
*
* A session maintains conversation state, handles events, and manages tool execution.
* Sessions are created via {@link CopilotClient.createSession} or resumed via
* {@link CopilotClient.resumeSession}.
*
* @example
* ```typescript
* const session = await client.createSession({ model: "gpt-4" });
*
* // Subscribe to events
* const unsubscribe = session.on((event) => {
* if (event.type === "assistant.message") {
* console.log(event.data.content);
* }
* });
*
* // Send a message
* await session.send({ prompt: "Hello, world!" });
*
* // Clean up
* unsubscribe();
* await session.destroy();
* ```
*/
export declare class CopilotSession {
readonly sessionId: string;
private connection;
private eventHandlers;
private toolHandlers;
private permissionHandler?;
/**
* Creates a new CopilotSession instance.
*
* @param sessionId - The unique identifier for this session
* @param connection - The JSON-RPC message connection to the Copilot CLI
* @internal This constructor is internal. Use {@link CopilotClient.createSession} to create sessions.
*/
constructor(sessionId: string, connection: MessageConnection);
/**
* Sends a message to this session and waits for the response.
*
* The message is processed asynchronously. Subscribe to events via {@link on}
* to receive streaming responses and other session events.
*
* @param options - The message options including the prompt and optional attachments
* @returns A promise that resolves with the message ID of the response
* @throws Error if the session has been destroyed or the connection fails
*
* @example
* ```typescript
* const messageId = await session.send({
* prompt: "Explain this code",
* attachments: [{ type: "file", path: "./src/index.ts" }]
* });
* ```
*/
send(options: MessageOptions): Promise<string>;
/**
* Subscribes to events from this session.
*
* Events include assistant messages, tool executions, errors, and session state changes.
* Multiple handlers can be registered and will all receive events.
*
* @param handler - A callback function that receives session events
* @returns A function that, when called, unsubscribes the handler
*
* @example
* ```typescript
* const unsubscribe = session.on((event) => {
* switch (event.type) {
* case "assistant.message":
* console.log("Assistant:", event.data.content);
* break;
* case "session.error":
* console.error("Error:", event.data.message);
* break;
* }
* });
*
* // Later, to stop receiving events:
* unsubscribe();
* ```
*/
on(handler: SessionEventHandler): () => void;
/**
* Dispatches an event to all registered handlers.
*
* @param event - The session event to dispatch
* @internal This method is for internal use by the SDK.
*/
_dispatchEvent(event: SessionEvent): void;
/**
* Registers custom tool handlers for this session.
*
* Tools allow the assistant to execute custom functions. When the assistant
* invokes a tool, the corresponding handler is called with the tool arguments.
*
* @param tools - An array of tool definitions with their handlers, or undefined to clear all tools
* @internal This method is typically called internally when creating a session with tools.
*/
registerTools(tools?: Tool[]): void;
/**
* Retrieves a registered tool handler by name.
*
* @param name - The name of the tool to retrieve
* @returns The tool handler if found, or undefined
* @internal This method is for internal use by the SDK.
*/
getToolHandler(name: string): ToolHandler | undefined;
/**
* Registers a handler for permission requests.
*
* When the assistant needs permission to perform certain actions (e.g., file operations),
* this handler is called to approve or deny the request.
*
* @param handler - The permission handler function, or undefined to remove the handler
* @internal This method is typically called internally when creating a session.
*/
registerPermissionHandler(handler?: PermissionHandler): void;
/**
* Handles a permission request from the Copilot CLI.
*
* @param request - The permission request data from the CLI
* @returns A promise that resolves with the permission decision
* @internal This method is for internal use by the SDK.
*/
_handlePermissionRequest(request: unknown): Promise<PermissionRequestResult>;
/**
* Retrieves all events and messages from this session's history.
*
* This returns the complete conversation history including user messages,
* assistant responses, tool executions, and other session events.
*
* @returns A promise that resolves with an array of all session events
* @throws Error if the session has been destroyed or the connection fails
*
* @example
* ```typescript
* const events = await session.getMessages();
* for (const event of events) {
* if (event.type === "assistant.message") {
* console.log("Assistant:", event.data.content);
* }
* }
* ```
*/
getMessages(): Promise<SessionEvent[]>;
/**
* Destroys this session and releases all associated resources.
*
* After calling this method, the session can no longer be used. All event
* handlers and tool handlers are cleared. To continue the conversation,
* use {@link CopilotClient.resumeSession} with the session ID.
*
* @returns A promise that resolves when the session is destroyed
* @throws Error if the connection fails
*
* @example
* ```typescript
* // Clean up when done
* await session.destroy();
* ```
*/
destroy(): Promise<void>;
/**
* Aborts the currently processing message in this session.
*
* Use this to cancel a long-running request. The session remains valid
* and can continue to be used for new messages.
*
* @returns A promise that resolves when the abort request is acknowledged
* @throws Error if the session has been destroyed or the connection fails
*
* @example
* ```typescript
* // Start a long-running request
* const messagePromise = session.send({ prompt: "Write a very long story..." });
*
* // Abort after 5 seconds
* setTimeout(async () => {
* await session.abort();
* }, 5000);
* ```
*/
abort(): Promise<void>;
}
/**
* Type definitions for the Copilot SDK
*/
import type { SessionEvent as GeneratedSessionEvent } from "./generated/session-events.js";
export type SessionEvent = GeneratedSessionEvent;
/**
* Options for creating a CopilotClient
*/
export interface CopilotClientOptions {
/**
* Path to the Copilot CLI executable
* @default "copilot" (searches PATH)
*/
cliPath?: string;
/**
* Extra arguments to pass to the CLI executable (inserted before SDK-managed args)
*/
cliArgs?: string[];
/**
* Working directory for the CLI process
* If not set, inherits the current process's working directory
*/
cwd?: string;
/**
* Port for the CLI server (TCP mode only)
* @default 0 (random available port)
*/
port?: number;
/**
* Use stdio transport instead of TCP
* When true, communicates with CLI via stdin/stdout pipes
* @default true
*/
useStdio?: boolean;
/**
* URL of an existing Copilot CLI server to connect to over TCP
* When provided, the client will not spawn a CLI process
* Format: "host:port" or "http://host:port" or just "port" (defaults to localhost)
* Examples: "localhost:8080", "http://127.0.0.1:9000", "8080"
* Mutually exclusive with cliPath, useStdio
*/
cliUrl?: string;
/**
* Log level for the CLI server
*/
logLevel?: "none" | "error" | "warning" | "info" | "debug" | "all";
/**
* Auto-start the CLI server on first use
* @default true
*/
autoStart?: boolean;
/**
* Auto-restart the CLI server if it crashes
* @default true
*/
autoRestart?: boolean;
/**
* Environment variables to pass to the CLI process. If not set, inherits process.env.
*/
env?: Record<string, string | undefined>;
}
/**
* Configuration for creating a session
*/
export type ToolResultType = "success" | "failure" | "rejected" | "denied";
export type ToolBinaryResult = {
data: string;
mimeType: string;
type: string;
description?: string;
};
export type ToolResultObject = {
textResultForLlm: string;
binaryResultsForLlm?: ToolBinaryResult[];
resultType: ToolResultType;
error?: string;
sessionLog?: string;
toolTelemetry?: Record<string, unknown>;
};
export type ToolResult = string | ToolResultObject;
export interface ToolInvocation {
sessionId: string;
toolCallId: string;
toolName: string;
arguments: unknown;
}
export type ToolHandler<TArgs = unknown> = (args: TArgs, invocation: ToolInvocation) => Promise<unknown> | unknown;
/**
* Zod-like schema interface for type inference.
* Any object with `toJSONSchema()` method is treated as a Zod schema.
*/
export interface ZodSchema<T = unknown> {
_output: T;
toJSONSchema(): Record<string, unknown>;
}
/**
* Tool definition. Parameters can be either:
* - A Zod schema (provides type inference for handler)
* - A raw JSON schema object
* - Omitted (no parameters)
*/
export interface Tool<TArgs = unknown> {
name: string;
description?: string;
parameters?: ZodSchema<TArgs> | Record<string, unknown>;
handler: ToolHandler<TArgs>;
}
/**
* Helper to define a tool with Zod schema and get type inference for the handler.
* Without this helper, TypeScript cannot infer handler argument types from Zod schemas.
*/
export declare function defineTool<T = unknown>(name: string, config: {
description?: string;
parameters?: ZodSchema<T> | Record<string, unknown>;
handler: ToolHandler<T>;
}): Tool<T>;
export interface ToolCallRequestPayload {
sessionId: string;
toolCallId: string;
toolName: string;
arguments: unknown;
}
export interface ToolCallResponsePayload {
result: ToolResult;
}
/**
* Append mode: Use CLI foundation with optional appended content (default).
*/
export interface SystemMessageAppendConfig {
mode?: "append";
/**
* Additional instructions appended after SDK-managed sections.
*/
content?: string;
}
/**
* Replace mode: Use caller-provided system message entirely.
* Removes all SDK guardrails including security restrictions.
*/
export interface SystemMessageReplaceConfig {
mode: "replace";
/**
* Complete system message content.
* Replaces the entire SDK-managed system message.
*/
content: string;
}
/**
* System message configuration for session creation.
* - Append mode (default): SDK foundation + optional custom content
* - Replace mode: Full control, caller provides entire system message
*/
export type SystemMessageConfig = SystemMessageAppendConfig | SystemMessageReplaceConfig;
/**
* Permission request types from the server
*/
export interface PermissionRequest {
kind: "shell" | "write" | "mcp" | "read" | "url";
toolCallId?: string;
[key: string]: unknown;
}
export interface PermissionRequestResult {
kind: "approved" | "denied-by-rules" | "denied-no-approval-rule-and-could-not-request-from-user" | "denied-interactively-by-user";
rules?: unknown[];
}
export type PermissionHandler = (request: PermissionRequest, invocation: {
sessionId: string;
}) => Promise<PermissionRequestResult> | PermissionRequestResult;
/**
* Base interface for MCP server configuration.
*/
interface MCPServerConfigBase {
/**
* List of tools to include from this server. [] means none. "*" means all.
*/
tools: string[];
/**
* Indicates "remote" or "local" server type.
* If not specified, defaults to "local".
*/
type?: string;
/**
* Optional timeout in milliseconds for tool calls to this server.
*/
timeout?: number;
}
/**
* Configuration for a local/stdio MCP server.
*/
export interface MCPLocalServerConfig extends MCPServerConfigBase {
type?: "local" | "stdio";
command: string;
args: string[];
/**
* Environment variables to pass to the server.
*/
env?: Record<string, string>;
cwd?: string;
}
/**
* Configuration for a remote MCP server (HTTP or SSE).
*/
export interface MCPRemoteServerConfig extends MCPServerConfigBase {
type: "http" | "sse";
/**
* URL of the remote server.
*/
url: string;
/**
* Optional HTTP headers to include in requests.
*/
headers?: Record<string, string>;
}
/**
* Union type for MCP server configurations.
*/
export type MCPServerConfig = MCPLocalServerConfig | MCPRemoteServerConfig;
/**
* Configuration for a custom agent.
*/
export interface CustomAgentConfig {
/**
* Unique name of the custom agent.
*/
name: string;
/**
* Display name for UI purposes.
*/
displayName?: string;
/**
* Description of what the agent does.
*/
description?: string;
/**
* List of tool names the agent can use.
* Use null or undefined for all tools.
*/
tools?: string[] | null;
/**
* The prompt content for the agent.
*/
prompt: string;
/**
* MCP servers specific to this agent.
*/
mcpServers?: Record<string, MCPServerConfig>;
/**
* Whether the agent should be available for model inference.
* @default true
*/
infer?: boolean;
}
export interface SessionConfig {
/**
* Optional custom session ID
* If not provided, server will generate one
*/
sessionId?: string;
/**
* Model to use for this session
*/
model?: string;
/**
* Tools exposed to the CLI server
*/
tools?: Tool<any>[];
/**
* System message configuration
* Controls how the system prompt is constructed
*/
systemMessage?: SystemMessageConfig;
/**
* List of tool names to allow. When specified, only these tools will be available.
* Takes precedence over excludedTools.
*/
availableTools?: string[];
/**
* List of tool names to disable. All other tools remain available.
* Ignored if availableTools is specified.
*/
excludedTools?: string[];
/**
* Custom provider configuration (BYOK - Bring Your Own Key).
* When specified, uses the provided API endpoint instead of the Copilot API.
*/
provider?: ProviderConfig;
/**
* Handler for permission requests from the server.
* When provided, the server will call this handler to request permission for operations.
*/
onPermissionRequest?: PermissionHandler;
streaming?: boolean;
/**
* MCP server configurations for the session.
* Keys are server names, values are server configurations.
*/
mcpServers?: Record<string, MCPServerConfig>;
/**
* Custom agent configurations for the session.
*/
customAgents?: CustomAgentConfig[];
}
/**
* Configuration for resuming a session
*/
export type ResumeSessionConfig = Pick<SessionConfig, "tools" | "provider" | "streaming" | "onPermissionRequest" | "mcpServers" | "customAgents">;
/**
* Configuration for a custom API provider.
*/
export interface ProviderConfig {
/**
* Provider type. Defaults to "openai" for generic OpenAI-compatible APIs.
*/
type?: "openai" | "azure" | "anthropic";
/**
* API format (openai/azure only). Defaults to "completions".
*/
wireApi?: "completions" | "responses";
/**
* API endpoint URL
*/
baseUrl: string;
/**
* API key. Optional for local providers like Ollama.
*/
apiKey?: string;
/**
* Bearer token for authentication. Sets the Authorization header directly.
* Use this for services requiring bearer token auth instead of API key.
* Takes precedence over apiKey when both are set.
*/
bearerToken?: string;
/**
* Azure-specific options
*/
azure?: {
/**
* API version. Defaults to "2024-10-21".
*/
apiVersion?: string;
};
}
/**
* Options for sending a message to a session
*/
export interface MessageOptions {
/**
* The prompt/message to send
*/
prompt: string;
/**
* File or directory attachments
*/
attachments?: Array<{
type: "file" | "directory";
path: string;
displayName?: string;
}>;
/**
* Message delivery mode
* - "enqueue": Add to queue (default)
* - "immediate": Send immediately
*/
mode?: "enqueue" | "immediate";
}
/**
* Event handler callback type
*/
export type SessionEventHandler = (event: SessionEvent) => void;
/**
* Connection state
*/
export type ConnectionState = "disconnected" | "connecting" | "connected" | "error";
/**
* Metadata about a session
*/
export interface SessionMetadata {
sessionId: string;
startTime: Date;
modifiedTime: Date;
summary?: string;
isRemote: boolean;
}
export {};