@github/copilot-sdk 1.0.17-preview.2 → 1.0.17-preview.4

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/session.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import { createSessionRpc } from "./generated/rpc.js";
2
2
  import type { ModelSwitchAutoTierResult } from "./generated/rpc.js";
3
3
  import type { OpenCanvasInstance } from "./generated/rpc.js";
4
- import type { MessageOptions, ResponseSchema, ContextTier, ReasoningEffort, ReasoningSummary, AutoTier, ModelCapabilitiesOverride, SessionCapabilities, SessionEvent, SessionEventHandler, SessionEventType, SessionUiApi, TranscriptRecovery, TypedSessionEventHandler } from "./types.js";
4
+ import type { MessageOptions, ResponseSchema, ContextTier, ReasoningEffort, ReasoningSummary, AutoTier, ModelCapabilitiesOverride, SessionCapabilities, SessionEvent, SessionEventHandler, SessionEventType, SessionUiApi, Tool, TranscriptRecovery, TypedSessionEventHandler } from "./types.js";
5
5
  import { type SessionWorkflowApi } from "./workflow.js";
6
6
  /** Assistant message event - the final response from the assistant. */
7
7
  export type AssistantMessageEvent = Extract<SessionEvent, {
@@ -45,6 +45,8 @@ export declare class CopilotSession {
45
45
  private eventHandlers;
46
46
  private typedEventHandlers;
47
47
  private toolHandlers;
48
+ /** Settles once every earlier `setTools` call has finished. */
49
+ private setToolsQueue;
48
50
  private pendingExternalTools;
49
51
  private canvases;
50
52
  private bearerTokenProviders;
@@ -364,6 +366,48 @@ export declare class CopilotSession {
364
366
  * ```
365
367
  */
366
368
  setAutoTier(autoTier: AutoTier | null): Promise<ModelSwitchAutoTierResult>;
369
+ /**
370
+ * Replace the tools this client supplies to the session.
371
+ *
372
+ * `tools` becomes the complete set of tools this client implements,
373
+ * replacing the ones it supplied when the session was created or resumed,
374
+ * or in an earlier call. Built-in, MCP, and plugin tools, and tools other
375
+ * connected clients supply, are unaffected. Pass an empty array to remove
376
+ * all of this client's tools.
377
+ *
378
+ * Tools are defined the same way as for `createSession`: calls to tools
379
+ * with a `handler` are dispatched to it, and tools without one are
380
+ * declaration-only. Once the runtime accepts the replacement, every tool
381
+ * call this session dispatches uses the new handlers; calls already
382
+ * running finish on their original handlers. If the runtime rejects the
383
+ * replacement, this rejects and the previous tools and handlers stay in
384
+ * place. Concurrent calls on the same session are applied one at a time,
385
+ * in the order they are made.
386
+ *
387
+ * The agent sees the new tools from its next model request, which can fall
388
+ * within a turn in progress. A model request already in flight was made
389
+ * with the previous tools, so the agent can still call a tool you removed.
390
+ * This session doesn't answer that call, and it can stay pending until the
391
+ * turn is aborted. If a running turn might still call a tool you remove,
392
+ * replace tools while the session is idle.
393
+ *
394
+ * @param tools - The complete set of tools this client supplies
395
+ *
396
+ * @experimental Wraps the experimental `session.tools.set` RPC and may change
397
+ * or be removed in a future release.
398
+ *
399
+ * @example
400
+ * ```typescript
401
+ * await session.setTools([
402
+ * defineTool("search_issues", {
403
+ * description: "Search the issues shown on the current page",
404
+ * parameters: z.object({ query: z.string() }),
405
+ * handler: async ({ query }) => searchIssues(query),
406
+ * }),
407
+ * ]);
408
+ * ```
409
+ */
410
+ setTools(tools: Tool[]): Promise<void>;
367
411
  /**
368
412
  * Log a message to the session timeline.
369
413
  * The message appears in the session event stream and is visible to SDK consumers
package/dist/session.js CHANGED
@@ -20,6 +20,18 @@ function copyDefinedWorkflowAgentOption(source, target, key) {
20
20
  target[key] = value;
21
21
  }
22
22
  }
23
+ function toToolDefinition(tool) {
24
+ return {
25
+ name: tool.name,
26
+ description: tool.description ?? "",
27
+ parameters: toJsonSchema(tool.parameters),
28
+ overridesBuiltInTool: tool.overridesBuiltInTool,
29
+ skipPermission: tool.skipPermission,
30
+ defer: tool.defer,
31
+ metadata: tool.metadata,
32
+ isTerminal: tool.isTerminal
33
+ };
34
+ }
23
35
  const workflowExecutionStore = new AsyncLocalStorage();
24
36
  function throwIfWorkflowExecutionIsActive() {
25
37
  if (workflowExecutionStore.getStore()?.active) {
@@ -240,6 +252,8 @@ class CopilotSession {
240
252
  eventHandlers = /* @__PURE__ */ new Set();
241
253
  typedEventHandlers = /* @__PURE__ */ new Map();
242
254
  toolHandlers = /* @__PURE__ */ new Map();
255
+ /** Settles once every earlier `setTools` call has finished. */
256
+ setToolsQueue = Promise.resolve();
243
257
  pendingExternalTools = /* @__PURE__ */ new Map();
244
258
  canvases = /* @__PURE__ */ new Map();
245
259
  bearerTokenProviders = /* @__PURE__ */ new Map();
@@ -1051,7 +1065,20 @@ class CopilotSession {
1051
1065
  }
1052
1066
  for (const tool of tools) {
1053
1067
  if (tool.handler) {
1054
- this.toolHandlers.set(tool.name, tool.handler);
1068
+ const handler = tool.handler;
1069
+ if (tool.name === "apply_patch" && tool.overridesBuiltInTool && toJsonSchema(tool.parameters)?.type === "string") {
1070
+ this.toolHandlers.set(tool.name, (args, invocation) => {
1071
+ if (typeof args === "string") {
1072
+ return handler(args, invocation);
1073
+ }
1074
+ if (typeof args === "object" && args !== null && "input" in args && typeof args.input === "string") {
1075
+ return handler(args.input, invocation);
1076
+ }
1077
+ throw new TypeError("apply_patch string override requires a string input");
1078
+ });
1079
+ } else {
1080
+ this.toolHandlers.set(tool.name, handler);
1081
+ }
1055
1082
  }
1056
1083
  }
1057
1084
  }
@@ -1646,7 +1673,9 @@ class CopilotSession {
1646
1673
  sessionStart: this.hooks.onSessionStart,
1647
1674
  sessionEnd: this.hooks.onSessionEnd,
1648
1675
  errorOccurred: this.hooks.onErrorOccurred,
1649
- agentStop: this.hooks.onAgentStop
1676
+ agentStop: this.hooks.onAgentStop,
1677
+ subagentStart: this.hooks.onSubagentStart,
1678
+ subagentStop: this.hooks.onSubagentStop
1650
1679
  };
1651
1680
  const handler = handlerMap[hookType];
1652
1681
  if (!handler) {
@@ -1810,6 +1839,59 @@ class CopilotSession {
1810
1839
  async setAutoTier(autoTier) {
1811
1840
  return await this.rpc.model.switchAutoTier({ autoTier });
1812
1841
  }
1842
+ /**
1843
+ * Replace the tools this client supplies to the session.
1844
+ *
1845
+ * `tools` becomes the complete set of tools this client implements,
1846
+ * replacing the ones it supplied when the session was created or resumed,
1847
+ * or in an earlier call. Built-in, MCP, and plugin tools, and tools other
1848
+ * connected clients supply, are unaffected. Pass an empty array to remove
1849
+ * all of this client's tools.
1850
+ *
1851
+ * Tools are defined the same way as for `createSession`: calls to tools
1852
+ * with a `handler` are dispatched to it, and tools without one are
1853
+ * declaration-only. Once the runtime accepts the replacement, every tool
1854
+ * call this session dispatches uses the new handlers; calls already
1855
+ * running finish on their original handlers. If the runtime rejects the
1856
+ * replacement, this rejects and the previous tools and handlers stay in
1857
+ * place. Concurrent calls on the same session are applied one at a time,
1858
+ * in the order they are made.
1859
+ *
1860
+ * The agent sees the new tools from its next model request, which can fall
1861
+ * within a turn in progress. A model request already in flight was made
1862
+ * with the previous tools, so the agent can still call a tool you removed.
1863
+ * This session doesn't answer that call, and it can stay pending until the
1864
+ * turn is aborted. If a running turn might still call a tool you remove,
1865
+ * replace tools while the session is idle.
1866
+ *
1867
+ * @param tools - The complete set of tools this client supplies
1868
+ *
1869
+ * @experimental Wraps the experimental `session.tools.set` RPC and may change
1870
+ * or be removed in a future release.
1871
+ *
1872
+ * @example
1873
+ * ```typescript
1874
+ * await session.setTools([
1875
+ * defineTool("search_issues", {
1876
+ * description: "Search the issues shown on the current page",
1877
+ * parameters: z.object({ query: z.string() }),
1878
+ * handler: async ({ query }) => searchIssues(query),
1879
+ * }),
1880
+ * ]);
1881
+ * ```
1882
+ */
1883
+ async setTools(tools) {
1884
+ const definitions = tools.map(toToolDefinition);
1885
+ const replacement = this.setToolsQueue.then(async () => {
1886
+ await this.rpc.tools.set({ tools: definitions });
1887
+ this.registerTools(tools);
1888
+ });
1889
+ this.setToolsQueue = replacement.then(
1890
+ () => void 0,
1891
+ () => void 0
1892
+ );
1893
+ await replacement;
1894
+ }
1813
1895
  /**
1814
1896
  * Log a message to the session timeline.
1815
1897
  * The message appears in the session event stream and is visible to SDK consumers
@@ -37,6 +37,10 @@ export declare class SessionFsSqliteTransactionFailure extends Error {
37
37
  readonly errorClass: SessionFsSqliteTransactionErrorClass;
38
38
  constructor(message: string, errorClass?: SessionFsSqliteTransactionErrorClass);
39
39
  }
40
+ /** Throw from `writeFile` only when the provider changed the target before failing. */
41
+ export declare class SessionFsWriteFailure extends Error {
42
+ readonly writeChanged = true;
43
+ }
40
44
  /**
41
45
  * SQLite operations for the per-session database.
42
46
  * Implementers provide query execution and existence checking.
@@ -78,7 +82,11 @@ export interface SessionFsSqliteProvider {
78
82
  export interface SessionFsProvider {
79
83
  /** Reads the full content of a file. Throw if the file does not exist. */
80
84
  readFile(path: string): Promise<string>;
81
- /** Writes content to a file, creating parent directories if needed. */
85
+ /** Read exact file bytes. Required when capabilities.binary is enabled. */
86
+ readFileBytes?(path: string): Promise<Uint8Array>;
87
+ /** Write exact file bytes. Required when capabilities.binary is enabled. */
88
+ writeFileBytes?(path: string, content: Uint8Array, mode?: number): Promise<void>;
89
+ /** Writes content to a file, creating parent directories if needed. Throw {@link SessionFsWriteFailure} if a failed write changed the target. */
82
90
  writeFile(path: string, content: string, mode?: number): Promise<void>;
83
91
  /** Appends content to a file, creating parent directories if needed. */
84
92
  appendFile(path: string, content: string, mode?: number): Promise<void>;
@@ -1,3 +1,5 @@
1
+ const MAX_BINARY_BYTES = (64 * 1024 * 1024 - 1024) / 4 * 3;
2
+ const MAX_BINARY_CONTENT_LENGTH = Math.ceil(MAX_BINARY_BYTES / 3) * 4;
1
3
  class SessionFsSqliteTransactionFailure extends Error {
2
4
  /** Failure classification reported to the runtime. */
3
5
  errorClass;
@@ -7,6 +9,9 @@ class SessionFsSqliteTransactionFailure extends Error {
7
9
  this.errorClass = errorClass;
8
10
  }
9
11
  }
12
+ class SessionFsWriteFailure extends Error {
13
+ writeChanged = true;
14
+ }
10
15
  function normalizeSqliteParams(params) {
11
16
  if (!params) {
12
17
  return void 0;
@@ -29,10 +34,60 @@ function createSessionFsAdapter(provider) {
29
34
  return { content: "", error: toSessionFsError(err) };
30
35
  }
31
36
  },
37
+ readFileBytes: async ({ path }) => {
38
+ if (!provider.readFileBytes) {
39
+ return {
40
+ content: "",
41
+ error: { code: "UNKNOWN", message: "Binary reads are not supported" }
42
+ };
43
+ }
44
+ try {
45
+ const bytes = await provider.readFileBytes(path);
46
+ if (bytes.length > MAX_BINARY_BYTES) {
47
+ return {
48
+ content: "",
49
+ error: {
50
+ code: "UNKNOWN",
51
+ message: "sessionFs.readFileBytes content exceeds the binary read limit"
52
+ }
53
+ };
54
+ }
55
+ return {
56
+ content: Buffer.from(bytes).toString("base64")
57
+ };
58
+ } catch (err) {
59
+ return { content: "", error: toSessionFsError(err) };
60
+ }
61
+ },
32
62
  writeFile: async ({ path, content, mode }) => {
33
63
  try {
34
64
  await provider.writeFile(path, content, mode);
35
65
  return void 0;
66
+ } catch (err) {
67
+ const error = toSessionFsError(err);
68
+ return err instanceof SessionFsWriteFailure ? { ...error, writeChanged: true } : error;
69
+ }
70
+ },
71
+ writeFileBytes: async ({ path, content, mode }) => {
72
+ if (!provider.writeFileBytes) {
73
+ return { code: "UNKNOWN", message: "Binary writes are not supported" };
74
+ }
75
+ if (content.length > MAX_BINARY_CONTENT_LENGTH) {
76
+ return {
77
+ code: "UNKNOWN",
78
+ message: "sessionFs.writeFileBytes content exceeds the binary write limit"
79
+ };
80
+ }
81
+ const bytes = Buffer.from(content, "base64");
82
+ if (bytes.toString("base64") !== content || bytes.length > MAX_BINARY_BYTES) {
83
+ return {
84
+ code: "UNKNOWN",
85
+ message: "invalid sessionFs.writeFileBytes base64 content"
86
+ };
87
+ }
88
+ try {
89
+ await provider.writeFileBytes(path, bytes, mode);
90
+ return void 0;
36
91
  } catch (err) {
37
92
  return toSessionFsError(err);
38
93
  }
@@ -169,5 +224,6 @@ function toSqliteTransactionError(err) {
169
224
  }
170
225
  export {
171
226
  SessionFsSqliteTransactionFailure,
227
+ SessionFsWriteFailure,
172
228
  createSessionFsAdapter
173
229
  };
package/dist/types.d.ts CHANGED
@@ -48,6 +48,7 @@ export type { SessionFsSqliteProvider } from "./sessionFsProvider.js";
48
48
  export type { SessionFsSqliteStatement } from "./sessionFsProvider.js";
49
49
  export type { SessionFsSqliteTransactionErrorClass } from "./sessionFsProvider.js";
50
50
  export { SessionFsSqliteTransactionFailure } from "./sessionFsProvider.js";
51
+ export { SessionFsWriteFailure } from "./sessionFsProvider.js";
51
52
  export type { LlmInferenceHeaders } from "./generated/rpc.js";
52
53
  export type { PermissionDecisionContext, PermissionDecisionOutcome, PermissionDecisionSurface, PermissionResponseCapability, } from "./generated/rpc.js";
53
54
  export type { PermissionDecisionSource } from "./generated/session-events.js";
@@ -922,6 +923,8 @@ export interface SystemMessageReplaceConfig {
922
923
  /**
923
924
  * Customize mode: Override individual sections of the system prompt.
924
925
  * Keeps the SDK-managed prompt structure while allowing targeted modifications.
926
+ * The `last_instructions` section includes configured subagent-model guidance.
927
+ * Its overrides and transforms control that prose, not runtime model selection or tool availability.
925
928
  */
926
929
  export interface SystemMessageCustomizeConfig {
927
930
  mode: "customize";
@@ -1098,8 +1101,9 @@ export type AutoModeSwitchHandler = (request: AutoModeSwitchRequest, invocation:
1098
1101
  * Base interface for all hook inputs
1099
1102
  */
1100
1103
  export interface BaseHookInput {
1101
- /** The runtime session ID of the session that triggered the hook.
1102
- * For sub-agent hooks this differs from `invocation.sessionId`. */
1104
+ /** The runtime session ID associated with the hook. Child tool hooks use
1105
+ * the child session ID; sub-agent lifecycle hooks use the parent session ID,
1106
+ * matching `invocation.sessionId`. */
1103
1107
  sessionId: string;
1104
1108
  /** Time at which the hook event was emitted by the runtime. */
1105
1109
  timestamp: Date;
@@ -1366,6 +1370,54 @@ export interface AgentStopHookOutput {
1366
1370
  export type AgentStopHandler = (input: AgentStopHookInput, invocation: {
1367
1371
  sessionId: string;
1368
1372
  }) => Promise<AgentStopHookOutput | void> | AgentStopHookOutput | void;
1373
+ /**
1374
+ * Input for the hook fired before a sub-agent's first turn.
1375
+ *
1376
+ * The session metadata belongs to the parent session, not the child.
1377
+ */
1378
+ export interface SubagentStartHookInput extends BaseHookInput {
1379
+ transcriptPath: string;
1380
+ agentName: string;
1381
+ agentDisplayName?: string;
1382
+ agentDescription?: string;
1383
+ }
1384
+ /** Output for the sub-agent start hook. Context is prepended to the child's initial prompt. */
1385
+ export interface SubagentStartHookOutput {
1386
+ additionalContext?: string;
1387
+ }
1388
+ /** Handler for the sub-agent start hook. */
1389
+ export type SubagentStartHandler = (input: SubagentStartHookInput, invocation: {
1390
+ sessionId: string;
1391
+ }) => Promise<SubagentStartHookOutput | void> | SubagentStartHookOutput | void;
1392
+ /**
1393
+ * Input for the hook fired after a sub-agent completes a turn.
1394
+ *
1395
+ * The response is the child's last assistant message before any hook rewrite.
1396
+ */
1397
+ export interface SubagentStopHookInput extends SubagentStartHookInput {
1398
+ agentId?: string;
1399
+ agentType: string;
1400
+ stopReason: "end_turn";
1401
+ response: string;
1402
+ }
1403
+ /**
1404
+ * Output for the sub-agent stop hook. `"block"` with a nonempty `reason` continues
1405
+ * the child; otherwise `modifiedResponse` replaces the response reported to the parent.
1406
+ * When both are supplied, a valid block takes precedence over the rewrite.
1407
+ */
1408
+ export type SubagentStopHookOutput = {
1409
+ decision: "block";
1410
+ reason: string;
1411
+ modifiedResponse?: string;
1412
+ } | {
1413
+ decision?: "allow";
1414
+ reason?: never;
1415
+ modifiedResponse?: string;
1416
+ };
1417
+ /** Handler for the sub-agent stop hook. */
1418
+ export type SubagentStopHandler = (input: SubagentStopHookInput, invocation: {
1419
+ sessionId: string;
1420
+ }) => Promise<SubagentStopHookOutput | void> | SubagentStopHookOutput | void;
1369
1421
  /**
1370
1422
  * Configuration for session hooks
1371
1423
  */
@@ -1422,6 +1474,13 @@ export interface SessionHooks {
1422
1474
  * agent stop.
1423
1475
  */
1424
1476
  onAgentStop?: AgentStopHandler;
1477
+ /** Called before a sub-agent's first turn. Return context to prepend to its prompt. */
1478
+ onSubagentStart?: SubagentStartHandler;
1479
+ /**
1480
+ * Called after a sub-agent completes a turn. Return a block reason to
1481
+ * continue the child, or a replacement response to report to the parent.
1482
+ */
1483
+ onSubagentStop?: SubagentStopHandler;
1425
1484
  }
1426
1485
  /**
1427
1486
  * Base interface for MCP server configuration.
@@ -2522,6 +2581,12 @@ export interface ProviderTokenArgs {
2522
2581
  * surface and may change or be removed in future SDK or CLI releases.
2523
2582
  */
2524
2583
  export type BearerTokenProvider = (args: ProviderTokenArgs) => Promise<string>;
2584
+ /**
2585
+ * Product serving a configured provider's model. Allowed values are
2586
+ * "openai", "anthropic", "azure_openai", "ollama", "lm_studio",
2587
+ * "foundry_local", and "llama_cpp".
2588
+ */
2589
+ export type ProviderConfigModelProvider = "openai" | "anthropic" | "azure_openai" | "ollama" | "lm_studio" | "foundry_local" | "llama_cpp";
2525
2590
  /**
2526
2591
  * Configuration for a custom API provider.
2527
2592
  */
@@ -2544,6 +2609,11 @@ export interface ProviderConfig {
2544
2609
  * providers using `wireApi: "responses"`.
2545
2610
  */
2546
2611
  transport?: "http" | "websockets";
2612
+ /**
2613
+ * Product serving the model, such as "ollama" or "lm_studio", reported in
2614
+ * telemetry as `model_provider`. Only affects telemetry.
2615
+ */
2616
+ modelProvider?: ProviderConfigModelProvider;
2547
2617
  /**
2548
2618
  * API endpoint URL
2549
2619
  */
@@ -2637,6 +2707,11 @@ export interface NamedProviderConfig {
2637
2707
  * Wire API format (openai/azure only). Defaults to "completions".
2638
2708
  */
2639
2709
  wireApi?: "completions" | "responses";
2710
+ /**
2711
+ * Product serving this provider's models, such as "ollama" or "lm_studio",
2712
+ * reported in telemetry as `model_provider`. Only affects telemetry.
2713
+ */
2714
+ modelProvider?: ProviderConfigModelProvider;
2640
2715
  /**
2641
2716
  * API endpoint URL.
2642
2717
  */
@@ -2878,6 +2953,12 @@ export interface SessionFsConfig {
2878
2953
  * @default false
2879
2954
  */
2880
2955
  sqlite?: boolean;
2956
+ /**
2957
+ * Whether this provider supports exact binary reads and writes through readFileBytes and writeFileBytes.
2958
+ * Required to view images stored only in the provider.
2959
+ * @default false
2960
+ */
2961
+ binary?: boolean;
2881
2962
  };
2882
2963
  }
2883
2964
  /**
package/dist/types.js CHANGED
@@ -1,5 +1,6 @@
1
1
  import { createSessionFsAdapter } from "./sessionFsProvider.js";
2
2
  import { SessionFsSqliteTransactionFailure } from "./sessionFsProvider.js";
3
+ import { SessionFsWriteFailure } from "./sessionFsProvider.js";
3
4
  import {
4
5
  CopilotRequestHandler,
5
6
  CopilotWebSocketHandler,
@@ -106,10 +107,10 @@ const SYSTEM_MESSAGE_SECTIONS = {
106
107
  tool_instructions: { description: "Per-tool usage instructions" },
107
108
  custom_instructions: { description: "Repository and organization custom instructions" },
108
109
  runtime_instructions: {
109
- description: "Runtime-provided context and instructions (e.g. system notifications, memories, workspace context, mode-specific instructions, content-exclusion policy)"
110
+ description: "Runtime-provided system-prompt context and instructions, such as system notifications, memories, workspace context, and content-exclusion policy. Mode-specific instructions can travel in transition messages instead."
110
111
  },
111
112
  last_instructions: {
112
- description: "End-of-prompt instructions: parallel tool calling, persistence, task completion"
113
+ description: "End-of-prompt instructions: parallel tool calling, persistence, task completion, and configured subagent-model guidance when the task tool is available"
113
114
  }
114
115
  };
115
116
  function isAttributedPermissionResult(result) {
@@ -149,6 +150,7 @@ export {
149
150
  RuntimeConnection,
150
151
  SYSTEM_MESSAGE_SECTIONS,
151
152
  SessionFsSqliteTransactionFailure,
153
+ SessionFsWriteFailure,
152
154
  approveAll,
153
155
  convertMcpCallToolResult,
154
156
  createAttributedPermissionResult,
@@ -122,10 +122,12 @@ hooks: {
122
122
  onSessionStart: async (input, invocation) => { ... },
123
123
  onSessionEnd: async (input, invocation) => { ... },
124
124
  onErrorOccurred: async (input, invocation) => { ... },
125
+ onSubagentStart: async (input, invocation) => { ... },
126
+ onSubagentStop: async (input, invocation) => { ... },
125
127
  }
126
128
  ```
127
129
 
128
- All hook inputs include `timestamp` (`Date`) and `workingDirectory`.
130
+ All hook inputs include `sessionId`, `timestamp` (`Date`) and `workingDirectory`.
129
131
  All handlers receive `invocation: { sessionId: string }` as the second argument.
130
132
  All handlers may return `void`/`undefined` (no-op) or an output object.
131
133
 
@@ -214,7 +216,32 @@ fire it.
214
216
  | `retryCount` | `number` | Max retries (when errorHandling is "retry") |
215
217
  | `userNotification` | `string` | Message shown to the user |
216
218
 
217
- ---
219
+ ### onSubagentStart
220
+
221
+ Fires before a sub-agent's first turn. The input's `sessionId` and the
222
+ invocation's `sessionId` identify the parent session, not the child.
223
+
224
+ **Input:** `{ sessionId: string, transcriptPath: string, agentName: string, agentDisplayName?: string, agentDescription?: string, timestamp, workingDirectory }`
225
+
226
+ **Output (optional):**
227
+ | Field | Type | Effect |
228
+ |-------|------|--------|
229
+ | `additionalContext` | `string` | Prepended to the child's initial prompt |
230
+
231
+ ### onSubagentStop
232
+
233
+ Fires after a sub-agent completes a turn. The input includes the child's last
234
+ assistant `response` and the parent's session metadata. `agentId` is available
235
+ when the task registry supplies one. This is distinct from `onAgentStop`, which
236
+ only runs for the top-level agent.
237
+
238
+ **Input:** `{ sessionId: string, transcriptPath: string, agentName: string, agentDisplayName?: string, agentDescription?: string, agentId?: string, agentType: string, stopReason: "end_turn", response: string, timestamp, workingDirectory }`
239
+
240
+ **Output (choose one, or return nothing):**
241
+ | Field | Type | Effect |
242
+ |-------|------|--------|
243
+ | `decision` and `reason` | `"block"` and `string` | Continue the child for another turn using `reason` |
244
+ | `modifiedResponse` | `string` | Replace the child's response reported to the parent |
218
245
 
219
246
  ## Session Object
220
247
 
package/package.json CHANGED
@@ -5,8 +5,8 @@
5
5
  "url": "https://github.com/github/copilot-agent-runtime.git",
6
6
  "directory": "src/sdk/nodejs"
7
7
  },
8
- "version": "1.0.17-preview.2",
9
- "copilotCliVersion": "1.0.92-2",
8
+ "version": "1.0.17-preview.4",
9
+ "copilotCliVersion": "1.0.92-4",
10
10
  "description": "TypeScript SDK for programmatic control of GitHub Copilot CLI via JSON-RPC",
11
11
  "main": "./dist/cjs/index.js",
12
12
  "types": "./dist/index.d.ts",
@@ -98,22 +98,23 @@
98
98
  },
99
99
  "files": [
100
100
  "dist/**/*",
101
+ "!dist/tsconfig.tsbuildinfo",
101
102
  "docs/**/*",
102
103
  "README.md"
103
104
  ],
104
105
  "copilotRuntime": {
105
- "sourceSha": "ce004f2dae95799f005ce927555112f0684605c2",
106
- "version": "1.0.92-2",
106
+ "sourceSha": "f4385f4f118c567aa0178776aeb45e296e9e6733",
107
+ "version": "1.0.92-4",
107
108
  "visibility": "public"
108
109
  },
109
110
  "optionalDependencies": {
110
- "@github/copilot-sdk-darwin-arm64": "1.0.17-preview.2",
111
- "@github/copilot-sdk-darwin-x64": "1.0.17-preview.2",
112
- "@github/copilot-sdk-linux-arm64": "1.0.17-preview.2",
113
- "@github/copilot-sdk-linux-x64": "1.0.17-preview.2",
114
- "@github/copilot-sdk-linuxmusl-arm64": "1.0.17-preview.2",
115
- "@github/copilot-sdk-linuxmusl-x64": "1.0.17-preview.2",
116
- "@github/copilot-sdk-win32-arm64": "1.0.17-preview.2",
117
- "@github/copilot-sdk-win32-x64": "1.0.17-preview.2"
111
+ "@github/copilot-sdk-darwin-arm64": "1.0.17-preview.4",
112
+ "@github/copilot-sdk-darwin-x64": "1.0.17-preview.4",
113
+ "@github/copilot-sdk-linux-arm64": "1.0.17-preview.4",
114
+ "@github/copilot-sdk-linux-x64": "1.0.17-preview.4",
115
+ "@github/copilot-sdk-linuxmusl-arm64": "1.0.17-preview.4",
116
+ "@github/copilot-sdk-linuxmusl-x64": "1.0.17-preview.4",
117
+ "@github/copilot-sdk-win32-arm64": "1.0.17-preview.4",
118
+ "@github/copilot-sdk-win32-x64": "1.0.17-preview.4"
118
119
  }
119
120
  }