@github/copilot-sdk 1.0.29 → 1.0.30-preview.1

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.
@@ -0,0 +1,139 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+ var decisions_exports = {};
20
+ __export(decisions_exports, {
21
+ CopilotDecisions: () => CopilotDecisions,
22
+ decisionErrorData: () => decisionErrorData,
23
+ decisionErrorKind: () => decisionErrorKind
24
+ });
25
+ module.exports = __toCommonJS(decisions_exports);
26
+ var import_node = require("vscode-jsonrpc/node");
27
+ class CopilotDecisions {
28
+ constructor(rpc) {
29
+ this.rpc = rpc;
30
+ }
31
+ rpc;
32
+ /**
33
+ * The decision models the account can call: `models.list`'s `decisionModels`,
34
+ * or an empty list when the runtime does not report them (the feature is off).
35
+ */
36
+ async listModels(request, options) {
37
+ const list = await withAbort(() => this.rpc().models.list(request ?? {}), options?.signal);
38
+ return list.decisionModels ?? [];
39
+ }
40
+ /** Asks every question in `request` and returns the answers, also indexed by name. */
41
+ async ask(request, options) {
42
+ const result = await withAbort(() => this.rpc().decisions.ask(request), options?.signal);
43
+ return {
44
+ ...result,
45
+ byName: Object.fromEntries(result.answers.map((answer) => [answer.name, answer]))
46
+ };
47
+ }
48
+ /** Asks one yes/no question about `context`, which may be plain text or a structured context. */
49
+ async yesNo(question, context, options) {
50
+ const threshold = options?.threshold ?? 0.5;
51
+ const result = await this.ask(
52
+ {
53
+ context: typeof context === "string" ? { kind: "text", text: context } : context,
54
+ questions: [{ kind: "boolean", name: "answer", instructions: question }],
55
+ ...options?.selectionId !== void 0 ? { selectionId: options.selectionId } : {},
56
+ ...options?.gitHubToken !== void 0 ? { gitHubToken: options.gitHubToken } : {},
57
+ ...options?.model !== void 0 ? { model: options.model } : {},
58
+ ...options?.timeoutMs !== void 0 ? { timeoutMs: options.timeoutMs } : {},
59
+ ...options?.purpose !== void 0 ? { purpose: options.purpose } : {}
60
+ },
61
+ options
62
+ );
63
+ const answer = result.answers[0];
64
+ if (answer?.kind !== "boolean") {
65
+ return { refused: true };
66
+ }
67
+ return {
68
+ refused: false,
69
+ yes: answer.probability >= threshold,
70
+ probability: answer.probability
71
+ };
72
+ }
73
+ }
74
+ function decisionErrorData(error) {
75
+ if (!(error instanceof import_node.ResponseError)) {
76
+ return void 0;
77
+ }
78
+ const data = error.data;
79
+ if (typeof data !== "object" || data === null) {
80
+ return void 0;
81
+ }
82
+ const kind = data.kind;
83
+ if (typeof kind !== "string" || !DECISION_ERROR_KINDS.has(kind)) {
84
+ return void 0;
85
+ }
86
+ return data;
87
+ }
88
+ const DECISION_ERROR_KINDS = /* @__PURE__ */ new Set([
89
+ "notEnabled",
90
+ "noModel",
91
+ "unauthenticated",
92
+ "invalidRequest",
93
+ "tooLarge",
94
+ "upstreamProtocol",
95
+ "rateLimited",
96
+ "timeout",
97
+ "unavailable",
98
+ "overloaded"
99
+ ]);
100
+ function decisionErrorKind(error) {
101
+ return decisionErrorData(error)?.kind;
102
+ }
103
+ function abortError(signal) {
104
+ const reason = signal.reason;
105
+ if (reason instanceof Error && reason.name === "AbortError") {
106
+ return reason;
107
+ }
108
+ const error = new Error("The decisions call was aborted");
109
+ error.name = "AbortError";
110
+ return error;
111
+ }
112
+ function withAbort(call, signal) {
113
+ if (!signal) {
114
+ return call();
115
+ }
116
+ if (signal.aborted) {
117
+ return Promise.reject(abortError(signal));
118
+ }
119
+ return new Promise((resolve, reject) => {
120
+ const onAbort = () => reject(abortError(signal));
121
+ signal.addEventListener("abort", onAbort, { once: true });
122
+ call().then(
123
+ (value) => {
124
+ signal.removeEventListener("abort", onAbort);
125
+ resolve(value);
126
+ },
127
+ (error) => {
128
+ signal.removeEventListener("abort", onAbort);
129
+ reject(error);
130
+ }
131
+ );
132
+ });
133
+ }
134
+ // Annotate the CommonJS export names for ESM import in node:
135
+ 0 && (module.exports = {
136
+ CopilotDecisions,
137
+ decisionErrorData,
138
+ decisionErrorKind
139
+ });
@@ -289,6 +289,17 @@ function createServerRpc(connection) {
289
289
  listTokenPriceUnits: async (params) => connection.sendRequest("models.listTokenPriceUnits", params)
290
290
  },
291
291
  /** @experimental */
292
+ decisions: {
293
+ /**
294
+ * Asks a decision model yes/no, pick-one, or rating questions about shared context and returns normalized probabilities. Sessionless, so a host can classify or route a request before any session exists. Requires the `DECISIONS_API` feature flag. A failed request is a JSON-RPC error whose `data` is a `DecisionErrorData`.
295
+ *
296
+ * @param params One request to a decision model: shared context plus the questions to answer about it.
297
+ *
298
+ * @returns The decision model's answers.
299
+ */
300
+ ask: async (params) => connection.sendRequest("decisions.ask", params)
301
+ },
302
+ /** @experimental */
292
303
  azureMl: {
293
304
  /**
294
305
  * Lists eligible Azure ML local models and redacted warnings before a chat session exists.
@@ -957,13 +968,13 @@ function createServerRpc(connection) {
957
968
  httpResponseChunk: async (params) => connection.sendRequest("llmInference.httpResponseChunk", params)
958
969
  },
959
970
  /** @experimental */
960
- kerberosAuth: {
971
+ network: {
961
972
  /**
962
- * Registers the calling SDK client's Kerberos callback. The callback authenticates requests made for the client's sessions and, with `runtime` scope, the runtime's shared background traffic; only one connection may hold `runtime` scope. The registration ends when the connection closes.
973
+ * Registers the calling SDK client's network callbacks, replacing any previous registration. With `resolveProxy`, the client decides the proxies for every request the runtime would otherwise route by ambient proxy settings (proxy environment variables, `NO_PROXY` and operating-system settings), or leaves a request to that routing; requests with an explicitly configured proxy and loopback targets never consult it. With `authenticateNegotiate`, the client supplies the Kerberos tokens for Negotiate proxy challenges instead of native credential lookup. The callbacks serve requests made for the client's sessions and, with `runtime` scope, the runtime's shared traffic, which includes background requests and remote MCP server connections; only one connection may hold `runtime` scope. The registration ends when the connection closes.
963
974
  *
964
- * @param params Registers the calling SDK connection's Kerberos credential provider.
975
+ * @param params Registers the calling SDK connection's network callbacks, replacing any previous registration.
965
976
  */
966
- setProvider: async (params) => connection.sendRequest("kerberosAuth.setProvider", params)
977
+ setProvider: async (params) => connection.sendRequest("network.setProvider", params)
967
978
  },
968
979
  /** @experimental */
969
980
  sessions: {
@@ -1205,6 +1216,17 @@ function createServerRpc(connection) {
1205
1216
  * @returns Entries for the selected account.
1206
1217
  */
1207
1218
  refresh: async (params) => connection.sendRequest("connectors.refresh", params)
1219
+ },
1220
+ /** @experimental */
1221
+ lsp: {
1222
+ /**
1223
+ * Reads the process-wide language-server inventory for a working directory without starting servers. Uses the host configuration home and persisted workspace trust.
1224
+ *
1225
+ * @param params Parameters for a process-wide, read-only language-server inventory.
1226
+ *
1227
+ * @returns Runtime-owned configuration inventory and configuration diagnostics.
1228
+ */
1229
+ list: async (params) => connection.sendRequest("lsp.list", params)
1208
1230
  }
1209
1231
  };
1210
1232
  }
@@ -1506,6 +1528,12 @@ function createInternalServerRpc(connection) {
1506
1528
  * @returns Outcome of validating and writing one top-level setting subtree.
1507
1529
  */
1508
1530
  applyTopKey: async (params) => connection.sendRequest("user.settings.applyTopKey", params),
1531
+ /**
1532
+ * Writes or removes one raw user setting under the settings transaction and file locks. Preserves unrelated keys and legacy spellings, and records explicit mutations so startup cleanup cannot delete the user's choice. Unlike applyTopKey, this operation does not validate or canonicalize settings. Invalid or unreadable files are replaced by default, matching the existing raw writer; set refuseOnReadFailure=true to reject instead. Deletion requires delete=true; otherwise value must be present.
1533
+ *
1534
+ * @param params A raw top-level setting edit with explicit read-failure behavior.
1535
+ */
1536
+ writeKey: async (params) => connection.sendRequest("user.settings.writeKey", params),
1509
1537
  /**
1510
1538
  * Replaces the user settings file's entire content in one write. A key absent from `settings` is removed, which is what distinguishes this from `user.settings.set`: that one merges, so it can never clear a key the caller has dropped. For a caller saving the result of a raw edit, a merge would silently resurrect every key the user deleted. Records the same one-time mutation marks a per-key write records, so a setting the user has now chosen explicitly stops being migrated for them.
1511
1539
  *
@@ -2812,6 +2840,14 @@ function createSessionRpc(connection, sessionId) {
2812
2840
  * @returns The session's authoritative model snapshot. Auto preference fields are configuration for the virtual `auto` model and do not change the selected model identifier. The context tier reflects `Session.getContextTier()`, restored from the session journal on resume.
2813
2841
  */
2814
2842
  getCurrent: async () => connection.sendRequest("session.model.getCurrent", { sessionId }),
2843
+ /**
2844
+ * Reads the session's cached startup model state without fetching a catalog or resolving credentials. An interactive host can claim the one-time enablement prompt after applying its startup configuration. Claims remain shared with the owning host and are scoped to this session's lifetime.
2845
+ *
2846
+ * @param params Options for a host's startup model admission check.
2847
+ *
2848
+ * @returns A cached startup model snapshot and an optional one-time enablement prompt. This check never resolves credentials or fetches a catalog.
2849
+ */
2850
+ startupAdmission: async (params) => connection.sendRequest("session.model.startupAdmission", { ...params, sessionId }),
2815
2851
  /**
2816
2852
  * Switches the session to a model and optional reasoning configuration.
2817
2853
  *
@@ -2841,7 +2877,7 @@ function createSessionRpc(connection, sessionId) {
2841
2877
  *
2842
2878
  * @param params Reasoning effort level to apply to the currently selected model.
2843
2879
  *
2844
- * @returns Update the session's reasoning effort without changing the selected model. Use `switchTo` instead when you also need to change the model. The runtime stores the effort on the session and applies it to subsequent turns.
2880
+ * @returns Update the session's reasoning effort without changing the selected model. Use `switchTo` instead when you also need to change the model. The runtime applies the effort to the next new model request, including tool continuations, without changing retries of an already-started request.
2845
2881
  */
2846
2882
  setReasoningEffort: async (params) => connection.sendRequest("session.model.setReasoningEffort", { ...params, sessionId }),
2847
2883
  /**
@@ -3787,6 +3823,12 @@ function createSessionRpc(connection, sessionId) {
3787
3823
  */
3788
3824
  refresh: async (params) => connection.sendRequest("session.plugins.marketplaces.refresh", { ...params, sessionId })
3789
3825
  },
3826
+ /**
3827
+ * Reads Team and managed soft plugin defaults for the live session. Does not install plugins or persist user preferences.
3828
+ *
3829
+ * @returns Soft plugin defaults for this session, without persistent user preferences or hard policy.
3830
+ */
3831
+ getDefaults: async () => connection.sendRequest("session.plugins.getDefaults", { sessionId }),
3790
3832
  /**
3791
3833
  * Reloads the session's plugin set, refreshing MCP servers, custom agents, hooks, and skills cache so SDK-driven changes via `server.plugins.*` take effect immediately.
3792
3834
  *
@@ -3861,7 +3903,41 @@ function createSessionRpc(connection, sessionId) {
3861
3903
  *
3862
3904
  * @param params Parameters for (re)loading the merged LSP configuration set.
3863
3905
  */
3864
- initialize: async (params) => connection.sendRequest("session.lsp.initialize", { ...params, sessionId })
3906
+ initialize: async (params) => connection.sendRequest("session.lsp.initialize", { ...params, sessionId }),
3907
+ /**
3908
+ * Reads language-server configuration and diagnostics using the session's settings and active plugins. Explicit force reloads the files from disk.
3909
+ *
3910
+ * @param params Parameters for (re)loading the merged LSP configuration set.
3911
+ *
3912
+ * @returns Runtime-owned configuration inventory and configuration diagnostics.
3913
+ */
3914
+ list: async (params) => connection.sendRequest("session.lsp.list", { ...params, sessionId }),
3915
+ /**
3916
+ * Initializes and retains configured language servers under the session's effective LSP sandbox policy. The runtime owns client leases, callbacks, and process lifetime.
3917
+ *
3918
+ * @param params Parameters for (re)loading the merged LSP configuration set.
3919
+ *
3920
+ * @returns The servers retained by the session after warmup.
3921
+ */
3922
+ start: async (params) => connection.sendRequest("session.lsp.start", { ...params, sessionId }),
3923
+ /**
3924
+ * Stops the session's language-server clients without changing another session or the process-wide inventory.
3925
+ */
3926
+ stop: async () => connection.sendRequest("session.lsp.stop", { sessionId }),
3927
+ /**
3928
+ * Probes one configured language-server process under the session's effective LSP sandbox policy, then terminates the probe process.
3929
+ *
3930
+ * @param params A server selected for a startup probe.
3931
+ *
3932
+ * @returns Result of a language-server startup probe.
3933
+ */
3934
+ diagnose: async (params) => connection.sendRequest("session.lsp.diagnose", { ...params, sessionId }),
3935
+ /**
3936
+ * Persists a user-level language-server enable override in the session's configuration home. Reload configuration to apply it.
3937
+ *
3938
+ * @param params A persistent user-level server toggle.
3939
+ */
3940
+ set: async (params) => connection.sendRequest("session.lsp.set", { ...params, sessionId })
3865
3941
  },
3866
3942
  /** @experimental */
3867
3943
  extensions: {
@@ -4114,11 +4190,13 @@ function createSessionRpc(connection, sessionId) {
4114
4190
  */
4115
4191
  handlePendingExitPlanMode: async (params) => connection.sendRequest("session.ui.handlePendingExitPlanMode", { ...params, sessionId }),
4116
4192
  /**
4117
- * Registers an in-process handler for auto-mode-switch requests so the server bridge skips dispatch.
4193
+ * Registers an in-process handler for auto-mode-switch requests so the server bridge skips dispatch. Set `autoModeRecovery` to also handle Auto recovery consent offers.
4194
+ *
4195
+ * @param params Optional recovery-aware enrollment for an in-process Auto-switch handler.
4118
4196
  *
4119
- * @returns Register an in-process handler for `auto_mode_switch.requested` events. The caller still attaches the actual listener via the standard event-subscription mechanism; this registration solely tells the server bridge to skip its own dispatch (so a remote client doesn't race the in-process handler for the same requestId).
4197
+ * @returns Registers an in-process Auto-switch responder and suppresses server-bridge dispatch to avoid competing responders for the same requestId. When requested, also enrolls the responder for active-request Auto recovery and acknowledges support. Attach the actual listener separately through standard event subscriptions before starting a turn, and release the handle when the responder is removed.
4120
4198
  */
4121
- registerDirectAutoModeSwitchHandler: async () => connection.sendRequest("session.ui.registerDirectAutoModeSwitchHandler", { sessionId }),
4199
+ registerDirectAutoModeSwitchHandler: async (params) => connection.sendRequest("session.ui.registerDirectAutoModeSwitchHandler", { ...params, sessionId }),
4122
4200
  /**
4123
4201
  * Unregisters a previously-registered in-process auto-mode-switch handler by its opaque handle.
4124
4202
  *
@@ -4935,7 +5013,74 @@ function createInternalSessionRpc(connection, sessionId) {
4935
5013
  *
4936
5014
  * @param params Server name identifying the external client to remove.
4937
5015
  */
4938
- unregisterExternalClient: async (params) => connection.sendRequest("session.mcp.unregisterExternalClient", { ...params, sessionId })
5016
+ unregisterExternalClient: async (params) => connection.sendRequest("session.mcp.unregisterExternalClient", { ...params, sessionId }),
5017
+ /** @experimental */
5018
+ oauth: {
5019
+ /**
5020
+ * Reserves a host-driven OAuth flow identity before authentication or cancellation.
5021
+ *
5022
+ * @param params Correlation identity reserved before an effectful authentication request.
5023
+ */
5024
+ prepareFlow: async (params) => connection.sendRequest("session.mcp.oauth.prepareFlow", { ...params, sessionId }),
5025
+ /**
5026
+ * Cancels an exact host-driven OAuth flow on its original session requester.
5027
+ *
5028
+ * @param params Correlation identity reserved before an effectful authentication request.
5029
+ */
5030
+ cancelFlow: async (params) => connection.sendRequest("session.mcp.oauth.cancelFlow", { ...params, sessionId }),
5031
+ /**
5032
+ * Authenticates an arbitrary MCP URL through the original session credential owner, with correlated host progress and authorization callbacks.
5033
+ *
5034
+ * @param params Full host-driven authentication for an arbitrary, possibly unsaved, MCP URL.
5035
+ *
5036
+ * @returns Token projection for the existing host-delegated provider.
5037
+ */
5038
+ authenticate: async (params) => connection.sendRequest("session.mcp.oauth.authenticate", { ...params, sessionId }),
5039
+ /**
5040
+ * Checks whether the selected MCP credential owner has a valid access token.
5041
+ *
5042
+ * @param params A narrow token-validity query against the chosen credential owner.
5043
+ *
5044
+ * @returns Whether the credential operation succeeded.
5045
+ */
5046
+ hasValidTokens: async (params) => connection.sendRequest("session.mcp.oauth.hasValidTokens", { ...params, sessionId }),
5047
+ /**
5048
+ * Attempts silent MCP token refresh without opening a browser.
5049
+ *
5050
+ * @param params A narrow token-validity query against the chosen credential owner.
5051
+ *
5052
+ * @returns Whether the credential operation succeeded.
5053
+ */
5054
+ tryRefreshTokens: async (params) => connection.sendRequest("session.mcp.oauth.tryRefreshTokens", { ...params, sessionId }),
5055
+ /**
5056
+ * Stores a confidential MCP client's static secret in its selected credential owner.
5057
+ *
5058
+ * @param params Persist a confidential client's static secret without exposing token-store CRUD.
5059
+ */
5060
+ saveStaticClientSecret: async (params) => connection.sendRequest("session.mcp.oauth.saveStaticClientSecret", { ...params, sessionId }),
5061
+ /**
5062
+ * Releases an explicit host-owned MCP OAuth store on its original session requester.
5063
+ *
5064
+ * @param params Dispose an explicit host store without altering the session authorizer's owner.
5065
+ */
5066
+ disposeStore: async (params) => connection.sendRequest("session.mcp.oauth.disposeStore", { ...params, sessionId }),
5067
+ /**
5068
+ * Completes a tokenless initialize handshake for an unsaved remote MCP URL, preserving session egress and the refusing authentication challenge.
5069
+ *
5070
+ * @param params Tokenless initialize handshake for a possibly unsaved remote MCP server.
5071
+ *
5072
+ * @returns Outcome of the tokenless handshake, with the original challenge when available.
5073
+ */
5074
+ testConnection: async (params) => connection.sendRequest("session.mcp.oauth.testConnection", { ...params, sessionId }),
5075
+ /**
5076
+ * Derives an MCP credential key through the selected session account and store owner.
5077
+ *
5078
+ * @param params Derive a credential key through the selected account and store owner.
5079
+ *
5080
+ * @returns The selected owner's OAuth credential key.
5081
+ */
5082
+ storeKey: async (params) => connection.sendRequest("session.mcp.oauth.storeKey", { ...params, sessionId })
5083
+ }
4939
5084
  },
4940
5085
  /** @experimental */
4941
5086
  diagnostics: {
@@ -5290,10 +5435,15 @@ function registerClientGlobalApiHandlers(connection, handlers) {
5290
5435
  if (!handler) throw new Error("No extensionLaunchProvider client-global handler registered");
5291
5436
  return handler.resolve(params);
5292
5437
  });
5293
- connection.onRequest("kerberosAuth.acquire", async (params) => {
5294
- const handler = handlers.kerberosAuth;
5295
- if (!handler) throw new Error("No kerberosAuth client-global handler registered");
5296
- return handler.acquire(params);
5438
+ connection.onRequest("network.resolveProxy", async (params) => {
5439
+ const handler = handlers.network;
5440
+ if (!handler) throw new Error("No network client-global handler registered");
5441
+ return handler.resolveProxy(params);
5442
+ });
5443
+ connection.onRequest("network.authenticateNegotiate", async (params) => {
5444
+ const handler = handlers.network;
5445
+ if (!handler) throw new Error("No network client-global handler registered");
5446
+ return handler.authenticateNegotiate(params);
5297
5447
  });
5298
5448
  connection.onRequest("llmInference.httpRequestStart", async (params) => {
5299
5449
  const handler = handlers.llmInference;
package/dist/cjs/index.js CHANGED
@@ -23,6 +23,7 @@ __export(index_exports, {
23
23
  Canvas: () => import_canvas.Canvas,
24
24
  CanvasError: () => import_canvas.CanvasError,
25
25
  CopilotClient: () => import_client.CopilotClient,
26
+ CopilotDecisions: () => import_decisions.CopilotDecisions,
26
27
  CopilotRequestHandler: () => import_types2.CopilotRequestHandler,
27
28
  CopilotSession: () => import_session.CopilotSession,
28
29
  CopilotWebSocketCloseStatus: () => import_types2.CopilotWebSocketCloseStatus,
@@ -40,12 +41,15 @@ __export(index_exports, {
40
41
  createAttributedPermissionResult: () => import_types2.createAttributedPermissionResult,
41
42
  createCanvas: () => import_canvas.createCanvas,
42
43
  createSessionFsAdapter: () => import_types2.createSessionFsAdapter,
44
+ decisionErrorData: () => import_decisions.decisionErrorData,
45
+ decisionErrorKind: () => import_decisions.decisionErrorKind,
43
46
  defineTool: () => import_types2.defineTool,
44
47
  defineWorkflow: () => import_workflow.defineWorkflow,
45
48
  isWorkflowRunTerminal: () => import_workflow.isWorkflowRunTerminal
46
49
  });
47
50
  module.exports = __toCommonJS(index_exports);
48
51
  var import_client = require("./client.js");
52
+ var import_decisions = require("./decisions.js");
49
53
  var import_host = require("./host.js");
50
54
  var import_types = require("./types.js");
51
55
  var import_toolSet = require("./toolSet.js");
@@ -60,6 +64,7 @@ var import_types2 = require("./types.js");
60
64
  Canvas,
61
65
  CanvasError,
62
66
  CopilotClient,
67
+ CopilotDecisions,
63
68
  CopilotRequestHandler,
64
69
  CopilotSession,
65
70
  CopilotWebSocketCloseStatus,
@@ -77,6 +82,8 @@ var import_types2 = require("./types.js");
77
82
  createAttributedPermissionResult,
78
83
  createCanvas,
79
84
  createSessionFsAdapter,
85
+ decisionErrorData,
86
+ decisionErrorKind,
80
87
  defineTool,
81
88
  defineWorkflow,
82
89
  isWorkflowRunTerminal
@@ -283,8 +283,8 @@ class CopilotSession {
283
283
  * @param traceContextProvider - Optional callback to get W3C Trace Context for outbound RPCs
284
284
  * @internal This constructor is internal. Use {@link CopilotClient.createSession} to create sessions.
285
285
  */
286
- constructor(sessionId, connection, _workspacePath, traceContextProvider, options) {
287
- this.sessionId = sessionId;
286
+ constructor(_sessionId, connection, _workspacePath, traceContextProvider, options) {
287
+ this._sessionId = _sessionId;
288
288
  this.connection = connection;
289
289
  this._workspacePath = _workspacePath;
290
290
  this.traceContextProvider = traceContextProvider;
@@ -292,10 +292,11 @@ class CopilotSession {
292
292
  this.managedSettingsEnabled = options?.managedSettingsEnabled === true;
293
293
  this.onDisconnected = options?.onDisconnected;
294
294
  }
295
- sessionId;
295
+ _sessionId;
296
296
  connection;
297
297
  _workspacePath;
298
298
  _transcriptRecovery;
299
+ _permissionModeResult;
299
300
  eventHandlers = /* @__PURE__ */ new Set();
300
301
  typedEventHandlers = /* @__PURE__ */ new Map();
301
302
  toolHandlers = /* @__PURE__ */ new Map();
@@ -316,6 +317,7 @@ class CopilotSession {
316
317
  autoModeSwitchHandler;
317
318
  skillProvider;
318
319
  sessionCreationHandler;
320
+ memoryStoreHandler;
319
321
  hooks;
320
322
  transformCallbacks;
321
323
  _rpc = null;
@@ -330,6 +332,7 @@ class CopilotSession {
330
332
  completionRpcUnsupported = false;
331
333
  disconnecting = false;
332
334
  onDisconnected;
335
+ releaseFromClient;
333
336
  /** @internal Client session API handlers, populated by CopilotClient during create/resume. */
334
337
  clientSessionApis = {};
335
338
  /**
@@ -468,6 +471,15 @@ class CopilotSession {
468
471
  void read();
469
472
  });
470
473
  }
474
+ get sessionId() {
475
+ return this._sessionId;
476
+ }
477
+ /** @internal */
478
+ _setSessionId(sessionId) {
479
+ this._sessionId = sessionId;
480
+ this._rpc = null;
481
+ this._internalRpc = null;
482
+ }
471
483
  /**
472
484
  * Typed session-scoped RPC methods.
473
485
  */
@@ -500,6 +512,18 @@ class CopilotSession {
500
512
  setTranscriptRecovery(recovery) {
501
513
  this._transcriptRecovery = recovery;
502
514
  }
515
+ /**
516
+ * Outcome of the `permissionMode` requested when this session was created
517
+ * or resumed: whether it was applied, and the authoritative mode the
518
+ * session started in. Undefined when no mode was requested.
519
+ */
520
+ get permissionModeResult() {
521
+ return this._permissionModeResult;
522
+ }
523
+ /** @internal */
524
+ setPermissionModeResult(result) {
525
+ this._permissionModeResult = result;
526
+ }
503
527
  /**
504
528
  * Host capabilities reported when the session was created or resumed.
505
529
  * Use this to check feature support before calling capability-gated APIs.
@@ -548,6 +572,7 @@ class CopilotSession {
548
572
  prompt: options.prompt,
549
573
  source: options.source,
550
574
  displayPrompt: options.displayPrompt,
575
+ clientTurnId: options.clientTurnId,
551
576
  attachments: options.attachments,
552
577
  mode: options.mode,
553
578
  agentMode: options.agentMode,
@@ -891,6 +916,7 @@ class CopilotSession {
891
916
  return;
892
917
  }
893
918
  this.disconnected = true;
919
+ this.releaseFromClient = void 0;
894
920
  for (const fail of this.pendingResponseWaits) {
895
921
  fail(new Error("Session disconnected while waiting for a response"));
896
922
  }
@@ -907,6 +933,7 @@ class CopilotSession {
907
933
  controller.abort();
908
934
  }
909
935
  this.pendingSessionCreations.clear();
936
+ this._clearMemoryStore();
910
937
  this.eventHandlers.clear();
911
938
  this.typedEventHandlers.clear();
912
939
  this.toolHandlers.clear();
@@ -918,6 +945,7 @@ class CopilotSession {
918
945
  this.autoModeSwitchHandler = void 0;
919
946
  this.skillProvider = void 0;
920
947
  this.sessionCreationHandler = void 0;
948
+ this.memoryStoreHandler = void 0;
921
949
  this.hooks = void 0;
922
950
  this.traceContextProvider = void 0;
923
951
  this.bearerTokenProviders.clear();
@@ -948,6 +976,17 @@ class CopilotSession {
948
976
  this.assertConnected();
949
977
  this.onDisconnected = callback;
950
978
  }
979
+ /**
980
+ * @internal Lets the owning client stop tracking this session once `disconnect()`
981
+ * succeeds. Failed create/resume paths unregister the session themselves.
982
+ */
983
+ _setReleaseFromClient(callback) {
984
+ this.releaseFromClient = callback;
985
+ }
986
+ /** @internal */
987
+ _isDisconnected() {
988
+ return this.disconnected;
989
+ }
951
990
  on(eventTypeOrHandler, handler) {
952
991
  if (this.disconnected) {
953
992
  throw new Error("Session is disconnected");
@@ -1135,6 +1174,7 @@ class CopilotSession {
1135
1174
  return;
1136
1175
  }
1137
1176
  this.pendingExternalTools.set(requestId, controller);
1177
+ let claimed = false;
1138
1178
  try {
1139
1179
  let availableTools;
1140
1180
  if (toolName === TOOL_SEARCH_TOOL_NAME) {
@@ -1191,20 +1231,45 @@ class CopilotSession {
1191
1231
  if (!this._claimExternalTool(requestId, controller)) {
1192
1232
  return;
1193
1233
  }
1234
+ claimed = true;
1194
1235
  await this.rpc.tools.handlePendingToolCall({ requestId, result });
1195
1236
  } catch (error) {
1196
- if (!this._claimExternalTool(requestId, controller)) {
1237
+ if (claimed) {
1238
+ if (this.disconnected) {
1239
+ return;
1240
+ }
1241
+ console.error("External tool result delivery failed", {
1242
+ sessionId: this.sessionId,
1243
+ requestId,
1244
+ toolName,
1245
+ error
1246
+ });
1247
+ } else if (!this._claimExternalTool(requestId, controller)) {
1197
1248
  return;
1198
1249
  }
1199
1250
  let message = error instanceof Error ? error.message : String(error);
1200
1251
  if (!message) {
1201
1252
  message = error instanceof Error && error.name || "Error";
1202
1253
  }
1203
- try {
1204
- await this.rpc.tools.handlePendingToolCall({ requestId, error: message });
1205
- } catch (rpcError) {
1206
- if (!(rpcError instanceof import_node.ConnectionError || rpcError instanceof import_node.ResponseError)) {
1207
- throw rpcError;
1254
+ for (let attempt = 0; attempt < (claimed ? 1 : 2); attempt++) {
1255
+ try {
1256
+ await this.rpc.tools.handlePendingToolCall({ requestId, error: message });
1257
+ return;
1258
+ } catch (rpcError) {
1259
+ const retryable = !claimed && attempt === 0 && !this.disconnected;
1260
+ if (!retryable) {
1261
+ if (!(rpcError instanceof import_node.ConnectionError || rpcError instanceof import_node.ResponseError)) {
1262
+ throw rpcError;
1263
+ }
1264
+ return;
1265
+ }
1266
+ console.error("External tool error delivery failed", {
1267
+ sessionId: this.sessionId,
1268
+ requestId,
1269
+ toolName,
1270
+ error: rpcError
1271
+ });
1272
+ message = (rpcError instanceof Error ? rpcError.message || rpcError.name : "") || String(rpcError) || "Error";
1208
1273
  }
1209
1274
  }
1210
1275
  } finally {
@@ -1907,6 +1972,43 @@ class CopilotSession {
1907
1972
  throw error;
1908
1973
  }
1909
1974
  }
1975
+ /**
1976
+ * Registers the callback the runtime calls through `memoryStore.store`.
1977
+ * Registered before create or resume declares `hasMemoryStore`.
1978
+ * @internal
1979
+ */
1980
+ _registerMemoryStore(handler) {
1981
+ this.assertConnected();
1982
+ this.memoryStoreHandler = handler;
1983
+ }
1984
+ /** @internal */
1985
+ _clearMemoryStore() {
1986
+ this.memoryStoreHandler = void 0;
1987
+ }
1988
+ /** @internal */
1989
+ async _handleMemoryStore(memory, signal) {
1990
+ this.assertConnected();
1991
+ const handler = this.memoryStoreHandler;
1992
+ if (!handler) throw new Error("No memory store is registered");
1993
+ try {
1994
+ await handler(
1995
+ {
1996
+ sessionId: memory.sessionId,
1997
+ subject: memory.subject,
1998
+ fact: memory.fact,
1999
+ citations: memory.citations,
2000
+ reason: memory.reason
2001
+ },
2002
+ { signal }
2003
+ );
2004
+ } catch (error) {
2005
+ if (signal.aborted) {
2006
+ throw new import_node.ResponseError(-32800, "Memory store call cancelled");
2007
+ }
2008
+ console.warn("Memory store callback failed", error);
2009
+ throw new Error("Memory store callback failed");
2010
+ }
2011
+ }
1910
2012
  /** @internal */
1911
2013
  async _handleSessionManagementCreate(request, token) {
1912
2014
  this.assertConnected();
@@ -2153,7 +2255,9 @@ class CopilotSession {
2153
2255
  `Failed to disconnect session ${this.sessionId}: ${response.error || "Unknown error"}`
2154
2256
  );
2155
2257
  }
2258
+ const release = this.releaseFromClient;
2156
2259
  this._markDisconnected();
2260
+ release?.();
2157
2261
  } catch (error) {
2158
2262
  this.disconnecting = false;
2159
2263
  throw error;
@@ -1,2 +1,2 @@
1
- export declare const COPILOT_CLI_VERSION = "1.0.107";
1
+ export declare const COPILOT_CLI_VERSION = "1.0.108-1";
2
2
  export declare const COPILOT_CLI_USE_NPM_PACKAGE = false;