@github/copilot-sdk 0.1.33-unstable.1 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -5,5 +5,5 @@
5
5
  */
6
6
  export { CopilotClient } from "./client.js";
7
7
  export { CopilotSession, type AssistantMessageEvent } from "./session.js";
8
- export { defineTool, approveAll } from "./types.js";
9
- export type { ConnectionState, CopilotClientOptions, CustomAgentConfig, ForegroundSessionInfo, GetAuthStatusResponse, GetStatusResponse, InfiniteSessionConfig, MCPLocalServerConfig, MCPRemoteServerConfig, MCPServerConfig, MessageOptions, ModelBilling, ModelCapabilities, ModelInfo, ModelPolicy, PermissionHandler, PermissionRequest, PermissionRequestResult, ResumeSessionConfig, SessionConfig, SessionEvent, SessionEventHandler, SessionEventPayload, SessionEventType, SessionLifecycleEvent, SessionLifecycleEventType, SessionLifecycleHandler, SessionContext, SessionListFilter, SessionMetadata, SystemMessageAppendConfig, SystemMessageConfig, SystemMessageReplaceConfig, Tool, ToolHandler, ToolInvocation, ToolResultObject, TypedSessionEventHandler, TypedSessionLifecycleHandler, ZodSchema, } from "./types.js";
8
+ export { defineTool, approveAll, SYSTEM_PROMPT_SECTIONS } from "./types.js";
9
+ export type { ConnectionState, CopilotClientOptions, CustomAgentConfig, ForegroundSessionInfo, GetAuthStatusResponse, GetStatusResponse, InfiniteSessionConfig, MCPLocalServerConfig, MCPRemoteServerConfig, MCPServerConfig, MessageOptions, ModelBilling, ModelCapabilities, ModelInfo, ModelPolicy, PermissionHandler, PermissionRequest, PermissionRequestResult, ResumeSessionConfig, SectionOverride, SectionOverrideAction, SectionTransformFn, SessionConfig, SessionEvent, SessionEventHandler, SessionEventPayload, SessionEventType, SessionLifecycleEvent, SessionLifecycleEventType, SessionLifecycleHandler, SessionContext, SessionListFilter, SessionMetadata, SystemMessageAppendConfig, SystemMessageConfig, SystemMessageCustomizeConfig, SystemMessageReplaceConfig, SystemPromptSection, TelemetryConfig, TraceContext, TraceContextProvider, Tool, ToolHandler, ToolInvocation, ToolResultObject, TypedSessionEventHandler, TypedSessionLifecycleHandler, ZodSchema, } from "./types.js";
package/dist/index.js CHANGED
@@ -1,9 +1,10 @@
1
1
  import { CopilotClient } from "./client.js";
2
2
  import { CopilotSession } from "./session.js";
3
- import { defineTool, approveAll } from "./types.js";
3
+ import { defineTool, approveAll, SYSTEM_PROMPT_SECTIONS } from "./types.js";
4
4
  export {
5
5
  CopilotClient,
6
6
  CopilotSession,
7
+ SYSTEM_PROMPT_SECTIONS,
7
8
  approveAll,
8
9
  defineTool
9
10
  };
package/dist/session.d.ts CHANGED
@@ -4,7 +4,8 @@
4
4
  */
5
5
  import type { MessageConnection } from "vscode-jsonrpc/node.js";
6
6
  import { createSessionRpc } from "./generated/rpc.js";
7
- import type { MessageOptions, PermissionHandler, PermissionRequestResult, SessionEvent, SessionEventHandler, SessionEventType, SessionHooks, Tool, ToolHandler, TypedSessionEventHandler, UserInputHandler, UserInputResponse } from "./types.js";
7
+ import type { MessageOptions, PermissionHandler, PermissionRequestResult, ReasoningEffort, SectionTransformFn, SessionEvent, SessionEventHandler, SessionEventType, SessionHooks, Tool, ToolHandler, TraceContextProvider, TypedSessionEventHandler, UserInputHandler, UserInputResponse } from "./types.js";
8
+ export declare const NO_RESULT_PERMISSION_V2_ERROR = "Permission handlers cannot return 'no-result' when connected to a protocol v2 server.";
8
9
  /** Assistant message event - the final response from the assistant. */
9
10
  export type AssistantMessageEvent = Extract<SessionEvent, {
10
11
  type: "assistant.message";
@@ -37,23 +38,26 @@ export type AssistantMessageEvent = Extract<SessionEvent, {
37
38
  export declare class CopilotSession {
38
39
  readonly sessionId: string;
39
40
  private connection;
40
- private readonly _workspacePath?;
41
+ private _workspacePath?;
41
42
  private eventHandlers;
42
43
  private typedEventHandlers;
43
44
  private toolHandlers;
44
45
  private permissionHandler?;
45
46
  private userInputHandler?;
46
47
  private hooks?;
48
+ private transformCallbacks?;
47
49
  private _rpc;
50
+ private traceContextProvider?;
48
51
  /**
49
52
  * Creates a new CopilotSession instance.
50
53
  *
51
54
  * @param sessionId - The unique identifier for this session
52
55
  * @param connection - The JSON-RPC message connection to the Copilot CLI
53
56
  * @param workspacePath - Path to the session workspace directory (when infinite sessions enabled)
57
+ * @param traceContextProvider - Optional callback to get W3C Trace Context for outbound RPCs
54
58
  * @internal This constructor is internal. Use {@link CopilotClient.createSession} to create sessions.
55
59
  */
56
- constructor(sessionId: string, connection: MessageConnection, _workspacePath?: string | undefined);
60
+ constructor(sessionId: string, connection: MessageConnection, _workspacePath?: string | undefined, traceContextProvider?: TraceContextProvider);
57
61
  /**
58
62
  * Typed session-scoped RPC methods.
59
63
  */
@@ -226,6 +230,28 @@ export declare class CopilotSession {
226
230
  * @internal This method is typically called internally when creating a session.
227
231
  */
228
232
  registerHooks(hooks?: SessionHooks): void;
233
+ /**
234
+ * Registers transform callbacks for system message sections.
235
+ *
236
+ * @param callbacks - Map of section ID to transform callback, or undefined to clear
237
+ * @internal This method is typically called internally when creating a session.
238
+ */
239
+ registerTransformCallbacks(callbacks?: Map<string, SectionTransformFn>): void;
240
+ /**
241
+ * Handles a systemMessage.transform request from the runtime.
242
+ * Dispatches each section to its registered transform callback.
243
+ *
244
+ * @param sections - Map of section IDs to their current rendered content
245
+ * @returns A promise that resolves with the transformed sections
246
+ * @internal This method is for internal use by the SDK.
247
+ */
248
+ _handleSystemMessageTransform(sections: Record<string, {
249
+ content: string;
250
+ }>): Promise<{
251
+ sections: Record<string, {
252
+ content: string;
253
+ }>;
254
+ }>;
229
255
  /**
230
256
  * Handles a permission request in the v2 protocol format (synchronous RPC).
231
257
  * Used as a back-compat adapter when connected to a v2 server.
@@ -332,13 +358,17 @@ export declare class CopilotSession {
332
358
  * The new model takes effect for the next message. Conversation history is preserved.
333
359
  *
334
360
  * @param model - Model ID to switch to
361
+ * @param options - Optional settings for the new model
335
362
  *
336
363
  * @example
337
364
  * ```typescript
338
365
  * await session.setModel("gpt-4.1");
366
+ * await session.setModel("claude-sonnet-4.6", { reasoningEffort: "high" });
339
367
  * ```
340
368
  */
341
- setModel(model: string): Promise<void>;
369
+ setModel(model: string, options?: {
370
+ reasoningEffort?: ReasoningEffort;
371
+ }): Promise<void>;
342
372
  /**
343
373
  * Log a message to the session timeline.
344
374
  * The message appears in the session event stream and is visible to SDK consumers
package/dist/session.js CHANGED
@@ -1,5 +1,7 @@
1
1
  import { ConnectionError, ResponseError } from "vscode-jsonrpc/node.js";
2
2
  import { createSessionRpc } from "./generated/rpc.js";
3
+ import { getTraceContext } from "./telemetry.js";
4
+ const NO_RESULT_PERMISSION_V2_ERROR = "Permission handlers cannot return 'no-result' when connected to a protocol v2 server.";
3
5
  class CopilotSession {
4
6
  /**
5
7
  * Creates a new CopilotSession instance.
@@ -7,12 +9,14 @@ class CopilotSession {
7
9
  * @param sessionId - The unique identifier for this session
8
10
  * @param connection - The JSON-RPC message connection to the Copilot CLI
9
11
  * @param workspacePath - Path to the session workspace directory (when infinite sessions enabled)
12
+ * @param traceContextProvider - Optional callback to get W3C Trace Context for outbound RPCs
10
13
  * @internal This constructor is internal. Use {@link CopilotClient.createSession} to create sessions.
11
14
  */
12
- constructor(sessionId, connection, _workspacePath) {
15
+ constructor(sessionId, connection, _workspacePath, traceContextProvider) {
13
16
  this.sessionId = sessionId;
14
17
  this.connection = connection;
15
18
  this._workspacePath = _workspacePath;
19
+ this.traceContextProvider = traceContextProvider;
16
20
  }
17
21
  eventHandlers = /* @__PURE__ */ new Set();
18
22
  typedEventHandlers = /* @__PURE__ */ new Map();
@@ -20,7 +24,9 @@ class CopilotSession {
20
24
  permissionHandler;
21
25
  userInputHandler;
22
26
  hooks;
27
+ transformCallbacks;
23
28
  _rpc = null;
29
+ traceContextProvider;
24
30
  /**
25
31
  * Typed session-scoped RPC methods.
26
32
  */
@@ -58,6 +64,7 @@ class CopilotSession {
58
64
  */
59
65
  async send(options) {
60
66
  const response = await this.connection.sendRequest("session.send", {
67
+ ...await getTraceContext(this.traceContextProvider),
61
68
  sessionId: this.sessionId,
62
69
  prompt: options.prompt,
63
70
  attachments: options.attachments,
@@ -187,9 +194,19 @@ class CopilotSession {
187
194
  const { requestId, toolName } = event.data;
188
195
  const args = event.data.arguments;
189
196
  const toolCallId = event.data.toolCallId;
197
+ const traceparent = event.data.traceparent;
198
+ const tracestate = event.data.tracestate;
190
199
  const handler = this.toolHandlers.get(toolName);
191
200
  if (handler) {
192
- void this._executeToolAndRespond(requestId, toolName, toolCallId, args, handler);
201
+ void this._executeToolAndRespond(
202
+ requestId,
203
+ toolName,
204
+ toolCallId,
205
+ args,
206
+ handler,
207
+ traceparent,
208
+ tracestate
209
+ );
193
210
  }
194
211
  } else if (event.type === "permission.requested") {
195
212
  const { requestId, permissionRequest } = event.data;
@@ -202,13 +219,15 @@ class CopilotSession {
202
219
  * Executes a tool handler and sends the result back via RPC.
203
220
  * @internal
204
221
  */
205
- async _executeToolAndRespond(requestId, toolName, toolCallId, args, handler) {
222
+ async _executeToolAndRespond(requestId, toolName, toolCallId, args, handler, traceparent, tracestate) {
206
223
  try {
207
224
  const rawResult = await handler(args, {
208
225
  sessionId: this.sessionId,
209
226
  toolCallId,
210
227
  toolName,
211
- arguments: args
228
+ arguments: args,
229
+ traceparent,
230
+ tracestate
212
231
  });
213
232
  let result;
214
233
  if (rawResult == null) {
@@ -239,6 +258,9 @@ class CopilotSession {
239
258
  const result = await this.permissionHandler(permissionRequest, {
240
259
  sessionId: this.sessionId
241
260
  });
261
+ if (result.kind === "no-result") {
262
+ return;
263
+ }
242
264
  await this.rpc.permissions.handlePendingPermissionRequest({ requestId, result });
243
265
  } catch (_error) {
244
266
  try {
@@ -319,6 +341,40 @@ class CopilotSession {
319
341
  registerHooks(hooks) {
320
342
  this.hooks = hooks;
321
343
  }
344
+ /**
345
+ * Registers transform callbacks for system message sections.
346
+ *
347
+ * @param callbacks - Map of section ID to transform callback, or undefined to clear
348
+ * @internal This method is typically called internally when creating a session.
349
+ */
350
+ registerTransformCallbacks(callbacks) {
351
+ this.transformCallbacks = callbacks;
352
+ }
353
+ /**
354
+ * Handles a systemMessage.transform request from the runtime.
355
+ * Dispatches each section to its registered transform callback.
356
+ *
357
+ * @param sections - Map of section IDs to their current rendered content
358
+ * @returns A promise that resolves with the transformed sections
359
+ * @internal This method is for internal use by the SDK.
360
+ */
361
+ async _handleSystemMessageTransform(sections) {
362
+ const result = {};
363
+ for (const [sectionId, { content }] of Object.entries(sections)) {
364
+ const callback = this.transformCallbacks?.get(sectionId);
365
+ if (callback) {
366
+ try {
367
+ const transformed = await callback(content);
368
+ result[sectionId] = { content: transformed };
369
+ } catch (_error) {
370
+ result[sectionId] = { content };
371
+ }
372
+ } else {
373
+ result[sectionId] = { content };
374
+ }
375
+ }
376
+ return { sections: result };
377
+ }
322
378
  /**
323
379
  * Handles a permission request in the v2 protocol format (synchronous RPC).
324
380
  * Used as a back-compat adapter when connected to a v2 server.
@@ -335,8 +391,14 @@ class CopilotSession {
335
391
  const result = await this.permissionHandler(request, {
336
392
  sessionId: this.sessionId
337
393
  });
394
+ if (result.kind === "no-result") {
395
+ throw new Error(NO_RESULT_PERMISSION_V2_ERROR);
396
+ }
338
397
  return result;
339
- } catch (_error) {
398
+ } catch (error) {
399
+ if (error instanceof Error && error.message === NO_RESULT_PERMISSION_V2_ERROR) {
400
+ throw error;
401
+ }
340
402
  return { kind: "denied-no-approval-rule-and-could-not-request-from-user" };
341
403
  }
342
404
  }
@@ -492,14 +554,16 @@ class CopilotSession {
492
554
  * The new model takes effect for the next message. Conversation history is preserved.
493
555
  *
494
556
  * @param model - Model ID to switch to
557
+ * @param options - Optional settings for the new model
495
558
  *
496
559
  * @example
497
560
  * ```typescript
498
561
  * await session.setModel("gpt-4.1");
562
+ * await session.setModel("claude-sonnet-4.6", { reasoningEffort: "high" });
499
563
  * ```
500
564
  */
501
- async setModel(model) {
502
- await this.rpc.model.switchTo({ modelId: model });
565
+ async setModel(model, options) {
566
+ await this.rpc.model.switchTo({ modelId: model, ...options });
503
567
  }
504
568
  /**
505
569
  * Log a message to the session timeline.
@@ -522,5 +586,6 @@ class CopilotSession {
522
586
  }
523
587
  }
524
588
  export {
525
- CopilotSession
589
+ CopilotSession,
590
+ NO_RESULT_PERMISSION_V2_ERROR
526
591
  };
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Trace-context helpers.
3
+ *
4
+ * The SDK does not depend on any OpenTelemetry packages. Instead, users
5
+ * provide an {@link TraceContextProvider} callback via client options.
6
+ *
7
+ * @module telemetry
8
+ */
9
+ import type { TraceContext, TraceContextProvider } from "./types.js";
10
+ /**
11
+ * Calls the user-provided {@link TraceContextProvider} to obtain the current
12
+ * W3C Trace Context. Returns `{}` when no provider is configured.
13
+ */
14
+ export declare function getTraceContext(provider?: TraceContextProvider): Promise<TraceContext>;
@@ -0,0 +1,11 @@
1
+ async function getTraceContext(provider) {
2
+ if (!provider) return {};
3
+ try {
4
+ return await provider() ?? {};
5
+ } catch {
6
+ return {};
7
+ }
8
+ }
9
+ export {
10
+ getTraceContext
11
+ };
package/dist/types.d.ts CHANGED
@@ -6,6 +6,38 @@ export type SessionEvent = GeneratedSessionEvent;
6
6
  /**
7
7
  * Options for creating a CopilotClient
8
8
  */
9
+ /**
10
+ * W3C Trace Context headers used for distributed trace propagation.
11
+ */
12
+ export interface TraceContext {
13
+ traceparent?: string;
14
+ tracestate?: string;
15
+ }
16
+ /**
17
+ * Callback that returns the current W3C Trace Context.
18
+ * Wire this up to your OpenTelemetry (or other tracing) SDK to enable
19
+ * distributed trace propagation between your app and the Copilot CLI.
20
+ */
21
+ export type TraceContextProvider = () => TraceContext | Promise<TraceContext>;
22
+ /**
23
+ * Configuration for OpenTelemetry instrumentation.
24
+ *
25
+ * When provided via {@link CopilotClientOptions.telemetry}, the SDK sets
26
+ * the corresponding environment variables on the spawned CLI process so
27
+ * that the CLI's built-in OTel exporter is configured automatically.
28
+ */
29
+ export interface TelemetryConfig {
30
+ /** OTLP HTTP endpoint URL for trace/metric export. Sets OTEL_EXPORTER_OTLP_ENDPOINT. */
31
+ otlpEndpoint?: string;
32
+ /** File path for JSON-lines trace output. Sets COPILOT_OTEL_FILE_EXPORTER_PATH. */
33
+ filePath?: string;
34
+ /** Exporter backend type: "otlp-http" or "file". Sets COPILOT_OTEL_EXPORTER_TYPE. */
35
+ exporterType?: string;
36
+ /** Instrumentation scope name. Sets COPILOT_OTEL_SOURCE_NAME. */
37
+ sourceName?: string;
38
+ /** Whether to capture message content (prompts, responses). Sets OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT. */
39
+ captureContent?: boolean;
40
+ }
9
41
  export interface CopilotClientOptions {
10
42
  /**
11
43
  * Path to the CLI executable or JavaScript entry point.
@@ -56,8 +88,7 @@ export interface CopilotClientOptions {
56
88
  */
57
89
  autoStart?: boolean;
58
90
  /**
59
- * Auto-restart the CLI server if it crashes
60
- * @default true
91
+ * @deprecated This option has no effect and will be removed in a future release.
61
92
  */
62
93
  autoRestart?: boolean;
63
94
  /**
@@ -84,6 +115,37 @@ export interface CopilotClientOptions {
84
115
  * available from your custom provider.
85
116
  */
86
117
  onListModels?: () => Promise<ModelInfo[]> | ModelInfo[];
118
+ /**
119
+ * OpenTelemetry configuration for the CLI process.
120
+ * When provided, the corresponding OTel environment variables are set
121
+ * on the spawned CLI server.
122
+ */
123
+ telemetry?: TelemetryConfig;
124
+ /**
125
+ * Advanced: callback that returns the current W3C Trace Context for distributed
126
+ * trace propagation. Most users do not need this — the {@link telemetry} config
127
+ * alone is sufficient to collect traces from the CLI.
128
+ *
129
+ * This callback is only useful when your application creates its own
130
+ * OpenTelemetry spans and you want them to appear in the **same** distributed
131
+ * trace as the CLI's spans. The SDK calls this before `session.create`,
132
+ * `session.resume`, and `session.send` RPCs to inject `traceparent`/`tracestate`
133
+ * into the request.
134
+ *
135
+ * @example
136
+ * ```typescript
137
+ * import { propagation, context } from "@opentelemetry/api";
138
+ *
139
+ * const client = new CopilotClient({
140
+ * onGetTraceContext: () => {
141
+ * const carrier: Record<string, string> = {};
142
+ * propagation.inject(context.active(), carrier);
143
+ * return carrier;
144
+ * },
145
+ * });
146
+ * ```
147
+ */
148
+ onGetTraceContext?: TraceContextProvider;
87
149
  }
88
150
  /**
89
151
  * Configuration for creating a session
@@ -109,6 +171,10 @@ export interface ToolInvocation {
109
171
  toolCallId: string;
110
172
  toolName: string;
111
173
  arguments: unknown;
174
+ /** W3C Trace Context traceparent from the CLI's execute_tool span. */
175
+ traceparent?: string;
176
+ /** W3C Trace Context tracestate from the CLI's execute_tool span. */
177
+ tracestate?: string;
112
178
  }
113
179
  export type ToolHandler<TArgs = unknown> = (args: TArgs, invocation: ToolInvocation) => Promise<unknown> | unknown;
114
180
  /**
@@ -136,6 +202,10 @@ export interface Tool<TArgs = unknown> {
136
202
  * will return an error.
137
203
  */
138
204
  overridesBuiltInTool?: boolean;
205
+ /**
206
+ * When true, the tool can execute without a permission prompt.
207
+ */
208
+ skipPermission?: boolean;
139
209
  }
140
210
  /**
141
211
  * Helper to define a tool with Zod schema and get type inference for the handler.
@@ -146,6 +216,7 @@ export declare function defineTool<T = unknown>(name: string, config: {
146
216
  parameters?: ZodSchema<T> | Record<string, unknown>;
147
217
  handler: ToolHandler<T>;
148
218
  overridesBuiltInTool?: boolean;
219
+ skipPermission?: boolean;
149
220
  }): Tool<T>;
150
221
  export interface ToolCallRequestPayload {
151
222
  sessionId: string;
@@ -156,6 +227,46 @@ export interface ToolCallRequestPayload {
156
227
  export interface ToolCallResponsePayload {
157
228
  result: ToolResult;
158
229
  }
230
+ /**
231
+ * Known system prompt section identifiers for the "customize" mode.
232
+ * Each section corresponds to a distinct part of the system prompt.
233
+ */
234
+ export type SystemPromptSection = "identity" | "tone" | "tool_efficiency" | "environment_context" | "code_change_rules" | "guidelines" | "safety" | "tool_instructions" | "custom_instructions" | "last_instructions";
235
+ /** Section metadata for documentation and tooling. */
236
+ export declare const SYSTEM_PROMPT_SECTIONS: Record<SystemPromptSection, {
237
+ description: string;
238
+ }>;
239
+ /**
240
+ * Transform callback for a single section: receives current content, returns new content.
241
+ */
242
+ export type SectionTransformFn = (currentContent: string) => string | Promise<string>;
243
+ /**
244
+ * Override action: a string literal for static overrides, or a callback for transforms.
245
+ *
246
+ * - `"replace"`: Replace section content entirely
247
+ * - `"remove"`: Remove the section
248
+ * - `"append"`: Append to existing section content
249
+ * - `"prepend"`: Prepend to existing section content
250
+ * - `function`: Transform callback — receives current section content, returns new content
251
+ */
252
+ export type SectionOverrideAction = "replace" | "remove" | "append" | "prepend" | SectionTransformFn;
253
+ /**
254
+ * Override operation for a single system prompt section.
255
+ */
256
+ export interface SectionOverride {
257
+ /**
258
+ * The operation to perform on this section.
259
+ * Can be a string action or a transform callback function.
260
+ */
261
+ action: SectionOverrideAction;
262
+ /**
263
+ * Content for the override. Optional for all actions.
264
+ * - For replace, omitting content replaces with an empty string.
265
+ * - For append/prepend, content is added before/after the existing section.
266
+ * - Ignored for the remove action.
267
+ */
268
+ content?: string;
269
+ }
159
270
  /**
160
271
  * Append mode: Use CLI foundation with optional appended content (default).
161
272
  */
@@ -178,12 +289,31 @@ export interface SystemMessageReplaceConfig {
178
289
  */
179
290
  content: string;
180
291
  }
292
+ /**
293
+ * Customize mode: Override individual sections of the system prompt.
294
+ * Keeps the SDK-managed prompt structure while allowing targeted modifications.
295
+ */
296
+ export interface SystemMessageCustomizeConfig {
297
+ mode: "customize";
298
+ /**
299
+ * Override specific sections of the system prompt by section ID.
300
+ * Unknown section IDs gracefully fall back: content-bearing overrides are appended
301
+ * to additional instructions, and "remove" on unknown sections is a silent no-op.
302
+ */
303
+ sections?: Partial<Record<SystemPromptSection, SectionOverride>>;
304
+ /**
305
+ * Additional content appended after all sections.
306
+ * Equivalent to append mode's content field — provided for convenience.
307
+ */
308
+ content?: string;
309
+ }
181
310
  /**
182
311
  * System message configuration for session creation.
183
312
  * - Append mode (default): SDK foundation + optional custom content
184
313
  * - Replace mode: Full control, caller provides entire system message
314
+ * - Customize mode: Section-level overrides with graceful fallback
185
315
  */
186
- export type SystemMessageConfig = SystemMessageAppendConfig | SystemMessageReplaceConfig;
316
+ export type SystemMessageConfig = SystemMessageAppendConfig | SystemMessageReplaceConfig | SystemMessageCustomizeConfig;
187
317
  /**
188
318
  * Permission request types from the server
189
319
  */
@@ -193,7 +323,9 @@ export interface PermissionRequest {
193
323
  [key: string]: unknown;
194
324
  }
195
325
  import type { SessionPermissionsHandlePendingPermissionRequestParams } from "./generated/rpc.js";
196
- export type PermissionRequestResult = SessionPermissionsHandlePendingPermissionRequestParams["result"];
326
+ export type PermissionRequestResult = SessionPermissionsHandlePendingPermissionRequestParams["result"] | {
327
+ kind: "no-result";
328
+ };
197
329
  export type PermissionHandler = (request: PermissionRequest, invocation: {
198
330
  sessionId: string;
199
331
  }) => Promise<PermissionRequestResult> | PermissionRequestResult;
@@ -613,11 +745,21 @@ export interface SessionConfig {
613
745
  * Set to `{ enabled: false }` to disable.
614
746
  */
615
747
  infiniteSessions?: InfiniteSessionConfig;
748
+ /**
749
+ * Optional event handler that is registered on the session before the
750
+ * session.create RPC is issued. This guarantees that early events emitted
751
+ * by the CLI during session creation (e.g. session.start) are delivered to
752
+ * the handler.
753
+ *
754
+ * Equivalent to calling `session.on(handler)` immediately after creation,
755
+ * but executes earlier in the lifecycle so no events are missed.
756
+ */
757
+ onEvent?: SessionEventHandler;
616
758
  }
617
759
  /**
618
760
  * Configuration for resuming a session
619
761
  */
620
- export type ResumeSessionConfig = Pick<SessionConfig, "clientName" | "model" | "tools" | "systemMessage" | "availableTools" | "excludedTools" | "provider" | "streaming" | "reasoningEffort" | "onPermissionRequest" | "onUserInputRequest" | "hooks" | "workingDirectory" | "configDir" | "mcpServers" | "customAgents" | "agent" | "skillDirectories" | "disabledSkills" | "infiniteSessions"> & {
762
+ export type ResumeSessionConfig = Pick<SessionConfig, "clientName" | "model" | "tools" | "systemMessage" | "availableTools" | "excludedTools" | "provider" | "streaming" | "reasoningEffort" | "onPermissionRequest" | "onUserInputRequest" | "hooks" | "workingDirectory" | "configDir" | "mcpServers" | "customAgents" | "agent" | "skillDirectories" | "disabledSkills" | "infiniteSessions" | "onEvent"> & {
621
763
  /**
622
764
  * When true, skips emitting the session.resume event.
623
765
  * Useful for reconnecting to a session without triggering resume-related side effects.
@@ -670,7 +812,7 @@ export interface MessageOptions {
670
812
  */
671
813
  prompt: string;
672
814
  /**
673
- * File, directory, or selection attachments
815
+ * File, directory, selection, or blob attachments
674
816
  */
675
817
  attachments?: Array<{
676
818
  type: "file";
@@ -695,6 +837,11 @@ export interface MessageOptions {
695
837
  };
696
838
  };
697
839
  text?: string;
840
+ } | {
841
+ type: "blob";
842
+ data: string;
843
+ mimeType: string;
844
+ displayName?: string;
698
845
  }>;
699
846
  /**
700
847
  * Message delivery mode
package/dist/types.js CHANGED
@@ -1,8 +1,23 @@
1
1
  function defineTool(name, config) {
2
2
  return { name, ...config };
3
3
  }
4
+ const SYSTEM_PROMPT_SECTIONS = {
5
+ identity: { description: "Agent identity preamble and mode statement" },
6
+ tone: { description: "Response style, conciseness rules, output formatting preferences" },
7
+ tool_efficiency: { description: "Tool usage patterns, parallel calling, batching guidelines" },
8
+ environment_context: { description: "CWD, OS, git root, directory listing, available tools" },
9
+ code_change_rules: { description: "Coding rules, linting/testing, ecosystem tools, style" },
10
+ guidelines: { description: "Tips, behavioral best practices, behavioral guidelines" },
11
+ safety: { description: "Environment limitations, prohibited actions, security policies" },
12
+ tool_instructions: { description: "Per-tool usage instructions" },
13
+ custom_instructions: { description: "Repository and organization custom instructions" },
14
+ last_instructions: {
15
+ description: "End-of-prompt instructions: parallel tool calling, persistence, task completion"
16
+ }
17
+ };
4
18
  const approveAll = () => ({ kind: "approved" });
5
19
  export {
20
+ SYSTEM_PROMPT_SECTIONS,
6
21
  approveAll,
7
22
  defineTool
8
23
  };
@@ -59,11 +59,9 @@ Discovery rules:
59
59
  ## Minimal Skeleton
60
60
 
61
61
  ```js
62
- import { approveAll } from "@github/copilot-sdk";
63
62
  import { joinSession } from "@github/copilot-sdk/extension";
64
63
 
65
64
  await joinSession({
66
- onPermissionRequest: approveAll, // Required — handle permission requests
67
65
  tools: [], // Optional — custom tools
68
66
  hooks: {}, // Optional — lifecycle hooks
69
67
  });
package/docs/examples.md CHANGED
@@ -7,11 +7,9 @@ A practical guide to writing extensions using the `@github/copilot-sdk` extensio
7
7
  Every extension starts with the same boilerplate:
8
8
 
9
9
  ```js
10
- import { approveAll } from "@github/copilot-sdk";
11
10
  import { joinSession } from "@github/copilot-sdk/extension";
12
11
 
13
12
  const session = await joinSession({
14
- onPermissionRequest: approveAll,
15
13
  hooks: { /* ... */ },
16
14
  tools: [ /* ... */ ],
17
15
  });
@@ -33,7 +31,6 @@ Use `session.log()` to surface messages to the user in the CLI timeline:
33
31
 
34
32
  ```js
35
33
  const session = await joinSession({
36
- onPermissionRequest: approveAll,
37
34
  hooks: {
38
35
  onSessionStart: async () => {
39
36
  await session.log("My extension loaded");
@@ -383,7 +380,6 @@ function copyToClipboard(text) {
383
380
  }
384
381
 
385
382
  const session = await joinSession({
386
- onPermissionRequest: approveAll,
387
383
  hooks: {
388
384
  onUserPromptSubmitted: async (input) => {
389
385
  if (/\\bcopy\\b/i.test(input.prompt)) {
@@ -425,15 +421,12 @@ Correlate `tool.execution_start` / `tool.execution_complete` events by `toolCall
425
421
  ```js
426
422
  import { existsSync, watchFile, readFileSync } from "node:fs";
427
423
  import { join } from "node:path";
428
- import { approveAll } from "@github/copilot-sdk";
429
424
  import { joinSession } from "@github/copilot-sdk/extension";
430
425
 
431
426
  const agentEdits = new Set(); // toolCallIds for in-flight agent edits
432
427
  const recentAgentPaths = new Set(); // paths recently written by the agent
433
428
 
434
- const session = await joinSession({
435
- onPermissionRequest: approveAll,
436
- });
429
+ const session = await joinSession();
437
430
 
438
431
  const workspace = session.workspacePath; // e.g. ~/.copilot/session-state/<id>
439
432
  if (workspace) {
@@ -480,14 +473,11 @@ Filter out agent edits by tracking `tool.execution_start` / `tool.execution_comp
480
473
  ```js
481
474
  import { watch, readFileSync, statSync } from "node:fs";
482
475
  import { join, relative, resolve } from "node:path";
483
- import { approveAll } from "@github/copilot-sdk";
484
476
  import { joinSession } from "@github/copilot-sdk/extension";
485
477
 
486
478
  const agentEditPaths = new Set();
487
479
 
488
- const session = await joinSession({
489
- onPermissionRequest: approveAll,
490
- });
480
+ const session = await joinSession();
491
481
 
492
482
  const cwd = process.cwd();
493
483
  const IGNORE = new Set(["node_modules", ".git", "dist"]);
@@ -582,7 +572,6 @@ Register `onUserInputRequest` to enable the agent's `ask_user` tool:
582
572
 
583
573
  ```js
584
574
  const session = await joinSession({
585
- onPermissionRequest: approveAll,
586
575
  onUserInputRequest: async (request) => {
587
576
  // request.question has the agent's question
588
577
  // request.choices has the options (if multiple choice)
@@ -599,7 +588,6 @@ An extension that combines tools, hooks, and events.
599
588
 
600
589
  ```js
601
590
  import { execFile, exec } from "node:child_process";
602
- import { approveAll } from "@github/copilot-sdk";
603
591
  import { joinSession } from "@github/copilot-sdk/extension";
604
592
 
605
593
  const isWindows = process.platform === "win32";
@@ -617,7 +605,6 @@ function openInEditor(filePath) {
617
605
  }
618
606
 
619
607
  const session = await joinSession({
620
- onPermissionRequest: approveAll,
621
608
  hooks: {
622
609
  onUserPromptSubmitted: async (input) => {
623
610
  if (/\\bcopy this\\b/i.test(input.prompt)) {