@github/copilot-sdk 0.1.33-preview.2 → 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/dist/client.d.ts CHANGED
@@ -47,6 +47,7 @@ export declare class CopilotClient {
47
47
  private isExternalServer;
48
48
  private forceStopping;
49
49
  private onListModels?;
50
+ private onGetTraceContext?;
50
51
  private modelsCache;
51
52
  private modelsCacheLock;
52
53
  private sessionLifecycleHandlers;
@@ -422,6 +423,7 @@ export declare class CopilotClient {
422
423
  private handleSessionLifecycleNotification;
423
424
  private handleUserInputRequest;
424
425
  private handleHooksInvoke;
426
+ private handleSystemMessageTransform;
425
427
  /**
426
428
  * Handles a v2-style tool.call RPC request from the server.
427
429
  * Looks up the session and tool handler, executes it, and returns the result
package/dist/client.js CHANGED
@@ -1,6 +1,7 @@
1
1
  import { spawn } from "node:child_process";
2
2
  import { randomUUID } from "node:crypto";
3
3
  import { existsSync } from "node:fs";
4
+ import { createRequire } from "node:module";
4
5
  import { Socket } from "node:net";
5
6
  import { dirname, join } from "node:path";
6
7
  import { fileURLToPath } from "node:url";
@@ -12,6 +13,7 @@ import {
12
13
  import { createServerRpc } from "./generated/rpc.js";
13
14
  import { getSdkProtocolVersion } from "./sdkProtocolVersion.js";
14
15
  import { CopilotSession, NO_RESULT_PERMISSION_V2_ERROR } from "./session.js";
16
+ import { getTraceContext } from "./telemetry.js";
15
17
  const MIN_PROTOCOL_VERSION = 2;
16
18
  function isZodSchema(value) {
17
19
  return value != null && typeof value === "object" && "toJSONSchema" in value && typeof value.toJSONSchema === "function";
@@ -23,6 +25,30 @@ function toJsonSchema(parameters) {
23
25
  }
24
26
  return parameters;
25
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
+ }
26
52
  function getNodeExecPath() {
27
53
  if (process.versions.bun) {
28
54
  return "node";
@@ -30,9 +56,22 @@ function getNodeExecPath() {
30
56
  return process.execPath;
31
57
  }
32
58
  function getBundledCliPath() {
33
- const sdkUrl = import.meta.resolve("@github/copilot/sdk");
34
- const sdkPath = fileURLToPath(sdkUrl);
35
- return join(dirname(dirname(sdkPath)), "index.js");
59
+ if (typeof import.meta.resolve === "function") {
60
+ const sdkUrl = import.meta.resolve("@github/copilot/sdk");
61
+ const sdkPath = fileURLToPath(sdkUrl);
62
+ return join(dirname(dirname(sdkPath)), "index.js");
63
+ }
64
+ const req = createRequire(__filename);
65
+ const searchPaths = req.resolve.paths("@github/copilot") ?? [];
66
+ for (const base of searchPaths) {
67
+ const candidate = join(base, "@github", "copilot", "index.js");
68
+ if (existsSync(candidate)) {
69
+ return candidate;
70
+ }
71
+ }
72
+ throw new Error(
73
+ `Could not find @github/copilot package. Searched ${searchPaths.length} paths. Ensure it is installed, or pass cliPath/cliUrl to CopilotClient.`
74
+ );
36
75
  }
37
76
  class CopilotClient {
38
77
  cliProcess = null;
@@ -48,6 +87,7 @@ class CopilotClient {
48
87
  isExternalServer = false;
49
88
  forceStopping = false;
50
89
  onListModels;
90
+ onGetTraceContext;
51
91
  modelsCache = null;
52
92
  modelsCacheLock = Promise.resolve();
53
93
  sessionLifecycleHandlers = /* @__PURE__ */ new Set();
@@ -114,6 +154,7 @@ class CopilotClient {
114
154
  this.isExternalServer = true;
115
155
  }
116
156
  this.onListModels = options.onListModels;
157
+ this.onGetTraceContext = options.onGetTraceContext;
117
158
  this.options = {
118
159
  cliPath: options.cliUrl ? void 0 : options.cliPath || getBundledCliPath(),
119
160
  cliArgs: options.cliArgs ?? [],
@@ -129,7 +170,8 @@ class CopilotClient {
129
170
  env: options.env ?? process.env,
130
171
  githubToken: options.githubToken,
131
172
  // Default useLoggedInUser to false when githubToken is provided, otherwise true
132
- useLoggedInUser: options.useLoggedInUser ?? (options.githubToken ? false : true)
173
+ useLoggedInUser: options.useLoggedInUser ?? (options.githubToken ? false : true),
174
+ telemetry: options.telemetry
133
175
  };
134
176
  }
135
177
  /**
@@ -382,7 +424,12 @@ class CopilotClient {
382
424
  }
383
425
  }
384
426
  const sessionId = config.sessionId ?? randomUUID();
385
- const session = new CopilotSession(sessionId, this.connection);
427
+ const session = new CopilotSession(
428
+ sessionId,
429
+ this.connection,
430
+ void 0,
431
+ this.onGetTraceContext
432
+ );
386
433
  session.registerTools(config.tools);
387
434
  session.registerPermissionHandler(config.onPermissionRequest);
388
435
  if (config.onUserInputRequest) {
@@ -391,12 +438,19 @@ class CopilotClient {
391
438
  if (config.hooks) {
392
439
  session.registerHooks(config.hooks);
393
440
  }
441
+ const { wirePayload: wireSystemMessage, transformCallbacks } = extractTransformCallbacks(
442
+ config.systemMessage
443
+ );
444
+ if (transformCallbacks) {
445
+ session.registerTransformCallbacks(transformCallbacks);
446
+ }
394
447
  if (config.onEvent) {
395
448
  session.on(config.onEvent);
396
449
  }
397
450
  this.sessions.set(sessionId, session);
398
451
  try {
399
452
  const response = await this.connection.sendRequest("session.create", {
453
+ ...await getTraceContext(this.onGetTraceContext),
400
454
  model: config.model,
401
455
  sessionId,
402
456
  clientName: config.clientName,
@@ -408,7 +462,7 @@ class CopilotClient {
408
462
  overridesBuiltInTool: tool.overridesBuiltInTool,
409
463
  skipPermission: tool.skipPermission
410
464
  })),
411
- systemMessage: config.systemMessage,
465
+ systemMessage: wireSystemMessage,
412
466
  availableTools: config.availableTools,
413
467
  excludedTools: config.excludedTools,
414
468
  provider: config.provider,
@@ -471,7 +525,12 @@ class CopilotClient {
471
525
  throw new Error("Client not connected. Call start() first.");
472
526
  }
473
527
  }
474
- const session = new CopilotSession(sessionId, this.connection);
528
+ const session = new CopilotSession(
529
+ sessionId,
530
+ this.connection,
531
+ void 0,
532
+ this.onGetTraceContext
533
+ );
475
534
  session.registerTools(config.tools);
476
535
  session.registerPermissionHandler(config.onPermissionRequest);
477
536
  if (config.onUserInputRequest) {
@@ -480,17 +539,24 @@ class CopilotClient {
480
539
  if (config.hooks) {
481
540
  session.registerHooks(config.hooks);
482
541
  }
542
+ const { wirePayload: wireSystemMessage, transformCallbacks } = extractTransformCallbacks(
543
+ config.systemMessage
544
+ );
545
+ if (transformCallbacks) {
546
+ session.registerTransformCallbacks(transformCallbacks);
547
+ }
483
548
  if (config.onEvent) {
484
549
  session.on(config.onEvent);
485
550
  }
486
551
  this.sessions.set(sessionId, session);
487
552
  try {
488
553
  const response = await this.connection.sendRequest("session.resume", {
554
+ ...await getTraceContext(this.onGetTraceContext),
489
555
  sessionId,
490
556
  clientName: config.clientName,
491
557
  model: config.model,
492
558
  reasoningEffort: config.reasoningEffort,
493
- systemMessage: config.systemMessage,
559
+ systemMessage: wireSystemMessage,
494
560
  availableTools: config.availableTools,
495
561
  excludedTools: config.excludedTools,
496
562
  tools: config.tools?.map((tool) => ({
@@ -829,6 +895,22 @@ class CopilotClient {
829
895
  "Path to Copilot CLI is required. Please provide it via the cliPath option, or use cliUrl to rely on a remote CLI."
830
896
  );
831
897
  }
898
+ if (this.options.telemetry) {
899
+ const t = this.options.telemetry;
900
+ envWithoutNodeDebug.COPILOT_OTEL_ENABLED = "true";
901
+ if (t.otlpEndpoint !== void 0)
902
+ envWithoutNodeDebug.OTEL_EXPORTER_OTLP_ENDPOINT = t.otlpEndpoint;
903
+ if (t.filePath !== void 0)
904
+ envWithoutNodeDebug.COPILOT_OTEL_FILE_EXPORTER_PATH = t.filePath;
905
+ if (t.exporterType !== void 0)
906
+ envWithoutNodeDebug.COPILOT_OTEL_EXPORTER_TYPE = t.exporterType;
907
+ if (t.sourceName !== void 0)
908
+ envWithoutNodeDebug.COPILOT_OTEL_SOURCE_NAME = t.sourceName;
909
+ if (t.captureContent !== void 0)
910
+ envWithoutNodeDebug.OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT = String(
911
+ t.captureContent
912
+ );
913
+ }
832
914
  if (!existsSync(this.options.cliPath)) {
833
915
  throw new Error(
834
916
  `Copilot CLI not found at ${this.options.cliPath}. Ensure @github/copilot is installed.`
@@ -1032,6 +1114,10 @@ stderr: ${stderrOutput}`
1032
1114
  "hooks.invoke",
1033
1115
  async (params) => await this.handleHooksInvoke(params)
1034
1116
  );
1117
+ this.connection.onRequest(
1118
+ "systemMessage.transform",
1119
+ async (params) => await this.handleSystemMessageTransform(params)
1120
+ );
1035
1121
  this.connection.onClose(() => {
1036
1122
  this.state = "disconnected";
1037
1123
  });
@@ -1095,6 +1181,16 @@ stderr: ${stderrOutput}`
1095
1181
  const output = await session._handleHooksInvoke(params.hookType, params.input);
1096
1182
  return { output };
1097
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
+ }
1098
1194
  // ========================================================================
1099
1195
  // Protocol v2 backward-compatibility adapters
1100
1196
  // ========================================================================
@@ -1123,11 +1219,15 @@ stderr: ${stderrOutput}`
1123
1219
  };
1124
1220
  }
1125
1221
  try {
1222
+ const traceparent = params.traceparent;
1223
+ const tracestate = params.tracestate;
1126
1224
  const invocation = {
1127
1225
  sessionId: params.sessionId,
1128
1226
  toolCallId: params.toolCallId,
1129
1227
  toolName: params.toolName,
1130
- arguments: params.arguments
1228
+ arguments: params.arguments,
1229
+ traceparent,
1230
+ tracestate
1131
1231
  };
1132
1232
  const result = await handler(params.arguments, invocation);
1133
1233
  return { result: this.normalizeToolResultV2(result) };