@agentclientprotocol/claude-agent-acp 0.85.2-preview.4 → 0.85.2-preview.5

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.
@@ -17,6 +17,8 @@ export declare const AIR_SKILL_KEY = "skill";
17
17
  export declare const AIR_CONTEXT_COMPACTION_KEY = "contextCompaction";
18
18
  export declare const AIR_GOAL_KEY = "goal";
19
19
  export declare const AIR_KIND_KEY = "kind";
20
+ /** The absolute path of the `SKILL.md` of a skill command in `available_commands_update`. */
21
+ export declare const AIR_SKILL_PATH_KEY = "skillPath";
20
22
  export declare const AIR_PERMISSION_KEY = "permission";
21
23
  export declare const AIR_CUSTOM_ANSWER_KEY = "customAnswer";
22
24
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"air-extension.d.ts","sourceRoot":"","sources":["../src/air-extension.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,uCAAuC,2BAA2B,CAAC;AAChF,eAAO,MAAM,0BAA0B,eAAe,CAAC;AACvD,eAAO,MAAM,8BAA8B,mBAAmB,CAAC;AAC/D,eAAO,MAAM,uCAAuC,qBAAqB,CAAC;AAC1E,eAAO,MAAM,yBAAyB,cAAc,CAAC;AACrD,4EAA4E;AAC5E,eAAO,MAAM,kCAAkC,sBAAsB,CAAC;AACtE;;;GAGG;AACH,eAAO,MAAM,wBAAwB,aAAa,CAAC;AAEnD,8EAA8E;AAC9E,eAAO,MAAM,qBAAqB,iBAAiB,CAAC;AACpD,eAAO,MAAM,gBAAgB,aAAa,CAAC;AAC3C,eAAO,MAAM,aAAa,UAAU,CAAC;AACrC,eAAO,MAAM,0BAA0B,sBAAsB,CAAC;AAC9D,eAAO,MAAM,YAAY,SAAS,CAAC;AACnC,eAAO,MAAM,YAAY,SAAS,CAAC;AACnC,eAAO,MAAM,kBAAkB,eAAe,CAAC;AAC/C,eAAO,MAAM,qBAAqB,iBAAiB,CAAC;AACpD;;;;GAIG;AACH,eAAO,MAAM,4BAA4B,iCAAiC,CAAC;AAQ3E,2EAA2E;AAC3E,wBAAgB,iBAAiB,CAAC,GAAG,YAAY,EAAE,MAAM,EAAE,2BAE1D;AAED;;;;;;GAMG;AACH,wBAAgB,WAAW,CACzB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,GAAG,SAAS,EAChD,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,OAAO,GACf,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAczB;AAED;;;;;;;GAOG;AACH,wBAAgB,WAAW,CAAC,YAAY,EAAE,OAAO,GAAG,OAAO,CAE1D;AAED;;;GAGG;AACH,wBAAgB,WAAW,CACzB,SAAS,EAAE,OAAO,EAClB,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,OAAO,EAChB,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,GACpC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,CAErC;AAED,2FAA2F;AAC3F,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,OAAO,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,CAKnF;AAED;;;;;GAKG;AACH,wBAAgB,2BAA2B,CAAC,YAAY,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAY9F"}
1
+ {"version":3,"file":"air-extension.d.ts","sourceRoot":"","sources":["../src/air-extension.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,uCAAuC,2BAA2B,CAAC;AAChF,eAAO,MAAM,0BAA0B,eAAe,CAAC;AACvD,eAAO,MAAM,8BAA8B,mBAAmB,CAAC;AAC/D,eAAO,MAAM,uCAAuC,qBAAqB,CAAC;AAC1E,eAAO,MAAM,yBAAyB,cAAc,CAAC;AACrD,4EAA4E;AAC5E,eAAO,MAAM,kCAAkC,sBAAsB,CAAC;AACtE;;;GAGG;AACH,eAAO,MAAM,wBAAwB,aAAa,CAAC;AAEnD,8EAA8E;AAC9E,eAAO,MAAM,qBAAqB,iBAAiB,CAAC;AACpD,eAAO,MAAM,gBAAgB,aAAa,CAAC;AAC3C,eAAO,MAAM,aAAa,UAAU,CAAC;AACrC,eAAO,MAAM,0BAA0B,sBAAsB,CAAC;AAC9D,eAAO,MAAM,YAAY,SAAS,CAAC;AACnC,eAAO,MAAM,YAAY,SAAS,CAAC;AACnC,6FAA6F;AAC7F,eAAO,MAAM,kBAAkB,cAAc,CAAC;AAC9C,eAAO,MAAM,kBAAkB,eAAe,CAAC;AAC/C,eAAO,MAAM,qBAAqB,iBAAiB,CAAC;AACpD;;;;GAIG;AACH,eAAO,MAAM,4BAA4B,iCAAiC,CAAC;AAQ3E,2EAA2E;AAC3E,wBAAgB,iBAAiB,CAAC,GAAG,YAAY,EAAE,MAAM,EAAE,2BAE1D;AAED;;;;;;GAMG;AACH,wBAAgB,WAAW,CACzB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,GAAG,SAAS,EAChD,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,OAAO,GACf,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAczB;AAED;;;;;;;GAOG;AACH,wBAAgB,WAAW,CAAC,YAAY,EAAE,OAAO,GAAG,OAAO,CAE1D;AAED;;;GAGG;AACH,wBAAgB,WAAW,CACzB,SAAS,EAAE,OAAO,EAClB,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,OAAO,EAChB,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,GACpC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,CAErC;AAED,2FAA2F;AAC3F,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,OAAO,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,CAKnF;AAED;;;;;GAKG;AACH,wBAAgB,2BAA2B,CAAC,YAAY,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAY9F"}
@@ -17,6 +17,8 @@ export const AIR_SKILL_KEY = "skill";
17
17
  export const AIR_CONTEXT_COMPACTION_KEY = "contextCompaction";
18
18
  export const AIR_GOAL_KEY = "goal";
19
19
  export const AIR_KIND_KEY = "kind";
20
+ /** The absolute path of the `SKILL.md` of a skill command in `available_commands_update`. */
21
+ export const AIR_SKILL_PATH_KEY = "skillPath";
20
22
  export const AIR_PERMISSION_KEY = "permission";
21
23
  export const AIR_CUSTOM_ANSWER_KEY = "customAnswer";
22
24
  /**
@@ -0,0 +1,51 @@
1
+ import type { AvailableCommand } from "@agentclientprotocol/sdk";
2
+ import type { McpServerStatus, Query } from "@anthropic-ai/claude-agent-sdk";
3
+ /** The `/mcp` entry of `available_commands_update`. The adapter shows the
4
+ * servers as a list, and runs a reconnect, an enable, or a disable through
5
+ * the SDK control API. */
6
+ export declare const MCP_AVAILABLE_COMMAND: AvailableCommand;
7
+ /** A `/mcp` prompt that gets a replacement for its Claude Code text. `all` is
8
+ * true for `all` and for a reconnect without a server name, as in Claude
9
+ * Code. `server` is undefined for an enable or a disable without a name. */
10
+ export type McpCommand = {
11
+ action: "status";
12
+ } | {
13
+ action: "reconnect" | "enable" | "disable";
14
+ all: boolean;
15
+ server?: string;
16
+ };
17
+ /** Parse a prompt that is exactly `/mcp`, or `/mcp reconnect`, `/mcp enable`,
18
+ * or `/mcp disable` with an optional server name or `all`. Any other `/mcp`
19
+ * argument gives null, and the prompt gets no replacement. */
20
+ export declare function parseMcpCommand(text: string): McpCommand | null;
21
+ /** Read the MCP server status for the list after a `/mcp` command. Resolves
22
+ * to null when the read fails, takes too long, or `signal` aborts. Then the
23
+ * turn keeps the text of Claude Code. */
24
+ export declare function readMcpServerStatus(query: Pick<Query, "mcpServerStatus">, signal: AbortSignal, logError: (message: string) => void): Promise<McpServerStatus[] | null>;
25
+ /** Make an MCP error short and readable for one list item. The result has
26
+ * no leading wrapper segments, at most two sentences, and at most
27
+ * `MAX_ERROR_LENGTH` code points. A wrapper before an error code stays, so
28
+ * an error code is never alone. The result is empty for an error with only
29
+ * whitespace. */
30
+ export declare function cleanMcpError(error: string): string;
31
+ /** Markdown for `/mcp`: a summary line, one group of servers for each
32
+ * status, and the disabled servers on one line. A list reads better than a
33
+ * table in a narrow chat. */
34
+ export declare function formatMcpStatus(statuses: McpServerStatus[]): string;
35
+ /** The SDK query methods that `/mcp` uses. */
36
+ export type McpControlQuery = Pick<Query, "mcpServerStatus" | "reconnectMcpServer" | "toggleMcpServer">;
37
+ /** The result of {@link runMcpCommand}. `markdown` is null when the turn
38
+ * keeps the text of Claude Code. `reconnected` holds the servers that the
39
+ * adapter tried to reconnect. */
40
+ export type McpCommandOutcome = {
41
+ markdown: string | null;
42
+ reconnected: string[];
43
+ };
44
+ /** Run a `/mcp` command after Claude Code sent `originalOutput`, its text for
45
+ * the command. Claude Code refuses a reconnect, an enable, and a disable in
46
+ * SDK mode, so the adapter runs them through the SDK control API. The result
47
+ * of each server goes above the server list. An error of one server does
48
+ * not stop the others. When the first status read fails or `signal`
49
+ * aborts, the turn keeps the text of Claude Code. */
50
+ export declare function runMcpCommand(query: McpControlQuery, command: McpCommand, originalOutput: string, signal: AbortSignal, logError: (message: string) => void): Promise<McpCommandOutcome>;
51
+ //# sourceMappingURL=mcp-command.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcp-command.d.ts","sourceRoot":"","sources":["../src/mcp-command.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AACjE,OAAO,KAAK,EAAE,eAAe,EAAE,KAAK,EAAE,MAAM,gCAAgC,CAAC;AAI7E;;2BAE2B;AAC3B,eAAO,MAAM,qBAAqB,EAAE,gBAInC,CAAC;AAQF;;6EAE6E;AAC7E,MAAM,MAAM,UAAU,GAClB;IAAE,MAAM,EAAE,QAAQ,CAAA;CAAE,GACpB;IAAE,MAAM,EAAE,WAAW,GAAG,QAAQ,GAAG,SAAS,CAAC;IAAC,GAAG,EAAE,OAAO,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAElF;;+DAE+D;AAC/D,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,UAAU,GAAG,IAAI,CAW/D;AAED;;0CAE0C;AAC1C,wBAAsB,mBAAmB,CACvC,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,iBAAiB,CAAC,EACrC,MAAM,EAAE,WAAW,EACnB,QAAQ,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,GAClC,OAAO,CAAC,eAAe,EAAE,GAAG,IAAI,CAAC,CAkBnC;AAuED;;;;kBAIkB;AAClB,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAiBnD;AA2DD;;8BAE8B;AAC9B,wBAAgB,eAAe,CAAC,QAAQ,EAAE,eAAe,EAAE,GAAG,MAAM,CA6BnE;AAED,8CAA8C;AAC9C,MAAM,MAAM,eAAe,GAAG,IAAI,CAChC,KAAK,EACL,iBAAiB,GAAG,oBAAoB,GAAG,iBAAiB,CAC7D,CAAC;AAEF;;kCAEkC;AAClC,MAAM,MAAM,iBAAiB,GAAG;IAAE,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,WAAW,EAAE,MAAM,EAAE,CAAA;CAAE,CAAC;AA4DnF;;;;;sDAKsD;AACtD,wBAAsB,aAAa,CACjC,KAAK,EAAE,eAAe,EACtB,OAAO,EAAE,UAAU,EACnB,cAAc,EAAE,MAAM,EACtB,MAAM,EAAE,WAAW,EACnB,QAAQ,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,GAClC,OAAO,CAAC,iBAAiB,CAAC,CAoD5B"}
@@ -0,0 +1,321 @@
1
+ import { escapeMarkdown } from "./usage-markdown.js";
2
+ import { raceTimeoutAndAbort } from "./utils.js";
3
+ /** The `/mcp` entry of `available_commands_update`. The adapter shows the
4
+ * servers as a list, and runs a reconnect, an enable, or a disable through
5
+ * the SDK control API. */
6
+ export const MCP_AVAILABLE_COMMAND = {
7
+ name: "mcp",
8
+ description: "Show the MCP servers and their status, or reconnect, enable, or disable a server",
9
+ input: { hint: "[reconnect|enable|disable [<server>|all]]" },
10
+ };
11
+ /** The time that the status read after a `/mcp` command can take. */
12
+ const MCP_STATUS_TIMEOUT_MS = 5_000;
13
+ /** The time that one reconnect, enable, or disable can take. */
14
+ const MCP_ACTION_TIMEOUT_MS = 30_000;
15
+ /** Parse a prompt that is exactly `/mcp`, or `/mcp reconnect`, `/mcp enable`,
16
+ * or `/mcp disable` with an optional server name or `all`. Any other `/mcp`
17
+ * argument gives null, and the prompt gets no replacement. */
18
+ export function parseMcpCommand(text) {
19
+ const words = text.trim().split(/\s+/);
20
+ if (words[0] !== "/mcp")
21
+ return null;
22
+ if (words.length === 1)
23
+ return { action: "status" };
24
+ const action = words[1]?.toLowerCase();
25
+ if (action !== "reconnect" && action !== "enable" && action !== "disable")
26
+ return null;
27
+ const server = words.slice(2).join(" ");
28
+ if (server === "all" || (server === "" && action === "reconnect")) {
29
+ return { action, all: true };
30
+ }
31
+ return server === "" ? { action, all: false } : { action, all: false, server };
32
+ }
33
+ /** Read the MCP server status for the list after a `/mcp` command. Resolves
34
+ * to null when the read fails, takes too long, or `signal` aborts. Then the
35
+ * turn keeps the text of Claude Code. */
36
+ export async function readMcpServerStatus(query, signal, logError) {
37
+ if (signal.aborted)
38
+ return null;
39
+ try {
40
+ const outcome = await raceTimeoutAndAbort(query.mcpServerStatus(), MCP_STATUS_TIMEOUT_MS, signal);
41
+ if (outcome.type === "timeout") {
42
+ logError("The MCP server status read timed out; keeping the Claude Code text of /mcp");
43
+ }
44
+ return outcome.type === "done" ? outcome.value : null;
45
+ }
46
+ catch (error) {
47
+ if (!signal.aborted) {
48
+ logError(`The MCP server status read failed; keeping the Claude Code text of /mcp: ${error}`);
49
+ }
50
+ return null;
51
+ }
52
+ }
53
+ /** The known statuses in the order of the groups and of the summary counts.
54
+ * A disabled server is not a group. It is on one line at the end. */
55
+ const GROUP_ORDER = ["failed", "needs-auth", "pending", "connected"];
56
+ const GROUP_TITLES = {
57
+ failed: "Failed",
58
+ "needs-auth": "Needs authentication",
59
+ pending: "Connecting",
60
+ connected: "Connected",
61
+ };
62
+ const SUMMARY_LABELS = {
63
+ connected: "connected",
64
+ failed: "failed",
65
+ "needs-auth": "need authentication",
66
+ pending: "connecting",
67
+ disabled: "disabled",
68
+ };
69
+ const KNOWN_STATUSES = [...GROUP_ORDER, "disabled"];
70
+ const MAX_ERROR_LENGTH = 160;
71
+ /** The longest segment that can be a wrapper. A longer segment is content. */
72
+ const MAX_WRAPPER_LENGTH = 60;
73
+ /** True for a server that a `/mcp reconnect` without a name must retry. */
74
+ function needsReconnect(status) {
75
+ return (status.status === "failed" || status.status === "pending" || status.status === "needs-auth");
76
+ }
77
+ /** The text as a Markdown code span. The fence is longer than the longest
78
+ * backtick run in the text, so the span shows the text unchanged. The user
79
+ * can copy a server name from it into `/mcp reconnect`. */
80
+ function codeSpan(text) {
81
+ const longestRun = Math.max(0, ...(text.match(/`+/g) ?? []).map((run) => run.length));
82
+ const fence = "`".repeat(longestRun + 1);
83
+ // CommonMark strips one space from each end of a span, so a pad keeps the text unchanged.
84
+ const pad = text.startsWith("`") || text.endsWith("`") || /^ .*[^ ].* $/.test(text) ? " " : "";
85
+ return `${fence}${pad}${text}${pad}${fence}`;
86
+ }
87
+ function isErrorCode(segment) {
88
+ return /^-?\d+$/.test(segment);
89
+ }
90
+ /** True for a segment that only wraps the real error, such as
91
+ * `MCP startup failed`, `McpError`, `MCP error -32001`, an error code, or a
92
+ * Rust or TypeScript type path. */
93
+ function isWrapperSegment(segment) {
94
+ return (isErrorCode(segment) ||
95
+ segment.includes("::") ||
96
+ (segment.length <= MAX_WRAPPER_LENGTH &&
97
+ !/[.!?]/.test(segment) &&
98
+ /(failed|error|exception)(\s+-?\d+)?$/i.test(segment)));
99
+ }
100
+ /** Cut the text to `MAX_ERROR_LENGTH` code points, so a surrogate pair stays whole. */
101
+ function truncate(text) {
102
+ const chars = Array.from(text);
103
+ if (chars.length <= MAX_ERROR_LENGTH)
104
+ return text;
105
+ const cut = chars.slice(0, MAX_ERROR_LENGTH - 1).join("");
106
+ return `${cut.trimEnd()}…`;
107
+ }
108
+ /** Make an MCP error short and readable for one list item. The result has
109
+ * no leading wrapper segments, at most two sentences, and at most
110
+ * `MAX_ERROR_LENGTH` code points. A wrapper before an error code stays, so
111
+ * an error code is never alone. The result is empty for an error with only
112
+ * whitespace. */
113
+ export function cleanMcpError(error) {
114
+ const segments = error.replace(/\s+/g, " ").trim().split(": ");
115
+ let start = 0;
116
+ while (start < segments.length - 1 &&
117
+ isWrapperSegment(segments[start]) &&
118
+ !segments.slice(start + 1).every(isErrorCode)) {
119
+ start++;
120
+ }
121
+ const content = segments.slice(start).join(": ");
122
+ return truncate(content
123
+ .split(/(?<=[.!?]) /)
124
+ .slice(0, 2)
125
+ .join(" "));
126
+ }
127
+ function toolCount(status) {
128
+ if (!status.tools)
129
+ return undefined;
130
+ return status.tools.length === 1 ? "1 tool" : `${status.tools.length} tools`;
131
+ }
132
+ /** The server name as inline code. Claude Code keys the servers by name, so
133
+ * two servers have the same name only from different scopes. Then the
134
+ * scope tells them apart. */
135
+ function serverName(status, duplicates) {
136
+ const origin = status.scope ?? status.source;
137
+ return duplicates.has(status.name) && origin
138
+ ? `${codeSpan(status.name)} (${escapeMarkdown(origin)})`
139
+ : codeSpan(status.name);
140
+ }
141
+ function serverItem(status, duplicates) {
142
+ const error = status.error ? cleanMcpError(status.error) : "";
143
+ const details = [error === "" ? undefined : escapeMarkdown(error), toolCount(status)]
144
+ .filter((detail) => detail !== undefined)
145
+ .join("; ");
146
+ const name = serverName(status, duplicates);
147
+ return details === "" ? `- ${name}` : `- ${name}: ${details}`;
148
+ }
149
+ function summaryLine(statuses) {
150
+ // The counts follow the group order. An unknown status also counts, so the counts add up to the total.
151
+ const counts = [...GROUP_ORDER, ...unknownStatuses(statuses), "disabled"]
152
+ .map((state) => ({
153
+ state,
154
+ count: statuses.filter((status) => status.status === state).length,
155
+ }))
156
+ .filter(({ count }) => count > 0);
157
+ const parts = counts.map(({ state, count }) => count === 1 && state === "needs-auth"
158
+ ? "1 needs authentication"
159
+ : `${count} ${SUMMARY_LABELS[state] ?? escapeMarkdown(state)}`);
160
+ return `**MCP servers:** ${statuses.length} (${parts.join(", ")})`;
161
+ }
162
+ /** The statuses that this adapter does not know, in the SDK order. The SDK
163
+ * can report a new status before the adapter knows it. */
164
+ function unknownStatuses(statuses) {
165
+ return [
166
+ ...new Set(statuses
167
+ .map((status) => status.status)
168
+ .filter((state) => !KNOWN_STATUSES.includes(state))),
169
+ ];
170
+ }
171
+ /** The group title of a status that the adapter does not know. It starts with a capital letter, as a known title does. */
172
+ function unknownTitle(state) {
173
+ return escapeMarkdown(state.charAt(0).toUpperCase() + state.slice(1));
174
+ }
175
+ /** Markdown for `/mcp`: a summary line, one group of servers for each
176
+ * status, and the disabled servers on one line. A list reads better than a
177
+ * table in a narrow chat. */
178
+ export function formatMcpStatus(statuses) {
179
+ if (statuses.length === 0)
180
+ return "No MCP servers are configured.";
181
+ const blocks = [];
182
+ const names = statuses.map((status) => status.name);
183
+ const duplicates = new Set(names.filter((name, index) => names.indexOf(name) !== index));
184
+ blocks.push(summaryLine(statuses));
185
+ const groups = [
186
+ ...GROUP_ORDER.map((state) => [state, GROUP_TITLES[state]]),
187
+ ...unknownStatuses(statuses).map((state) => [state, unknownTitle(state)]),
188
+ ];
189
+ for (const [state, title] of groups) {
190
+ const members = statuses.filter((status) => status.status === state);
191
+ if (members.length === 0)
192
+ continue;
193
+ blocks.push([`**${title}**`, ...members.map((status) => serverItem(status, duplicates))].join("\n"));
194
+ }
195
+ const disabled = statuses.filter((status) => status.status === "disabled");
196
+ if (disabled.length > 0) {
197
+ blocks.push(`**Disabled:** ${disabled.map((status) => serverName(status, duplicates)).join(", ")}`);
198
+ }
199
+ if (statuses.some(needsReconnect)) {
200
+ blocks.push("Run `/mcp reconnect <server>` to reconnect one server, or `/mcp reconnect` to reconnect every server that is not connected and not disabled.");
201
+ }
202
+ return blocks.join("\n\n");
203
+ }
204
+ /** Wait for one control call. The wait stops when `signal` aborts or the
205
+ * call takes more than {@link MCP_ACTION_TIMEOUT_MS}. */
206
+ async function awaitCall(call, signal) {
207
+ if (signal.aborted)
208
+ return { type: "aborted" };
209
+ try {
210
+ const outcome = await raceTimeoutAndAbort(call(), MCP_ACTION_TIMEOUT_MS, signal);
211
+ if (outcome.type === "timeout")
212
+ return { type: "failed", error: "The request timed out." };
213
+ return outcome.type === "done" ? { type: "done" } : outcome;
214
+ }
215
+ catch (error) {
216
+ return signal.aborted
217
+ ? { type: "aborted" }
218
+ : { type: "failed", error: error instanceof Error ? error.message : String(error) };
219
+ }
220
+ }
221
+ const ACTION_DONE = { reconnect: "Reconnected", enable: "Enabled", disable: "Disabled" };
222
+ /** The Claude Code sentence that refuses an action in SDK mode. */
223
+ const UNAVAILABLE_SENTENCE = /aren't available in this session/i;
224
+ /** A Claude Code sentence that points to a terminal, which an ACP client
225
+ * does not have. */
226
+ function isTerminalSentence(sentence) {
227
+ return /in the terminal/i.test(sentence) || sentence.includes("`/mcp reconnect all` here");
228
+ }
229
+ function sentences(text) {
230
+ return text
231
+ .trim()
232
+ .split(/(?<=[.!?])\s+/)
233
+ .filter((sentence) => sentence !== "");
234
+ }
235
+ /** The servers that the action changes. A named server is always a target,
236
+ * so the control API reports its own error. */
237
+ function actionTargets(command, statuses) {
238
+ if (!command.all)
239
+ return command.server === undefined ? [] : [command.server];
240
+ const names = statuses
241
+ .filter((status) => {
242
+ if (command.action === "reconnect")
243
+ return needsReconnect(status);
244
+ if (command.action === "enable")
245
+ return status.status === "disabled";
246
+ return status.status !== "disabled";
247
+ })
248
+ .map((status) => status.name);
249
+ return [...new Set(names)];
250
+ }
251
+ function nothingToDoLine(action) {
252
+ if (action === "enable")
253
+ return "Every MCP server is already enabled.";
254
+ if (action === "disable")
255
+ return "Every MCP server is already disabled.";
256
+ return "Every MCP server is connected or disabled. There is nothing to reconnect.";
257
+ }
258
+ /** Run a `/mcp` command after Claude Code sent `originalOutput`, its text for
259
+ * the command. Claude Code refuses a reconnect, an enable, and a disable in
260
+ * SDK mode, so the adapter runs them through the SDK control API. The result
261
+ * of each server goes above the server list. An error of one server does
262
+ * not stop the others. When the first status read fails or `signal`
263
+ * aborts, the turn keeps the text of Claude Code. */
264
+ export async function runMcpCommand(query, command, originalOutput, signal, logError) {
265
+ const reconnected = [];
266
+ const keep = { markdown: null, reconnected };
267
+ if (command.action === "status") {
268
+ // The list replaces the Claude Code summary line.
269
+ const statuses = await readMcpServerStatus(query, signal, logError);
270
+ return { markdown: statuses ? formatMcpStatus(statuses) : null, reconnected };
271
+ }
272
+ const before = await readMcpServerStatus(query, signal, logError);
273
+ if (!before)
274
+ return keep;
275
+ const cliSentences = sentences(originalOutput).filter((sentence) => !isTerminalSentence(sentence));
276
+ const cliNamesUnknown = cliSentences.some((sentence) => /no MCP server named/i.test(sentence));
277
+ const results = [];
278
+ if (!command.all && command.server === undefined) {
279
+ results.push(`Name a server or \`all\`, for example \`/mcp ${command.action} <server>\`.`);
280
+ }
281
+ const known = new Set(before.map((status) => status.name));
282
+ const targets = actionTargets(command, before);
283
+ if (command.all && targets.length === 0)
284
+ results.push(nothingToDoLine(command.action));
285
+ for (const server of targets) {
286
+ if (!known.has(server)) {
287
+ // Claude Code checks the name first. Its sentence then stays.
288
+ if (!cliNamesUnknown)
289
+ results.push(`There's no MCP server named ${codeSpan(server)}.`);
290
+ continue;
291
+ }
292
+ if (command.action === "reconnect")
293
+ reconnected.push(server);
294
+ const call = command.action === "reconnect"
295
+ ? () => query.reconnectMcpServer(server)
296
+ : () => query.toggleMcpServer(server, command.action === "enable");
297
+ const result = await awaitCall(call, signal);
298
+ if (result.type === "aborted")
299
+ return keep;
300
+ if (result.type === "done") {
301
+ results.push(`- ${ACTION_DONE[command.action]} ${codeSpan(server)}`);
302
+ }
303
+ else {
304
+ const error = cleanMcpError(result.error);
305
+ const failure = `- Couldn't ${command.action} ${codeSpan(server)}`;
306
+ results.push(error === "" ? failure : `${failure}: ${escapeMarkdown(error)}`);
307
+ }
308
+ }
309
+ const blocks = [];
310
+ const kept = cliSentences.filter((sentence) => !UNAVAILABLE_SENTENCE.test(sentence));
311
+ if (kept.length > 0)
312
+ blocks.push(kept.join(" "));
313
+ if (results.length > 0)
314
+ blocks.push(results.join("\n"));
315
+ const after = await readMcpServerStatus(query, signal, logError);
316
+ if (signal.aborted)
317
+ return keep;
318
+ if (after)
319
+ blocks.push(formatMcpStatus(after));
320
+ return { markdown: blocks.join("\n\n"), reconnected };
321
+ }
@@ -15,15 +15,25 @@ export declare function resumedModelFromTranscript(messages: SessionMessage[]):
15
15
  /** Read the resume model from the local transcript without starting a Claude
16
16
  * control request. This is intentionally on the load critical path. */
17
17
  export declare function readResumedSession(sessionId: string, logger?: ResumeLogger): Promise<ResumedSessionSnapshot>;
18
+ /** What a resume restores from the end of the local transcript. */
19
+ export type ResumedTail = {
20
+ model?: string;
21
+ /** The last permission mode of the main thread. See {@link TailScan}. */
22
+ permissionMode?: string;
23
+ };
18
24
  /**
19
- * Read the resume model of a session from the end of its local transcript.
25
+ * Read the resume model and the permission mode of a session from the end
26
+ * of its local transcript.
27
+ *
28
+ * A resume needs only these two values, not the messages. The transcript file
29
+ * is read backwards until both are known, so the cost does not grow with the
30
+ * length of the session. A session without a local transcript file falls back
31
+ * to {@link readResumedSession} for the model.
20
32
  *
21
- * A resume needs only the model, not the messages. The transcript file is
22
- * read backwards until the last real assistant record of the main thread, so
23
- * the cost does not grow with the length of the session. A session without a
24
- * local transcript file falls back to {@link readResumedSession}.
33
+ * A caller that already has the model passes `withModel: false`. The read then
34
+ * looks for the permission mode only and has no fallback.
25
35
  */
26
- export declare function readResumedModel(sessionId: string, logger?: ResumeLogger): Promise<string | undefined>;
36
+ export declare function readResumedTail(sessionId: string, logger?: ResumeLogger, withModel?: boolean): Promise<ResumedTail>;
27
37
  /** The local transcript of a session in any project directory, as the SDK looks it up. */
28
38
  export declare function findTranscript(sessionId: string): Promise<string | undefined>;
29
39
  export {};
@@ -1 +1 @@
1
- {"version":3,"file":"resumed-session.d.ts","sourceRoot":"","sources":["../src/resumed-session.ts"],"names":[],"mappings":"AAAA,OAAO,EAAsB,KAAK,cAAc,EAAE,MAAM,gCAAgC,CAAC;AASzF,KAAK,YAAY,GAAG;IAClB,GAAG,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,CAAC;IAClC,KAAK,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,CAAC;CACrC,CAAC;AAEF,MAAM,MAAM,sBAAsB,GAAG;IACnC,QAAQ,CAAC,EAAE,cAAc,EAAE,CAAC;IAC5B,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF;;;iDAGiD;AACjD,wBAAgB,0BAA0B,CAAC,QAAQ,EAAE,cAAc,EAAE,GAAG,MAAM,GAAG,SAAS,CAgBzF;AASD;uEACuE;AACvE,wBAAsB,kBAAkB,CACtC,SAAS,EAAE,MAAM,EACjB,MAAM,CAAC,EAAE,YAAY,GACpB,OAAO,CAAC,sBAAsB,CAAC,CAejC;AAED;;;;;;;GAOG;AACH,wBAAsB,gBAAgB,CACpC,SAAS,EAAE,MAAM,EACjB,MAAM,CAAC,EAAE,YAAY,GACpB,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAc7B;AAED,0FAA0F;AAC1F,wBAAsB,cAAc,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAkBnF"}
1
+ {"version":3,"file":"resumed-session.d.ts","sourceRoot":"","sources":["../src/resumed-session.ts"],"names":[],"mappings":"AAAA,OAAO,EAAsB,KAAK,cAAc,EAAE,MAAM,gCAAgC,CAAC;AASzF,KAAK,YAAY,GAAG;IAClB,GAAG,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,CAAC;IAClC,KAAK,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,CAAC;CACrC,CAAC;AAEF,MAAM,MAAM,sBAAsB,GAAG;IACnC,QAAQ,CAAC,EAAE,cAAc,EAAE,CAAC;IAC5B,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF;;;iDAGiD;AACjD,wBAAgB,0BAA0B,CAAC,QAAQ,EAAE,cAAc,EAAE,GAAG,MAAM,GAAG,SAAS,CAgBzF;AASD;uEACuE;AACvE,wBAAsB,kBAAkB,CACtC,SAAS,EAAE,MAAM,EACjB,MAAM,CAAC,EAAE,YAAY,GACpB,OAAO,CAAC,sBAAsB,CAAC,CAejC;AAED,mEAAmE;AACnE,MAAM,MAAM,WAAW,GAAG;IACxB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,yEAAyE;IACzE,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB,CAAC;AAEF;;;;;;;;;;;GAWG;AACH,wBAAsB,eAAe,CACnC,SAAS,EAAE,MAAM,EACjB,MAAM,CAAC,EAAE,YAAY,EACrB,SAAS,UAAO,GACf,OAAO,CAAC,WAAW,CAAC,CAiBtB;AAED,0FAA0F;AAC1F,wBAAsB,cAAc,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAkBnF"}
@@ -52,28 +52,32 @@ export async function readResumedSession(sessionId, logger) {
52
52
  }
53
53
  }
54
54
  /**
55
- * Read the resume model of a session from the end of its local transcript.
55
+ * Read the resume model and the permission mode of a session from the end
56
+ * of its local transcript.
56
57
  *
57
- * A resume needs only the model, not the messages. The transcript file is
58
- * read backwards until the last real assistant record of the main thread, so
59
- * the cost does not grow with the length of the session. A session without a
60
- * local transcript file falls back to {@link readResumedSession}.
58
+ * A resume needs only these two values, not the messages. The transcript file
59
+ * is read backwards until both are known, so the cost does not grow with the
60
+ * length of the session. A session without a local transcript file falls back
61
+ * to {@link readResumedSession} for the model.
62
+ *
63
+ * A caller that already has the model passes `withModel: false`. The read then
64
+ * looks for the permission mode only and has no fallback.
61
65
  */
62
- export async function readResumedModel(sessionId, logger) {
66
+ export async function readResumedTail(sessionId, logger, withModel = true) {
63
67
  const timing = new SessionTiming(logger, "models", sessionId);
64
68
  try {
65
69
  const filePath = await findTranscript(sessionId);
66
70
  if (filePath) {
67
- const model = await lastAssistantModel(filePath);
68
- timing.phase("read-transcript-tail", ` model=${model ?? "unknown"}`);
69
- return model;
71
+ const tail = await lastTailRecords(filePath, withModel);
72
+ timing.phase("read-transcript-tail", ` model=${tail.model ?? "unknown"} permissionMode=${tail.permissionMode ?? "unknown"}`);
73
+ return tail;
70
74
  }
71
75
  }
72
76
  catch (error) {
73
77
  timing.phase("read-transcript-tail", " outcome=error");
74
78
  logger?.error(`Failed to read the transcript tail of resumed session ${sessionId}:`, error);
75
79
  }
76
- return (await readResumedSession(sessionId, logger)).model;
80
+ return withModel ? { model: (await readResumedSession(sessionId, logger)).model } : {};
77
81
  }
78
82
  /** The local transcript of a session in any project directory, as the SDK looks it up. */
79
83
  export async function findTranscript(sessionId) {
@@ -97,9 +101,11 @@ export async function findTranscript(sessionId) {
97
101
  }
98
102
  return undefined;
99
103
  }
100
- /** The model of the last real assistant record of the main thread in a JSONL transcript. */
101
- async function lastAssistantModel(filePath) {
104
+ /** The model of the last real assistant record and the last permission mode
105
+ * of the main thread in a JSONL transcript. */
106
+ async function lastTailRecords(filePath, withModel) {
102
107
  const handle = await open(filePath, "r");
108
+ const scan = new TailScan(withModel);
103
109
  try {
104
110
  let end = (await handle.stat()).size;
105
111
  // The bytes of the line whose start is not read yet, in file order.
@@ -109,36 +115,96 @@ async function lastAssistantModel(filePath) {
109
115
  let chunk = Buffer.alloc(end - start);
110
116
  await handle.read(chunk, 0, chunk.length, start);
111
117
  for (let at = chunk.lastIndexOf(0x0a); at >= 0; at = chunk.lastIndexOf(0x0a)) {
112
- const model = assistantModelOfLine(Buffer.concat([chunk.subarray(at + 1), ...pending]));
113
- if (model)
114
- return model;
118
+ if (scan.visit(Buffer.concat([chunk.subarray(at + 1), ...pending])))
119
+ return scan.tail;
115
120
  pending = [];
116
121
  chunk = chunk.subarray(0, at);
117
122
  }
118
123
  pending.unshift(chunk);
119
124
  end = start;
120
125
  }
121
- return assistantModelOfLine(Buffer.concat(pending));
126
+ scan.visit(Buffer.concat(pending));
127
+ return scan.tail;
122
128
  }
123
129
  finally {
124
130
  await handle.close();
125
131
  }
126
132
  }
127
- function assistantModelOfLine(line) {
128
- // Most lines are not assistant records. The check skips their JSON parse.
129
- if (line.indexOf('"assistant"') < 0)
130
- return undefined;
133
+ /**
134
+ * Reads the lines of a transcript from the end and keeps what a resume needs.
135
+ *
136
+ * Claude Code records the permission mode on each prompt record of type `user`.
137
+ * The `permission-mode` records of the CLI metadata block are not used: they
138
+ * can disagree with the prompts, and the SDK does not write them.
139
+ * The SDK writes no record when it leaves plan mode through ExitPlanMode.
140
+ * It writes a `plan_mode_exit` attachment only, without the new mode. Thus a
141
+ * `plan` mode before a later plan exit is not the current mode, and the scan
142
+ * gives no mode.
143
+ *
144
+ * The mode search stops at the first mode record or at the last human prompt.
145
+ * Each human prompt of a current Claude Code has the mode, so a prompt without
146
+ * it means that the transcript does not record modes. A compaction does not
147
+ * stop the search: the mode of the prompt before it is still current.
148
+ */
149
+ class TailScan {
150
+ withModel;
151
+ tail = {};
152
+ modeDone = false;
153
+ planExited = false;
154
+ constructor(withModel) {
155
+ this.withModel = withModel;
156
+ }
157
+ /** Visit the previous line. Return true when the scan has all it needs. */
158
+ visit(line) {
159
+ let parsed;
160
+ // Most lines have no marker of interest. The check skips their JSON parse.
161
+ const record = (marker) => {
162
+ if (line.indexOf(marker) < 0)
163
+ return undefined;
164
+ if (parsed === undefined)
165
+ parsed = parseMainThreadRecord(line);
166
+ return parsed ?? undefined;
167
+ };
168
+ if (this.withModel && this.tail.model === undefined) {
169
+ const entry = record('"assistant"');
170
+ if (entry?.type === "assistant")
171
+ this.tail.model = concreteModel(entry.message?.model);
172
+ }
173
+ if (!this.modeDone)
174
+ this.visitForMode(record);
175
+ return (!this.withModel || this.tail.model !== undefined) && this.modeDone;
176
+ }
177
+ visitForMode(record) {
178
+ const modeEntry = record('"permissionMode"');
179
+ if (modeEntry?.type === "user" &&
180
+ typeof modeEntry.permissionMode === "string" &&
181
+ modeEntry.permissionMode.trim() !== "") {
182
+ const mode = modeEntry.permissionMode.trim();
183
+ this.modeDone = true;
184
+ if (!(this.planExited && mode === "plan"))
185
+ this.tail.permissionMode = mode;
186
+ return;
187
+ }
188
+ if (record('"plan_mode_exit"')?.attachment?.type === "plan_mode_exit") {
189
+ this.planExited = true;
190
+ return;
191
+ }
192
+ const human = record('"human"');
193
+ if (human?.type === "user" && human.origin?.kind === "human")
194
+ this.modeDone = true;
195
+ }
196
+ }
197
+ /** The parsed record of one line, or null for a subagent record or a bad line. */
198
+ function parseMainThreadRecord(line) {
131
199
  let entry;
132
200
  try {
133
201
  entry = JSON.parse(line.toString("utf8"));
134
202
  }
135
203
  catch {
136
- return undefined;
204
+ return null;
137
205
  }
138
206
  if (!entry || typeof entry !== "object")
139
- return undefined;
207
+ return null;
140
208
  const record = entry;
141
- if (record.type !== "assistant" || record.isSidechain === true)
142
- return undefined;
143
- return concreteModel(record.message?.model);
209
+ return record.isSidechain === true ? null : record;
144
210
  }
@@ -41,6 +41,20 @@ type InitializeSessionModeParams = {
41
41
  /** When false, bypassPermissions is omitted from the mode catalog. */
42
42
  allowBypass: boolean;
43
43
  };
44
+ /**
45
+ * The permission mode a new Claude query starts in.
46
+ *
47
+ * An explicit mode wins. A resume or a load continues in the mode of the last
48
+ * user record of the transcript. If that mode is unknown or not available now,
49
+ * for example bypass, the session starts in `defaultMode` of the settings.
50
+ */
51
+ export declare function resolveInitialPermissionMode(sources: {
52
+ explicit?: PermissionMode;
53
+ resumed?: string;
54
+ defaultMode?: unknown;
55
+ }, logger: {
56
+ error: (...args: unknown[]) => void;
57
+ }, allowBypass: boolean): PermissionMode;
44
58
  /** Owns session-mode policy and the ACP/SDK synchronization it requires. */
45
59
  export declare class SessionModeManager<S extends SessionMode> {
46
60
  private readonly options;
@@ -1 +1 @@
1
- {"version":3,"file":"session-mode.d.ts","sourceRoot":"","sources":["../src/session-mode.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,mBAAmB,EACxB,KAAK,gBAAgB,EACrB,KAAK,mBAAmB,EACxB,KAAK,qBAAqB,EAC1B,KAAK,sBAAsB,EAC5B,MAAM,0BAA0B,CAAC;AAClC,OAAO,KAAK,EACV,SAAS,EACT,cAAc,EACd,gBAAgB,EAChB,KAAK,EACN,MAAM,gCAAgC,CAAC;AASxC,eAAO,MAAM,cAAc,SAAS,CAAC;AACrC,eAAO,MAAM,kBAAkB,EAAE,cAA8B,CAAC;AAYhE,MAAM,MAAM,WAAW,GAAG;IACxB,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,mBAAmB,CAAC,CAAC;IACxC,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,KAAK,EAAE,gBAAgB,CAAC;IACxB,MAAM,EAAE;QAAE,cAAc,EAAE,MAAM,CAAA;KAAE,CAAC;IACnC,UAAU,EAAE,SAAS,EAAE,CAAC;IACxB,8EAA8E;IAC9E,4BAA4B,CAAC,EAAE,OAAO,CAAC;IACvC,gFAAgF;IAChF,8BAA8B,CAAC,EAAE,OAAO,CAAC;IACzC,6EAA6E;IAC7E,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB,CAAC;AAEF,MAAM,MAAM,yBAAyB,CAAC,CAAC,SAAS,WAAW,IAAI;IAC7D,UAAU,CAAC,SAAS,EAAE,MAAM,GAAG,CAAC,GAAG,SAAS,CAAC;IAC7C,mBAAmB,EAAE,MAAM,CAAC;IAC5B,kBAAkB,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACtF,aAAa,CAAC,MAAM,EAAE,mBAAmB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1D;;oCAEgC;IAChC,eAAe,CAAC,IAAI,OAAO,CAAC;IAC5B,QAAQ,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC;IACnC,2FAA2F;IAC3F,SAAS,CAAC,IAAI,OAAO,CAAC;CACvB,CAAC;AAEF,KAAK,iBAAiB,GAAG,WAAW,GAAG;IACrC,aAAa,EAAE,mBAAmB,EAAE,CAAC;CACtC,CAAC;AAEF,KAAK,2BAA2B,GAAG;IACjC,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,mBAAmB,CAAC,CAAC;IACxC,aAAa,EAAE,cAAc,CAAC;IAC9B,gBAAgB,CAAC,EAAE,SAAS,CAAC;IAC7B,cAAc,EAAE,MAAM,CAAC;IACvB,sEAAsE;IACtE,WAAW,EAAE,OAAO,CAAC;CACtB,CAAC;AAEF,4EAA4E;AAC5E,qBAAa,kBAAkB,CAAC,CAAC,SAAS,WAAW;IACvC,OAAO,CAAC,QAAQ,CAAC,OAAO;gBAAP,OAAO,EAAE,yBAAyB,CAAC,CAAC,CAAC;IAE5D,UAAU,CAAC,EACf,KAAK,EACL,aAAa,EACb,gBAAgB,EAChB,cAAc,EACd,WAAW,GACZ,EAAE,2BAA2B,GAAG,OAAO,CAAC;QACvC,KAAK,EAAE,gBAAgB,CAAC;QACxB,8BAA8B,EAAE,OAAO,CAAC;KACzC,CAAC;IAgCF,MAAM,CAAC,YAAY,CAAC,KAAK,EAAE,gBAAgB,GAAG,mBAAmB;IAiBjE,UAAU,CAAC,OAAO,EAAE,iBAAiB,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI;IAe1D,gBAAgB,CAAC,KAAK,EAAE,gBAAgB,GAAG,MAAM,EAAE;IAInD,aAAa,CAAC,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,cAAc,GAAG,cAAc;IAMlF,uBAAuB,CACrB,OAAO,EAAE,WAAW,EACpB,gBAAgB,EAAE,gBAAgB,GACjC;QAAE,gBAAgB,EAAE,gBAAgB,CAAC;QAAC,eAAe,EAAE,OAAO,CAAA;KAAE;IAwBnE;sDACkD;IAC5C,iBAAiB,CAAC,OAAO,EAAE,WAAW,EAAE,KAAK,EAAE,SAAS,GAAG,SAAS;IAqBpE,UAAU,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC;IAyBtE,cAAc,CAAC,MAAM,EAAE,qBAAqB,GAAG,OAAO,CAAC,sBAAsB,CAAC;IAS9E,cAAc,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAO9D,sBAAsB,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC;IAuB9E,oBAAoB,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC;IAKlF,OAAO,CAAC,kBAAkB;IAS1B,OAAO,CAAC,iBAAiB;IAQzB,OAAO,CAAC,WAAW;IAInB,OAAO,CAAC,SAAS;IAcjB,OAAO,CAAC,mBAAmB;YA4Cb,WAAW;CAW1B"}
1
+ {"version":3,"file":"session-mode.d.ts","sourceRoot":"","sources":["../src/session-mode.ts"],"names":[],"mappings":"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"}