@github/copilot-sdk
Advanced tools
+32
-35
@@ -275,2 +275,19 @@ "use strict"; | ||
| } | ||
| setupSessionFs(session, config) { | ||
| if (!this.sessionFsConfig) { | ||
| return; | ||
| } | ||
| if (!config.createSessionFsHandler) { | ||
| throw new Error( | ||
| "createSessionFsHandler is required in session config when sessionFs is enabled in client options." | ||
| ); | ||
| } | ||
| const provider = config.createSessionFsHandler(session); | ||
| if (this.sessionFsConfig.capabilities?.sqlite && !provider.sqlite) { | ||
| throw new Error( | ||
| "SessionFsConfig declares capabilities.sqlite but the provider does not implement sqlite." | ||
| ); | ||
| } | ||
| session.clientSessionApis.sessionFs = (0, import_sessionFsProvider.createSessionFsAdapter)(provider); | ||
| } | ||
| /** | ||
@@ -309,3 +326,4 @@ * Starts the CLI server and establishes a connection. | ||
| sessionStatePath: this.sessionFsConfig.sessionStatePath, | ||
| conventions: this.sessionFsConfig.conventions | ||
| conventions: this.sessionFsConfig.conventions, | ||
| capabilities: this.sessionFsConfig.capabilities | ||
| }); | ||
@@ -507,7 +525,2 @@ } | ||
| async createSession(config) { | ||
| if (!config?.onPermissionRequest) { | ||
| throw new Error( | ||
| "An onPermissionRequest handler is required when creating a session. For example, to allow all permissions, use { onPermissionRequest: approveAll }." | ||
| ); | ||
| } | ||
| if (!this.connection) { | ||
@@ -555,13 +568,3 @@ if (this.options.autoStart) { | ||
| this.sessions.set(sessionId, session); | ||
| if (this.sessionFsConfig) { | ||
| if (config.createSessionFsHandler) { | ||
| session.clientSessionApis.sessionFs = (0, import_sessionFsProvider.createSessionFsAdapter)( | ||
| config.createSessionFsHandler(session) | ||
| ); | ||
| } else { | ||
| throw new Error( | ||
| "createSessionFsHandler is required in session config when sessionFs is enabled in client options." | ||
| ); | ||
| } | ||
| } | ||
| this.setupSessionFs(session, config); | ||
| try { | ||
@@ -611,3 +614,5 @@ const response = await this.connection.sendRequest("session.create", { | ||
| infiniteSessions: config.infiniteSessions, | ||
| gitHubToken: config.gitHubToken | ||
| gitHubToken: config.gitHubToken, | ||
| remoteSession: config.remoteSession, | ||
| cloud: config.cloud | ||
| }); | ||
@@ -648,7 +653,2 @@ const { workspacePath, capabilities } = response; | ||
| async resumeSession(sessionId, config) { | ||
| if (!config?.onPermissionRequest) { | ||
| throw new Error( | ||
| "An onPermissionRequest handler is required when resuming a session. For example, to allow all permissions, use { onPermissionRequest: approveAll }." | ||
| ); | ||
| } | ||
| if (!this.connection) { | ||
@@ -695,13 +695,3 @@ if (this.options.autoStart) { | ||
| this.sessions.set(sessionId, session); | ||
| if (this.sessionFsConfig) { | ||
| if (config.createSessionFsHandler) { | ||
| session.clientSessionApis.sessionFs = (0, import_sessionFsProvider.createSessionFsAdapter)( | ||
| config.createSessionFsHandler(session) | ||
| ); | ||
| } else { | ||
| throw new Error( | ||
| "createSessionFsHandler is required in session config when sessionFs is enabled in client options." | ||
| ); | ||
| } | ||
| } | ||
| this.setupSessionFs(session, config); | ||
| try { | ||
@@ -753,3 +743,4 @@ const response = await this.connection.sendRequest("session.resume", { | ||
| continuePendingWork: config.continuePendingWork, | ||
| gitHubToken: config.gitHubToken | ||
| gitHubToken: config.gitHubToken, | ||
| remoteSession: config.remoteSession | ||
| }); | ||
@@ -1325,3 +1316,8 @@ const { workspacePath, capabilities } = response; | ||
| this.socket = new import_node_net.Socket(); | ||
| const connectionTimeout = setTimeout(() => { | ||
| this.socket?.destroy(); | ||
| reject(new Error("Timeout connecting to CLI server")); | ||
| }, 1e4); | ||
| this.socket.connect(this.actualPort, this.actualHost, () => { | ||
| clearTimeout(connectionTimeout); | ||
| this.connection = (0, import_node.createMessageConnection)( | ||
@@ -1336,2 +1332,3 @@ new import_node.StreamMessageReader(this.socket), | ||
| this.socket.on("error", (error) => { | ||
| clearTimeout(connectionTimeout); | ||
| reject(new Error(`Failed to connect to CLI server: ${error.message}`)); | ||
@@ -1338,0 +1335,0 @@ }); |
@@ -400,4 +400,4 @@ "use strict"; | ||
| * | ||
| * Tools allow the assistant to execute custom functions. When the assistant | ||
| * invokes a tool, the corresponding handler is called with the tool arguments. | ||
| * Tools with handlers allow the assistant to execute custom functions automatically. | ||
| * Declaration-only tools are surfaced as events and left pending for the consumer. | ||
| * | ||
@@ -413,3 +413,5 @@ * @param tools - An array of tool definitions with their handlers, or undefined to clear all tools | ||
| for (const tool of tools) { | ||
| this.toolHandlers.set(tool.name, tool.handler); | ||
| if (tool.handler) { | ||
| this.toolHandlers.set(tool.name, tool.handler); | ||
| } | ||
| } | ||
@@ -416,0 +418,0 @@ } |
@@ -24,2 +24,14 @@ "use strict"; | ||
| module.exports = __toCommonJS(sessionFsProvider_exports); | ||
| function normalizeSqliteParams(params) { | ||
| if (!params) { | ||
| return void 0; | ||
| } | ||
| const normalized = {}; | ||
| for (const [key, value] of Object.entries(params)) { | ||
| if (value !== void 0) { | ||
| normalized[key] = value; | ||
| } | ||
| } | ||
| return normalized; | ||
| } | ||
| function createSessionFsAdapter(provider) { | ||
@@ -111,2 +123,24 @@ return { | ||
| } | ||
| }, | ||
| // Unlike the FS methods above, SQLite methods let errors propagate to the JSON-RPC layer | ||
| // rather than catching and mapping via toSessionFsError. The FS error mapping is specifically | ||
| // for translating Node.js errno codes (e.g., ENOENT) into SessionFsError, which isn't | ||
| // meaningful for SQL errors. Letting exceptions propagate preserves the original error | ||
| // message in the JSON-RPC error response. | ||
| sqliteQuery: async ({ queryType, query, params: bindParams }) => { | ||
| if (!provider.sqlite) { | ||
| throw new Error("SQLite is not supported by this provider"); | ||
| } | ||
| const result = await provider.sqlite.query( | ||
| queryType, | ||
| query, | ||
| normalizeSqliteParams(bindParams) | ||
| ); | ||
| return result ?? { rows: [], columns: [], rowsAffected: 0 }; | ||
| }, | ||
| sqliteExists: async () => { | ||
| if (!provider.sqlite) { | ||
| throw new Error("SQLite is not supported by this provider"); | ||
| } | ||
| return { exists: await provider.sqlite.exists() }; | ||
| } | ||
@@ -113,0 +147,0 @@ }; |
+2
-1
@@ -102,2 +102,3 @@ import { createServerRpc } from "./generated/rpc.js"; | ||
| private validateSessionFsConfig; | ||
| private setupSessionFs; | ||
| /** | ||
@@ -255,3 +256,3 @@ * Starts the CLI server and establishes a connection. | ||
| message: string; | ||
| timestamp: number; | ||
| timestamp: string; | ||
| protocolVersion?: number; | ||
@@ -258,0 +259,0 @@ }>; |
+32
-35
@@ -261,2 +261,19 @@ import { spawn } from "node:child_process"; | ||
| } | ||
| setupSessionFs(session, config) { | ||
| if (!this.sessionFsConfig) { | ||
| return; | ||
| } | ||
| if (!config.createSessionFsHandler) { | ||
| throw new Error( | ||
| "createSessionFsHandler is required in session config when sessionFs is enabled in client options." | ||
| ); | ||
| } | ||
| const provider = config.createSessionFsHandler(session); | ||
| if (this.sessionFsConfig.capabilities?.sqlite && !provider.sqlite) { | ||
| throw new Error( | ||
| "SessionFsConfig declares capabilities.sqlite but the provider does not implement sqlite." | ||
| ); | ||
| } | ||
| session.clientSessionApis.sessionFs = createSessionFsAdapter(provider); | ||
| } | ||
| /** | ||
@@ -295,3 +312,4 @@ * Starts the CLI server and establishes a connection. | ||
| sessionStatePath: this.sessionFsConfig.sessionStatePath, | ||
| conventions: this.sessionFsConfig.conventions | ||
| conventions: this.sessionFsConfig.conventions, | ||
| capabilities: this.sessionFsConfig.capabilities | ||
| }); | ||
@@ -493,7 +511,2 @@ } | ||
| async createSession(config) { | ||
| if (!config?.onPermissionRequest) { | ||
| throw new Error( | ||
| "An onPermissionRequest handler is required when creating a session. For example, to allow all permissions, use { onPermissionRequest: approveAll }." | ||
| ); | ||
| } | ||
| if (!this.connection) { | ||
@@ -541,13 +554,3 @@ if (this.options.autoStart) { | ||
| this.sessions.set(sessionId, session); | ||
| if (this.sessionFsConfig) { | ||
| if (config.createSessionFsHandler) { | ||
| session.clientSessionApis.sessionFs = createSessionFsAdapter( | ||
| config.createSessionFsHandler(session) | ||
| ); | ||
| } else { | ||
| throw new Error( | ||
| "createSessionFsHandler is required in session config when sessionFs is enabled in client options." | ||
| ); | ||
| } | ||
| } | ||
| this.setupSessionFs(session, config); | ||
| try { | ||
@@ -597,3 +600,5 @@ const response = await this.connection.sendRequest("session.create", { | ||
| infiniteSessions: config.infiniteSessions, | ||
| gitHubToken: config.gitHubToken | ||
| gitHubToken: config.gitHubToken, | ||
| remoteSession: config.remoteSession, | ||
| cloud: config.cloud | ||
| }); | ||
@@ -634,7 +639,2 @@ const { workspacePath, capabilities } = response; | ||
| async resumeSession(sessionId, config) { | ||
| if (!config?.onPermissionRequest) { | ||
| throw new Error( | ||
| "An onPermissionRequest handler is required when resuming a session. For example, to allow all permissions, use { onPermissionRequest: approveAll }." | ||
| ); | ||
| } | ||
| if (!this.connection) { | ||
@@ -681,13 +681,3 @@ if (this.options.autoStart) { | ||
| this.sessions.set(sessionId, session); | ||
| if (this.sessionFsConfig) { | ||
| if (config.createSessionFsHandler) { | ||
| session.clientSessionApis.sessionFs = createSessionFsAdapter( | ||
| config.createSessionFsHandler(session) | ||
| ); | ||
| } else { | ||
| throw new Error( | ||
| "createSessionFsHandler is required in session config when sessionFs is enabled in client options." | ||
| ); | ||
| } | ||
| } | ||
| this.setupSessionFs(session, config); | ||
| try { | ||
@@ -739,3 +729,4 @@ const response = await this.connection.sendRequest("session.resume", { | ||
| continuePendingWork: config.continuePendingWork, | ||
| gitHubToken: config.gitHubToken | ||
| gitHubToken: config.gitHubToken, | ||
| remoteSession: config.remoteSession | ||
| }); | ||
@@ -1311,3 +1302,8 @@ const { workspacePath, capabilities } = response; | ||
| this.socket = new Socket(); | ||
| const connectionTimeout = setTimeout(() => { | ||
| this.socket?.destroy(); | ||
| reject(new Error("Timeout connecting to CLI server")); | ||
| }, 1e4); | ||
| this.socket.connect(this.actualPort, this.actualHost, () => { | ||
| clearTimeout(connectionTimeout); | ||
| this.connection = createMessageConnection( | ||
@@ -1322,2 +1318,3 @@ new StreamMessageReader(this.socket), | ||
| this.socket.on("error", (error) => { | ||
| clearTimeout(connectionTimeout); | ||
| reject(new Error(`Failed to connect to CLI server: ${error.message}`)); | ||
@@ -1324,0 +1321,0 @@ }); |
+2
-1
@@ -9,2 +9,3 @@ /** | ||
| export { defineTool, approveAll, convertMcpCallToolResult, createSessionFsAdapter, SYSTEM_PROMPT_SECTIONS, } from "./types.js"; | ||
| export type { CommandContext, CommandDefinition, CommandHandler, AutoModeSwitchHandler, AutoModeSwitchRequest, AutoModeSwitchResponse, ConnectionState, CopilotClientOptions, CustomAgentConfig, ElicitationFieldValue, ElicitationHandler, ElicitationParams, ElicitationContext, ElicitationResult, ElicitationSchema, ElicitationSchemaField, ExitPlanModeHandler, ExitPlanModeRequest, ExitPlanModeResult, ForegroundSessionInfo, GetAuthStatusResponse, GetStatusResponse, InfiniteSessionConfig, InputOptions, MCPStdioServerConfig, MCPHTTPServerConfig, MCPServerConfig, DefaultAgentConfig, MessageOptions, ModelBilling, ModelCapabilities, ModelCapabilitiesOverride, ModelInfo, ModelPolicy, PermissionHandler, PermissionRequest, PermissionRequestResult, ProviderConfig, ResumeSessionConfig, SectionOverride, SectionOverrideAction, SectionTransformFn, SessionCapabilities, SessionConfig, SessionEvent, SessionEventHandler, SessionEventPayload, SessionEventType, SessionLifecycleEvent, SessionLifecycleEventType, SessionLifecycleHandler, SessionContext, SessionListFilter, SessionMetadata, SessionUiApi, SessionFsConfig, SessionFsProvider, SessionFsFileInfo, SystemMessageAppendConfig, SystemMessageConfig, SystemMessageCustomizeConfig, SystemMessageReplaceConfig, SystemPromptSection, TelemetryConfig, TraceContext, TraceContextProvider, Tool, ToolHandler, ToolInvocation, ToolResultObject, TypedSessionEventHandler, TypedSessionLifecycleHandler, ZodSchema, } from "./types.js"; | ||
| export type * from "./generated/session-events.js"; | ||
| export type { CommandContext, CommandDefinition, CommandHandler, CloudSessionOptions, CloudSessionRepository, AutoModeSwitchHandler, AutoModeSwitchRequest, AutoModeSwitchResponse, ConnectionState, CopilotClientOptions, CustomAgentConfig, ElicitationFieldValue, ElicitationHandler, ElicitationParams, ElicitationContext, ElicitationResult, ElicitationSchema, ElicitationSchemaField, ExitPlanModeHandler, ExitPlanModeRequest, ExitPlanModeResult, ForegroundSessionInfo, GetAuthStatusResponse, GetStatusResponse, InfiniteSessionConfig, InputOptions, MCPStdioServerConfig, MCPHTTPServerConfig, MCPServerConfig, DefaultAgentConfig, MessageOptions, ModelBilling, ModelCapabilities, ModelCapabilitiesOverride, ModelInfo, ModelPolicy, PermissionHandler, PermissionRequest, PermissionRequestResult, ProviderConfig, RemoteSessionMode, ResumeSessionConfig, SectionOverride, SectionOverrideAction, SectionTransformFn, SessionCapabilities, SessionConfig, SessionEvent, SessionEventHandler, SessionEventPayload, SessionEventType, SessionLifecycleEvent, SessionLifecycleEventType, SessionLifecycleHandler, SessionContext, SessionListFilter, SessionMetadata, SessionUiApi, SessionFsConfig, SessionFsProvider, SessionFsFileInfo, SessionFsSqliteQueryResult, SessionFsSqliteQueryType, SessionFsSqliteProvider, SystemMessageAppendConfig, SystemMessageConfig, SystemMessageCustomizeConfig, SystemMessageReplaceConfig, SystemPromptSection, TelemetryConfig, TraceContext, TraceContextProvider, Tool, ToolHandler, ToolInvocation, ToolResultObject, TypedSessionEventHandler, TypedSessionLifecycleHandler, ZodSchema, } from "./types.js"; |
@@ -219,4 +219,4 @@ /** | ||
| * | ||
| * Tools allow the assistant to execute custom functions. When the assistant | ||
| * invokes a tool, the corresponding handler is called with the tool arguments. | ||
| * Tools with handlers allow the assistant to execute custom functions automatically. | ||
| * Declaration-only tools are surfaced as events and left pending for the consumer. | ||
| * | ||
@@ -223,0 +223,0 @@ * @param tools - An array of tool definitions with their handlers, or undefined to clear all tools |
+5
-3
@@ -376,4 +376,4 @@ import { ConnectionError, ResponseError } from "vscode-jsonrpc/node.js"; | ||
| * | ||
| * Tools allow the assistant to execute custom functions. When the assistant | ||
| * invokes a tool, the corresponding handler is called with the tool arguments. | ||
| * Tools with handlers allow the assistant to execute custom functions automatically. | ||
| * Declaration-only tools are surfaced as events and left pending for the consumer. | ||
| * | ||
@@ -389,3 +389,5 @@ * @param tools - An array of tool definitions with their handlers, or undefined to clear all tools | ||
| for (const tool of tools) { | ||
| this.toolHandlers.set(tool.name, tool.handler); | ||
| if (tool.handler) { | ||
| this.toolHandlers.set(tool.name, tool.handler); | ||
| } | ||
| } | ||
@@ -392,0 +394,0 @@ } |
@@ -1,2 +0,3 @@ | ||
| import type { SessionFsHandler, SessionFsStatResult, SessionFsReaddirWithTypesEntry } from "./generated/rpc.js"; | ||
| import type { SessionFsHandler, SessionFsStatResult, SessionFsReaddirWithTypesEntry, SessionFsSqliteQueryResult as GeneratedSqliteQueryResult, SessionFsSqliteQueryType } from "./generated/rpc.js"; | ||
| export type { SessionFsSqliteQueryType }; | ||
| /** | ||
@@ -9,2 +10,26 @@ * File metadata returned by {@link SessionFsProvider.stat}. | ||
| /** | ||
| * Result of a SQLite query execution via {@link SessionFsSqliteProvider.query}. | ||
| * Same shape as the generated {@link GeneratedSqliteQueryResult} but without the | ||
| * `error` field, since providers signal errors by throwing. | ||
| */ | ||
| export type SessionFsSqliteQueryResult = Omit<GeneratedSqliteQueryResult, "error">; | ||
| /** | ||
| * SQLite operations for the per-session database. | ||
| * Implementers provide query execution and existence checking. | ||
| */ | ||
| export interface SessionFsSqliteProvider { | ||
| /** | ||
| * Execute a SQLite query against the per-session database. | ||
| * | ||
| * @param queryType - How to execute: `"exec"` for DDL/multi-statement, `"query"` for SELECT, `"run"` for INSERT/UPDATE/DELETE. | ||
| * @param query - SQL query to execute. | ||
| * @param params - Optional named bind parameters. | ||
| */ | ||
| query(queryType: SessionFsSqliteQueryType, query: string, params?: Record<string, string | number | null>): Promise<SessionFsSqliteQueryResult | undefined>; | ||
| /** | ||
| * Check whether the per-session database already exists, without creating it. | ||
| */ | ||
| exists(): Promise<boolean>; | ||
| } | ||
| /** | ||
| * Interface for session filesystem providers. Implementers use idiomatic | ||
@@ -39,2 +64,4 @@ * TypeScript patterns: throw on error, return values directly. Use | ||
| rename(src: string, dest: string): Promise<void>; | ||
| /** Per-session SQLite database operations. Optional — omit if the provider does not support SQLite. */ | ||
| sqlite?: SessionFsSqliteProvider; | ||
| } | ||
@@ -41,0 +68,0 @@ /** |
@@ -0,1 +1,13 @@ | ||
| function normalizeSqliteParams(params) { | ||
| if (!params) { | ||
| return void 0; | ||
| } | ||
| const normalized = {}; | ||
| for (const [key, value] of Object.entries(params)) { | ||
| if (value !== void 0) { | ||
| normalized[key] = value; | ||
| } | ||
| } | ||
| return normalized; | ||
| } | ||
| function createSessionFsAdapter(provider) { | ||
@@ -87,2 +99,24 @@ return { | ||
| } | ||
| }, | ||
| // Unlike the FS methods above, SQLite methods let errors propagate to the JSON-RPC layer | ||
| // rather than catching and mapping via toSessionFsError. The FS error mapping is specifically | ||
| // for translating Node.js errno codes (e.g., ENOENT) into SessionFsError, which isn't | ||
| // meaningful for SQL errors. Letting exceptions propagate preserves the original error | ||
| // message in the JSON-RPC error response. | ||
| sqliteQuery: async ({ queryType, query, params: bindParams }) => { | ||
| if (!provider.sqlite) { | ||
| throw new Error("SQLite is not supported by this provider"); | ||
| } | ||
| const result = await provider.sqlite.query( | ||
| queryType, | ||
| query, | ||
| normalizeSqliteParams(bindParams) | ||
| ); | ||
| return result ?? { rows: [], columns: [], rowsAffected: 0 }; | ||
| }, | ||
| sqliteExists: async () => { | ||
| if (!provider.sqlite) { | ||
| throw new Error("SQLite is not supported by this provider"); | ||
| } | ||
| return { exists: await provider.sqlite.exists() }; | ||
| } | ||
@@ -89,0 +123,0 @@ }; |
+68
-9
@@ -7,2 +7,4 @@ /** | ||
| import type { CopilotSession } from "./session.js"; | ||
| import type { RemoteSessionMode } from "./generated/rpc.js"; | ||
| export type { RemoteSessionMode } from "./generated/rpc.js"; | ||
| export type SessionEvent = GeneratedSessionEvent; | ||
@@ -12,2 +14,5 @@ export type { SessionFsProvider } from "./sessionFsProvider.js"; | ||
| export type { SessionFsFileInfo } from "./sessionFsProvider.js"; | ||
| export type { SessionFsSqliteQueryResult } from "./sessionFsProvider.js"; | ||
| export type { SessionFsSqliteQueryType } from "./sessionFsProvider.js"; | ||
| export type { SessionFsSqliteProvider } from "./sessionFsProvider.js"; | ||
| /** | ||
@@ -204,3 +209,3 @@ * Options for creating a CopilotClient | ||
| mimeType: string; | ||
| type: string; | ||
| type: "image" | "resource"; | ||
| description?: string; | ||
@@ -218,2 +223,16 @@ }; | ||
| /** | ||
| * GitHub repository metadata to associate with a cloud session. | ||
| */ | ||
| export interface CloudSessionRepository { | ||
| owner: string; | ||
| name: string; | ||
| branch?: string; | ||
| } | ||
| /** | ||
| * Options for creating a remote session in the cloud. | ||
| */ | ||
| export interface CloudSessionOptions { | ||
| repository?: CloudSessionRepository; | ||
| } | ||
| /** | ||
| * Content block types within an MCP CallToolResult. | ||
@@ -276,2 +295,6 @@ */ | ||
| * - Omitted (no parameters) | ||
| * | ||
| * If `handler` is omitted, the SDK exposes the declaration but does not | ||
| * automatically invoke the tool. Consumers can resolve tool calls by observing | ||
| * external tool request events and calling the pending-tool RPC. | ||
| */ | ||
@@ -282,3 +305,3 @@ export interface Tool<TArgs = unknown> { | ||
| parameters?: ZodSchema<TArgs> | Record<string, unknown>; | ||
| handler: ToolHandler<TArgs>; | ||
| handler?: ToolHandler<TArgs>; | ||
| /** | ||
@@ -302,3 +325,3 @@ * When true, explicitly indicates this tool is intended to override a built-in tool | ||
| parameters?: ZodSchema<T> | Record<string, unknown>; | ||
| handler: ToolHandler<T>; | ||
| handler?: ToolHandler<T>; | ||
| overridesBuiltInTool?: boolean; | ||
@@ -713,2 +736,5 @@ skipPermission?: boolean; | ||
| export interface BaseHookInput { | ||
| /** The runtime session ID of the session that triggered the hook. | ||
| * For sub-agent hooks this differs from `invocation.sessionId`. */ | ||
| sessionId: string; | ||
| timestamp: number; | ||
@@ -900,3 +926,3 @@ cwd: string; | ||
| command: string; | ||
| args: string[]; | ||
| args?: string[]; | ||
| /** | ||
@@ -968,2 +994,8 @@ * Environment variables to pass to the server. | ||
| skills?: string[]; | ||
| /** | ||
| * Model identifier for this agent (e.g. "claude-haiku-4.5"). | ||
| * When set, the runtime will attempt to use this model for the agent, | ||
| * falling back to the parent session model if unavailable. | ||
| */ | ||
| model?: string; | ||
| } | ||
@@ -1053,3 +1085,4 @@ /** | ||
| /** | ||
| * Tools exposed to the CLI server | ||
| * Tools exposed to the CLI server. Tools without a handler are declaration-only | ||
| * and must be resolved by the consumer via pending external tool request RPCs. | ||
| */ | ||
@@ -1093,6 +1126,7 @@ tools?: Tool<any>[]; | ||
| /** | ||
| * Handler for permission requests from the server. | ||
| * When provided, the server will call this handler to request permission for operations. | ||
| * Optional handler for permission requests from the server. | ||
| * When omitted, permission requests are surfaced as events and left pending for | ||
| * the consumer to resolve via the pending permission RPC. | ||
| */ | ||
| onPermissionRequest: PermissionHandler; | ||
| onPermissionRequest?: PermissionHandler; | ||
| /** | ||
@@ -1192,2 +1226,14 @@ * Handler for user input requests from the agent. | ||
| /** | ||
| * Per-session remote behavior control: | ||
| * - `"off"` — local only, no remote export (default) | ||
| * - `"export"` — export session events to GitHub without enabling remote steering | ||
| * - `"on"` — export to GitHub AND enable remote steering | ||
| */ | ||
| remoteSession?: RemoteSessionMode; | ||
| /** | ||
| * Creates a remote session in the cloud instead of a local session. | ||
| * The optional repository is associated with the cloud session. | ||
| */ | ||
| cloud?: CloudSessionOptions; | ||
| /** | ||
| * Optional event handler that is registered on the session before the | ||
@@ -1211,3 +1257,3 @@ * session.create RPC is issued. This guarantees that early events emitted | ||
| */ | ||
| export type ResumeSessionConfig = Pick<SessionConfig, "clientName" | "model" | "tools" | "commands" | "systemMessage" | "availableTools" | "excludedTools" | "provider" | "enableSessionTelemetry" | "modelCapabilities" | "streaming" | "includeSubAgentStreamingEvents" | "reasoningEffort" | "onPermissionRequest" | "onUserInputRequest" | "onElicitationRequest" | "onExitPlanMode" | "onAutoModeSwitch" | "hooks" | "workingDirectory" | "configDir" | "enableConfigDiscovery" | "mcpServers" | "customAgents" | "defaultAgent" | "agent" | "skillDirectories" | "instructionDirectories" | "disabledSkills" | "infiniteSessions" | "gitHubToken" | "onEvent" | "createSessionFsHandler"> & { | ||
| export type ResumeSessionConfig = Pick<SessionConfig, "clientName" | "model" | "tools" | "commands" | "systemMessage" | "availableTools" | "excludedTools" | "provider" | "enableSessionTelemetry" | "modelCapabilities" | "streaming" | "includeSubAgentStreamingEvents" | "reasoningEffort" | "onPermissionRequest" | "onUserInputRequest" | "onElicitationRequest" | "onExitPlanMode" | "onAutoModeSwitch" | "hooks" | "workingDirectory" | "configDir" | "enableConfigDiscovery" | "mcpServers" | "customAgents" | "defaultAgent" | "agent" | "skillDirectories" | "instructionDirectories" | "disabledSkills" | "infiniteSessions" | "gitHubToken" | "remoteSession" | "onEvent" | "createSessionFsHandler"> & { | ||
| /** | ||
@@ -1401,2 +1447,15 @@ * When true, skips emitting the session.resume event. | ||
| conventions: "windows" | "posix"; | ||
| /** | ||
| * Optional capabilities declared by this provider. | ||
| * The runtime uses these to determine which features are available. | ||
| */ | ||
| capabilities?: { | ||
| /** | ||
| * Whether this provider supports SQLite query/exists operations. | ||
| * When false or omitted, the runtime will not offer SQL tools or | ||
| * todo tracking for sessions using this provider. | ||
| * @default false | ||
| */ | ||
| sqlite?: boolean; | ||
| }; | ||
| } | ||
@@ -1403,0 +1462,0 @@ /** |
+3
-3
@@ -564,8 +564,8 @@ # Copilot CLI Extension Examples | ||
| // request.fullCommandText has the shell command | ||
| return { kind: "approved" }; | ||
| return { kind: "approve-once" }; | ||
| } | ||
| if (request.kind === "write") { | ||
| return { kind: "approved" }; | ||
| return { kind: "approve-once" }; | ||
| } | ||
| return { kind: "denied-by-rules" }; | ||
| return { kind: "reject" }; | ||
| }, | ||
@@ -572,0 +572,0 @@ }); |
+3
-3
@@ -7,3 +7,3 @@ { | ||
| }, | ||
| "version": "1.0.0-beta.4", | ||
| "version": "1.0.0-beta.5", | ||
| "description": "TypeScript SDK for programmatic control of GitHub Copilot CLI via JSON-RPC", | ||
@@ -44,3 +44,3 @@ "main": "./dist/cjs/index.js", | ||
| "lint:fix": "eslint --fix \"src/**/*.ts\" \"test/**/*.ts\"", | ||
| "typecheck": "tsc --noEmit", | ||
| "typecheck": "tsc --noEmit && tsc --noEmit -p tsconfig.test.json", | ||
| "generate": "cd ../scripts/codegen && npm run generate", | ||
@@ -61,3 +61,3 @@ "update:protocol-version": "tsx scripts/update-protocol-version.ts", | ||
| "dependencies": { | ||
| "@github/copilot": "^1.0.46", | ||
| "@github/copilot": "^1.0.51", | ||
| "vscode-jsonrpc": "^8.2.1", | ||
@@ -64,0 +64,0 @@ "zod": "^4.3.6" |
+20
-17
@@ -35,3 +35,3 @@ # Copilot SDK for Node.js/TypeScript | ||
| // Create a session (onPermissionRequest is required) | ||
| // Create a session (onPermissionRequest is optional; approveAll allows every tool) | ||
| const session = await client.createSession({ | ||
@@ -119,7 +119,7 @@ model: "gpt-5", | ||
| - `reasoningEffort?: "low" | "medium" | "high" | "xhigh"` - Reasoning effort level for models that support it. Use `listModels()` to check which models support this option. | ||
| - `tools?: Tool[]` - Custom tools exposed to the CLI | ||
| - `tools?: Tool[]` - Custom tools exposed to the CLI. Tools without `handler` are declaration-only and must be resolved via pending tool-call RPCs. | ||
| - `systemMessage?: SystemMessageConfig` - System message customization (see below) | ||
| - `infiniteSessions?: InfiniteSessionConfig` - Configure automatic context compaction (see below) | ||
| - `provider?: ProviderConfig` - Custom API provider configuration (BYOK - Bring Your Own Key). See [Custom Providers](#custom-providers) section. | ||
| - `onPermissionRequest: PermissionHandler` - **Required.** Handler called before each tool execution to approve or deny it. Use `approveAll` to allow everything, or provide a custom function for fine-grained control. See [Permission Handling](#permission-handling) section. | ||
| - `onPermissionRequest?: PermissionHandler` - Optional handler called before each tool execution to approve or deny it. When omitted, permission requests are emitted as events and left pending for manual resolution. Use `approveAll` to allow everything, or provide a custom function for fine-grained control. See [Permission Handling](#permission-handling) section. | ||
| - `onUserInputRequest?: UserInputHandler` - Handler for user input requests from the agent. Enables the `ask_user` tool. See [User Input Requests](#user-input-requests) section. | ||
@@ -133,3 +133,3 @@ - `onElicitationRequest?: ElicitationHandler` - Handler for elicitation requests dispatched by the server. Enables this client to present form-based UI dialogs on behalf of the agent or other session participants. See [Elicitation Requests](#elicitation-requests) section. | ||
| ##### `ping(message?: string): Promise<{ message: string; timestamp: number }>` | ||
| ##### `ping(message?: string): Promise<{ message: string; timestamp: string }>` | ||
@@ -808,3 +808,3 @@ Ping the server to check connectivity. | ||
| An `onPermissionRequest` handler is **required** whenever you create or resume a session. The handler is called before the agent executes each tool (file writes, shell commands, custom tools, etc.) and must return a decision. | ||
| An `onPermissionRequest` handler is optional when you create or resume a session. When provided, it is called before the agent executes each tool (file writes, shell commands, custom tools, etc.) and returns a decision. When omitted, permission requests are emitted as events and left pending for the consumer to resolve with the pending permission RPC. | ||
@@ -850,7 +850,7 @@ ### Approve All (simplest) | ||
| if (request.kind === "shell") { | ||
| // Deny shell commands | ||
| return { kind: "denied-interactively-by-user" }; | ||
| // Deny shell commands, optionally telling the model why | ||
| return { kind: "reject", feedback: "Shell commands are not allowed." }; | ||
| } | ||
| return { kind: "approved" }; | ||
| return { kind: "approve-once" }; | ||
| }, | ||
@@ -862,14 +862,17 @@ }); | ||
| | Kind | Meaning | | ||
| | ----------------------------------------------------------- | ------------------------------------------------------------------------------------------- | | ||
| | `"approved"` | Allow the tool to run | | ||
| | `"denied-interactively-by-user"` | User explicitly denied the request | | ||
| | `"denied-no-approval-rule-and-could-not-request-from-user"` | No approval rule matched and user could not be asked | | ||
| | `"denied-by-rules"` | Denied by a policy rule | | ||
| | `"denied-by-content-exclusion-policy"` | Denied due to a content exclusion policy | | ||
| | `"no-result"` | Leave the request unanswered (only valid with protocol v1; rejected by protocol v2 servers) | | ||
| The handler must return one of the `PermissionDecision` shapes (or `{ kind: "no-result" }`). Approval scopes are present-tense — they describe the decision to apply, not the outcome reported back on session events: | ||
| | Kind | Meaning | Extra fields | | ||
| | ------------------------ | --------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------- | | ||
| | `"approve-once"` | Allow this single request | — | | ||
| | `"approve-for-session"` | Allow this request and remember the approval for the rest of the session | `approval?` (rule to remember), `domain?` (for URL approvals) | | ||
| | `"approve-for-location"` | Allow this request and persist the approval for this project location (git root or cwd) | `approval` (rule to persist), `locationKey` (location to persist under) | | ||
| | `"approve-permanently"` | Allow this request and persist the approval across sessions (currently used for URL domains) | `domain` (URL domain to approve) | | ||
| | `"reject"` | Deny the request | `feedback?` (optional string surfaced to the agent) | | ||
| | `"user-not-available"` | Deny the request because no user is available to confirm it | — | | ||
| | `"no-result"` | Leave the request unanswered (only valid with protocol v1; rejected by protocol v2 servers) | — | | ||
| ### Resuming Sessions | ||
| Pass `onPermissionRequest` when resuming a session too — it is required: | ||
| You may pass `onPermissionRequest` when resuming a session too: | ||
@@ -876,0 +879,0 @@ ```typescript |
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
Network access
Supply chain riskThis module accesses the network.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 2 instances in 1 package
AI-detected potential code anomaly
Supply chain riskAI has identified unusual behaviors that may pose a security risk.
Found 1 instance in 1 package
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
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
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 2 instances in 1 package
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
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
1004148
67.1%27203
66.29%1034
0.29%56
80.65%6
Infinity%Updated