@github/copilot-sdk 0.1.33-preview.3 → 0.1.33-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/README.md CHANGED
@@ -473,7 +473,45 @@ const session = await client.createSession({
473
473
  });
474
474
  ```
475
475
 
476
- The SDK auto-injects environment context, tool instructions, and security guardrails. The default CLI persona is preserved, and your `content` is appended after SDK-managed sections. To change the persona or fully redefine the prompt, use `mode: "replace"`.
476
+ The SDK auto-injects environment context, tool instructions, and security guardrails. The default CLI persona is preserved, and your `content` is appended after SDK-managed sections. To change the persona or fully redefine the prompt, use `mode: "replace"` or `mode: "customize"`.
477
+
478
+ #### Customize Mode
479
+
480
+ Use `mode: "customize"` to selectively override individual sections of the prompt while preserving the rest:
481
+
482
+ ```typescript
483
+ import { SYSTEM_PROMPT_SECTIONS } from "@github/copilot-sdk";
484
+ import type { SectionOverride, SystemPromptSection } from "@github/copilot-sdk";
485
+
486
+ const session = await client.createSession({
487
+ model: "gpt-5",
488
+ systemMessage: {
489
+ mode: "customize",
490
+ sections: {
491
+ // Replace the tone/style section
492
+ tone: { action: "replace", content: "Respond in a warm, professional tone. Be thorough in explanations." },
493
+ // Remove coding-specific rules
494
+ code_change_rules: { action: "remove" },
495
+ // Append to existing guidelines
496
+ guidelines: { action: "append", content: "\n* Always cite data sources" },
497
+ },
498
+ // Additional instructions appended after all sections
499
+ content: "Focus on financial analysis and reporting.",
500
+ },
501
+ });
502
+ ```
503
+
504
+ Available section IDs: `identity`, `tone`, `tool_efficiency`, `environment_context`, `code_change_rules`, `guidelines`, `safety`, `tool_instructions`, `custom_instructions`, `last_instructions`. Use the `SYSTEM_PROMPT_SECTIONS` constant for descriptions of each section.
505
+
506
+ Each section override supports four actions:
507
+ - **`replace`** — Replace the section content entirely
508
+ - **`remove`** — Remove the section from the prompt
509
+ - **`append`** — Add content after the existing section
510
+ - **`prepend`** — Add content before the existing section
511
+
512
+ Unknown section IDs are handled gracefully: content from `replace`/`append`/`prepend` overrides is appended to additional instructions, and `remove` overrides are silently ignored.
513
+
514
+ #### Replace Mode
477
515
 
478
516
  For full control (removes all guardrails), use `mode: "replace"`:
479
517
 
@@ -45,6 +45,30 @@ function toJsonSchema(parameters) {
45
45
  }
46
46
  return parameters;
47
47
  }
48
+ function extractTransformCallbacks(systemMessage) {
49
+ if (!systemMessage || systemMessage.mode !== "customize" || !systemMessage.sections) {
50
+ return { wirePayload: systemMessage, transformCallbacks: void 0 };
51
+ }
52
+ const transformCallbacks = /* @__PURE__ */ new Map();
53
+ const wireSections = {};
54
+ for (const [sectionId, override] of Object.entries(systemMessage.sections)) {
55
+ if (!override) continue;
56
+ if (typeof override.action === "function") {
57
+ transformCallbacks.set(sectionId, override.action);
58
+ wireSections[sectionId] = { action: "transform" };
59
+ } else {
60
+ wireSections[sectionId] = { action: override.action, content: override.content };
61
+ }
62
+ }
63
+ if (transformCallbacks.size === 0) {
64
+ return { wirePayload: systemMessage, transformCallbacks: void 0 };
65
+ }
66
+ const wirePayload = {
67
+ ...systemMessage,
68
+ sections: wireSections
69
+ };
70
+ return { wirePayload, transformCallbacks };
71
+ }
48
72
  function getNodeExecPath() {
49
73
  if (process.versions.bun) {
50
74
  return "node";
@@ -434,6 +458,12 @@ class CopilotClient {
434
458
  if (config.hooks) {
435
459
  session.registerHooks(config.hooks);
436
460
  }
461
+ const { wirePayload: wireSystemMessage, transformCallbacks } = extractTransformCallbacks(
462
+ config.systemMessage
463
+ );
464
+ if (transformCallbacks) {
465
+ session.registerTransformCallbacks(transformCallbacks);
466
+ }
437
467
  if (config.onEvent) {
438
468
  session.on(config.onEvent);
439
469
  }
@@ -452,7 +482,7 @@ class CopilotClient {
452
482
  overridesBuiltInTool: tool.overridesBuiltInTool,
453
483
  skipPermission: tool.skipPermission
454
484
  })),
455
- systemMessage: config.systemMessage,
485
+ systemMessage: wireSystemMessage,
456
486
  availableTools: config.availableTools,
457
487
  excludedTools: config.excludedTools,
458
488
  provider: config.provider,
@@ -529,6 +559,12 @@ class CopilotClient {
529
559
  if (config.hooks) {
530
560
  session.registerHooks(config.hooks);
531
561
  }
562
+ const { wirePayload: wireSystemMessage, transformCallbacks } = extractTransformCallbacks(
563
+ config.systemMessage
564
+ );
565
+ if (transformCallbacks) {
566
+ session.registerTransformCallbacks(transformCallbacks);
567
+ }
532
568
  if (config.onEvent) {
533
569
  session.on(config.onEvent);
534
570
  }
@@ -540,7 +576,7 @@ class CopilotClient {
540
576
  clientName: config.clientName,
541
577
  model: config.model,
542
578
  reasoningEffort: config.reasoningEffort,
543
- systemMessage: config.systemMessage,
579
+ systemMessage: wireSystemMessage,
544
580
  availableTools: config.availableTools,
545
581
  excludedTools: config.excludedTools,
546
582
  tools: config.tools?.map((tool) => ({
@@ -1098,6 +1134,10 @@ stderr: ${stderrOutput}`
1098
1134
  "hooks.invoke",
1099
1135
  async (params) => await this.handleHooksInvoke(params)
1100
1136
  );
1137
+ this.connection.onRequest(
1138
+ "systemMessage.transform",
1139
+ async (params) => await this.handleSystemMessageTransform(params)
1140
+ );
1101
1141
  this.connection.onClose(() => {
1102
1142
  this.state = "disconnected";
1103
1143
  });
@@ -1161,6 +1201,16 @@ stderr: ${stderrOutput}`
1161
1201
  const output = await session._handleHooksInvoke(params.hookType, params.input);
1162
1202
  return { output };
1163
1203
  }
1204
+ async handleSystemMessageTransform(params) {
1205
+ if (!params || typeof params.sessionId !== "string" || !params.sections || typeof params.sections !== "object") {
1206
+ throw new Error("Invalid systemMessage.transform payload");
1207
+ }
1208
+ const session = this.sessions.get(params.sessionId);
1209
+ if (!session) {
1210
+ throw new Error(`Session not found: ${params.sessionId}`);
1211
+ }
1212
+ return await session._handleSystemMessageTransform(params.sections);
1213
+ }
1164
1214
  // ========================================================================
1165
1215
  // Protocol v2 backward-compatibility adapters
1166
1216
  // ========================================================================
@@ -65,7 +65,33 @@ function createSessionRpc(connection, sessionId) {
65
65
  list: async () => connection.sendRequest("session.agent.list", { sessionId }),
66
66
  getCurrent: async () => connection.sendRequest("session.agent.getCurrent", { sessionId }),
67
67
  select: async (params) => connection.sendRequest("session.agent.select", { sessionId, ...params }),
68
- deselect: async () => connection.sendRequest("session.agent.deselect", { sessionId })
68
+ deselect: async () => connection.sendRequest("session.agent.deselect", { sessionId }),
69
+ reload: async () => connection.sendRequest("session.agent.reload", { sessionId })
70
+ },
71
+ /** @experimental */
72
+ skills: {
73
+ list: async () => connection.sendRequest("session.skills.list", { sessionId }),
74
+ enable: async (params) => connection.sendRequest("session.skills.enable", { sessionId, ...params }),
75
+ disable: async (params) => connection.sendRequest("session.skills.disable", { sessionId, ...params }),
76
+ reload: async () => connection.sendRequest("session.skills.reload", { sessionId })
77
+ },
78
+ /** @experimental */
79
+ mcp: {
80
+ list: async () => connection.sendRequest("session.mcp.list", { sessionId }),
81
+ enable: async (params) => connection.sendRequest("session.mcp.enable", { sessionId, ...params }),
82
+ disable: async (params) => connection.sendRequest("session.mcp.disable", { sessionId, ...params }),
83
+ reload: async () => connection.sendRequest("session.mcp.reload", { sessionId })
84
+ },
85
+ /** @experimental */
86
+ plugins: {
87
+ list: async () => connection.sendRequest("session.plugins.list", { sessionId })
88
+ },
89
+ /** @experimental */
90
+ extensions: {
91
+ list: async () => connection.sendRequest("session.extensions.list", { sessionId }),
92
+ enable: async (params) => connection.sendRequest("session.extensions.enable", { sessionId, ...params }),
93
+ disable: async (params) => connection.sendRequest("session.extensions.disable", { sessionId, ...params }),
94
+ reload: async () => connection.sendRequest("session.extensions.reload", { sessionId })
69
95
  },
70
96
  /** @experimental */
71
97
  compaction: {
@@ -74,6 +100,12 @@ function createSessionRpc(connection, sessionId) {
74
100
  tools: {
75
101
  handlePendingToolCall: async (params) => connection.sendRequest("session.tools.handlePendingToolCall", { sessionId, ...params })
76
102
  },
103
+ commands: {
104
+ handlePendingCommand: async (params) => connection.sendRequest("session.commands.handlePendingCommand", { sessionId, ...params })
105
+ },
106
+ ui: {
107
+ elicitation: async (params) => connection.sendRequest("session.ui.elicitation", { sessionId, ...params })
108
+ },
77
109
  permissions: {
78
110
  handlePendingPermissionRequest: async (params) => connection.sendRequest("session.permissions.handlePendingPermissionRequest", { sessionId, ...params })
79
111
  },
package/dist/cjs/index.js CHANGED
@@ -20,6 +20,7 @@ var index_exports = {};
20
20
  __export(index_exports, {
21
21
  CopilotClient: () => import_client.CopilotClient,
22
22
  CopilotSession: () => import_session.CopilotSession,
23
+ SYSTEM_PROMPT_SECTIONS: () => import_types.SYSTEM_PROMPT_SECTIONS,
23
24
  approveAll: () => import_types.approveAll,
24
25
  defineTool: () => import_types.defineTool
25
26
  });
@@ -31,6 +32,7 @@ var import_types = require("./types.js");
31
32
  0 && (module.exports = {
32
33
  CopilotClient,
33
34
  CopilotSession,
35
+ SYSTEM_PROMPT_SECTIONS,
34
36
  approveAll,
35
37
  defineTool
36
38
  });
@@ -48,6 +48,7 @@ class CopilotSession {
48
48
  permissionHandler;
49
49
  userInputHandler;
50
50
  hooks;
51
+ transformCallbacks;
51
52
  _rpc = null;
52
53
  traceContextProvider;
53
54
  /**
@@ -364,6 +365,40 @@ class CopilotSession {
364
365
  registerHooks(hooks) {
365
366
  this.hooks = hooks;
366
367
  }
368
+ /**
369
+ * Registers transform callbacks for system message sections.
370
+ *
371
+ * @param callbacks - Map of section ID to transform callback, or undefined to clear
372
+ * @internal This method is typically called internally when creating a session.
373
+ */
374
+ registerTransformCallbacks(callbacks) {
375
+ this.transformCallbacks = callbacks;
376
+ }
377
+ /**
378
+ * Handles a systemMessage.transform request from the runtime.
379
+ * Dispatches each section to its registered transform callback.
380
+ *
381
+ * @param sections - Map of section IDs to their current rendered content
382
+ * @returns A promise that resolves with the transformed sections
383
+ * @internal This method is for internal use by the SDK.
384
+ */
385
+ async _handleSystemMessageTransform(sections) {
386
+ const result = {};
387
+ for (const [sectionId, { content }] of Object.entries(sections)) {
388
+ const callback = this.transformCallbacks?.get(sectionId);
389
+ if (callback) {
390
+ try {
391
+ const transformed = await callback(content);
392
+ result[sectionId] = { content: transformed };
393
+ } catch (_error) {
394
+ result[sectionId] = { content };
395
+ }
396
+ } else {
397
+ result[sectionId] = { content };
398
+ }
399
+ }
400
+ return { sections: result };
401
+ }
367
402
  /**
368
403
  * Handles a permission request in the v2 protocol format (synchronous RPC).
369
404
  * Used as a back-compat adapter when connected to a v2 server.
package/dist/cjs/types.js CHANGED
@@ -18,6 +18,7 @@ var __copyProps = (to, from, except, desc) => {
18
18
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
19
  var types_exports = {};
20
20
  __export(types_exports, {
21
+ SYSTEM_PROMPT_SECTIONS: () => SYSTEM_PROMPT_SECTIONS,
21
22
  approveAll: () => approveAll,
22
23
  defineTool: () => defineTool
23
24
  });
@@ -25,9 +26,24 @@ module.exports = __toCommonJS(types_exports);
25
26
  function defineTool(name, config) {
26
27
  return { name, ...config };
27
28
  }
29
+ const SYSTEM_PROMPT_SECTIONS = {
30
+ identity: { description: "Agent identity preamble and mode statement" },
31
+ tone: { description: "Response style, conciseness rules, output formatting preferences" },
32
+ tool_efficiency: { description: "Tool usage patterns, parallel calling, batching guidelines" },
33
+ environment_context: { description: "CWD, OS, git root, directory listing, available tools" },
34
+ code_change_rules: { description: "Coding rules, linting/testing, ecosystem tools, style" },
35
+ guidelines: { description: "Tips, behavioral best practices, behavioral guidelines" },
36
+ safety: { description: "Environment limitations, prohibited actions, security policies" },
37
+ tool_instructions: { description: "Per-tool usage instructions" },
38
+ custom_instructions: { description: "Repository and organization custom instructions" },
39
+ last_instructions: {
40
+ description: "End-of-prompt instructions: parallel tool calling, persistence, task completion"
41
+ }
42
+ };
28
43
  const approveAll = () => ({ kind: "approved" });
29
44
  // Annotate the CommonJS export names for ESM import in node:
30
45
  0 && (module.exports = {
46
+ SYSTEM_PROMPT_SECTIONS,
31
47
  approveAll,
32
48
  defineTool
33
49
  });
package/dist/client.d.ts CHANGED
@@ -423,6 +423,7 @@ export declare class CopilotClient {
423
423
  private handleSessionLifecycleNotification;
424
424
  private handleUserInputRequest;
425
425
  private handleHooksInvoke;
426
+ private handleSystemMessageTransform;
426
427
  /**
427
428
  * Handles a v2-style tool.call RPC request from the server.
428
429
  * Looks up the session and tool handler, executes it, and returns the result
package/dist/client.js CHANGED
@@ -25,6 +25,30 @@ function toJsonSchema(parameters) {
25
25
  }
26
26
  return parameters;
27
27
  }
28
+ function extractTransformCallbacks(systemMessage) {
29
+ if (!systemMessage || systemMessage.mode !== "customize" || !systemMessage.sections) {
30
+ return { wirePayload: systemMessage, transformCallbacks: void 0 };
31
+ }
32
+ const transformCallbacks = /* @__PURE__ */ new Map();
33
+ const wireSections = {};
34
+ for (const [sectionId, override] of Object.entries(systemMessage.sections)) {
35
+ if (!override) continue;
36
+ if (typeof override.action === "function") {
37
+ transformCallbacks.set(sectionId, override.action);
38
+ wireSections[sectionId] = { action: "transform" };
39
+ } else {
40
+ wireSections[sectionId] = { action: override.action, content: override.content };
41
+ }
42
+ }
43
+ if (transformCallbacks.size === 0) {
44
+ return { wirePayload: systemMessage, transformCallbacks: void 0 };
45
+ }
46
+ const wirePayload = {
47
+ ...systemMessage,
48
+ sections: wireSections
49
+ };
50
+ return { wirePayload, transformCallbacks };
51
+ }
28
52
  function getNodeExecPath() {
29
53
  if (process.versions.bun) {
30
54
  return "node";
@@ -414,6 +438,12 @@ class CopilotClient {
414
438
  if (config.hooks) {
415
439
  session.registerHooks(config.hooks);
416
440
  }
441
+ const { wirePayload: wireSystemMessage, transformCallbacks } = extractTransformCallbacks(
442
+ config.systemMessage
443
+ );
444
+ if (transformCallbacks) {
445
+ session.registerTransformCallbacks(transformCallbacks);
446
+ }
417
447
  if (config.onEvent) {
418
448
  session.on(config.onEvent);
419
449
  }
@@ -432,7 +462,7 @@ class CopilotClient {
432
462
  overridesBuiltInTool: tool.overridesBuiltInTool,
433
463
  skipPermission: tool.skipPermission
434
464
  })),
435
- systemMessage: config.systemMessage,
465
+ systemMessage: wireSystemMessage,
436
466
  availableTools: config.availableTools,
437
467
  excludedTools: config.excludedTools,
438
468
  provider: config.provider,
@@ -509,6 +539,12 @@ class CopilotClient {
509
539
  if (config.hooks) {
510
540
  session.registerHooks(config.hooks);
511
541
  }
542
+ const { wirePayload: wireSystemMessage, transformCallbacks } = extractTransformCallbacks(
543
+ config.systemMessage
544
+ );
545
+ if (transformCallbacks) {
546
+ session.registerTransformCallbacks(transformCallbacks);
547
+ }
512
548
  if (config.onEvent) {
513
549
  session.on(config.onEvent);
514
550
  }
@@ -520,7 +556,7 @@ class CopilotClient {
520
556
  clientName: config.clientName,
521
557
  model: config.model,
522
558
  reasoningEffort: config.reasoningEffort,
523
- systemMessage: config.systemMessage,
559
+ systemMessage: wireSystemMessage,
524
560
  availableTools: config.availableTools,
525
561
  excludedTools: config.excludedTools,
526
562
  tools: config.tools?.map((tool) => ({
@@ -1078,6 +1114,10 @@ stderr: ${stderrOutput}`
1078
1114
  "hooks.invoke",
1079
1115
  async (params) => await this.handleHooksInvoke(params)
1080
1116
  );
1117
+ this.connection.onRequest(
1118
+ "systemMessage.transform",
1119
+ async (params) => await this.handleSystemMessageTransform(params)
1120
+ );
1081
1121
  this.connection.onClose(() => {
1082
1122
  this.state = "disconnected";
1083
1123
  });
@@ -1141,6 +1181,16 @@ stderr: ${stderrOutput}`
1141
1181
  const output = await session._handleHooksInvoke(params.hookType, params.input);
1142
1182
  return { output };
1143
1183
  }
1184
+ async handleSystemMessageTransform(params) {
1185
+ if (!params || typeof params.sessionId !== "string" || !params.sections || typeof params.sections !== "object") {
1186
+ throw new Error("Invalid systemMessage.transform payload");
1187
+ }
1188
+ const session = this.sessions.get(params.sessionId);
1189
+ if (!session) {
1190
+ throw new Error(`Session not found: ${params.sessionId}`);
1191
+ }
1192
+ return await session._handleSystemMessageTransform(params.sections);
1193
+ }
1144
1194
  // ========================================================================
1145
1195
  // Protocol v2 backward-compatibility adapters
1146
1196
  // ========================================================================