@agentclientprotocol/claude-agent-acp 0.85.2-preview.9 → 0.86.0
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/acp-agent.d.ts +56 -21
- package/dist/acp-agent.d.ts.map +1 -1
- package/dist/acp-agent.js +161 -34
- package/dist/clear-context-coordinator.d.ts +1 -0
- package/dist/clear-context-coordinator.d.ts.map +1 -1
- package/dist/clear-context-coordinator.js +2 -1
- package/dist/diff.d.ts +45 -8
- package/dist/diff.d.ts.map +1 -1
- package/dist/diff.js +111 -30
- package/dist/permissions/presentation.d.ts +17 -2
- package/dist/permissions/presentation.d.ts.map +1 -1
- package/dist/permissions/presentation.js +4 -0
- package/dist/session-config-ids.d.ts +1 -0
- package/dist/session-config-ids.d.ts.map +1 -1
- package/dist/session-config-ids.js +1 -0
- package/dist/tool-calls/client-capabilities.d.ts +20 -2
- package/dist/tool-calls/client-capabilities.d.ts.map +1 -1
- package/dist/tool-calls/client-capabilities.js +14 -4
- package/dist/tool-calls/facts.d.ts +8 -1
- package/dist/tool-calls/facts.d.ts.map +1 -1
- package/dist/tool-calls/renderer.d.ts +5 -1
- package/dist/tool-calls/renderer.d.ts.map +1 -1
- package/dist/tool-calls/renderer.js +14 -3
- package/dist/tool-calls/reporters/bash.d.ts.map +1 -1
- package/dist/tool-calls/reporters/bash.js +32 -5
- package/dist/tool-calls/reporters/file-edit.d.ts +1 -1
- package/dist/tool-calls/reporters/file-edit.d.ts.map +1 -1
- package/dist/tool-calls/reporters/file-edit.js +20 -14
- package/dist/v2/agent.d.ts +2 -0
- package/dist/v2/agent.d.ts.map +1 -1
- package/dist/v2/agent.js +109 -14
- package/dist/v2/initialize.d.ts +2 -5
- package/dist/v2/initialize.d.ts.map +1 -1
- package/dist/v2/initialize.js +42 -11
- package/dist/v2/permission.d.ts +25 -0
- package/dist/v2/permission.d.ts.map +1 -0
- package/dist/v2/permission.js +38 -0
- package/dist/v2/session-update.d.ts +6 -0
- package/dist/v2/session-update.d.ts.map +1 -1
- package/dist/v2/session-update.js +19 -0
- package/dist/v2/session.d.ts +29 -4
- package/dist/v2/session.d.ts.map +1 -1
- package/dist/v2/session.js +41 -6
- package/dist/v2/terminal.d.ts +42 -0
- package/dist/v2/terminal.d.ts.map +1 -0
- package/dist/v2/terminal.js +95 -0
- package/dist/v2/tool-call.d.ts +38 -0
- package/dist/v2/tool-call.d.ts.map +1 -0
- package/dist/v2/tool-call.js +49 -0
- package/package.json +1 -1
package/dist/acp-agent.js
CHANGED
|
@@ -21,7 +21,7 @@ import { SessionTiming } from "./session-timing.js";
|
|
|
21
21
|
import { ALLOW_BYPASS } from "./permissions/modes.js";
|
|
22
22
|
import { normalizeDurablePermissionChangeSet } from "./permissions/normalization.js";
|
|
23
23
|
import { buildClaudePermissionOptions } from "./permissions/options.js";
|
|
24
|
-
import { buildClaudePermissionPresentation } from "./permissions/presentation.js";
|
|
24
|
+
import { buildClaudePermissionPresentation, } from "./permissions/presentation.js";
|
|
25
25
|
import { decodeClaudePermissionResponse } from "./permissions/response.js";
|
|
26
26
|
import { SettingsManager } from "./settings.js";
|
|
27
27
|
import { activeUsageLimitMessage, airSessionFailureCapabilityMeta, assistantMessageText, createSessionFailureState, isSyntheticUsageLimitMessage, providerFailureCategory, SessionFailureController, sessionFailureMeta, supportsAirSessionFailures, } from "./session-failure-extension.js";
|
|
@@ -39,8 +39,10 @@ import { AcpToolCallRenderer } from "./tool-calls/renderer.js";
|
|
|
39
39
|
import { resolveSkillPath } from "./tool-calls/reporters/interaction.js";
|
|
40
40
|
import { nodeToWebReadable, nodeToWebWritable, Pushable, raceTimeoutAndAbort, unreachable, } from "./utils.js";
|
|
41
41
|
import { acceptedPlanToolResult, ExitPlanCoordinator, isExitPlanInterruptionResult, observeExitPlanToolResults, } from "./exit-plan.js";
|
|
42
|
+
import { DEFAULT_AGENT_ID } from "./session-config-ids.js";
|
|
42
43
|
import { parseToolResultMeta } from "./tool-result-meta.js";
|
|
43
44
|
import { formatUsageResponse, isUsageCommandText, parseUsageResponse } from "./usage-markdown.js";
|
|
45
|
+
export { DEFAULT_AGENT_ID } from "./session-config-ids.js";
|
|
44
46
|
import { MCP_AVAILABLE_COMMAND, parseMcpCommand, runMcpCommand } from "./mcp-command.js";
|
|
45
47
|
import { MODE_CONFIG_ID, resolveInitialPermissionMode, SessionModeManager, } from "./session-mode.js";
|
|
46
48
|
import { applyAvailableModelsAllowlist, buildModelConfigOption, getAvailableModels, MODEL_CONFIG_ID, resolveModelPreference, } from "./session-model.js";
|
|
@@ -79,6 +81,10 @@ const DEFAULT_CONTEXT_WINDOW = 200000;
|
|
|
79
81
|
* pre-empt a slow-but-healthy interrupt. */
|
|
80
82
|
const DEFAULT_FORCE_CANCEL_GRACE_MS = 30_000;
|
|
81
83
|
const STRUCTURED_USAGE_TIMEOUT_MS = 5_000;
|
|
84
|
+
/** How long a session teardown waits for the turns that it cancels to end.
|
|
85
|
+
* The teardown wakes the consumer itself, so they end within a few ticks
|
|
86
|
+
* unless the consumer is wedged. */
|
|
87
|
+
const TEARDOWN_TURN_END_TIMEOUT_MS = 5_000;
|
|
82
88
|
/** The number of settled subagents whose parent tool call a session keeps for
|
|
83
89
|
* a later resume (see `resumableSubagents`). */
|
|
84
90
|
const MAX_RESUMABLE_SUBAGENTS = 256;
|
|
@@ -1151,7 +1157,14 @@ export class ClaudeAcpAgent {
|
|
|
1151
1157
|
* return "cancelled". See {@link DEFAULT_FORCE_CANCEL_GRACE_MS}. Mutable so
|
|
1152
1158
|
* tests can shrink it. */
|
|
1153
1159
|
forceCancelGraceMs = DEFAULT_FORCE_CANCEL_GRACE_MS;
|
|
1154
|
-
|
|
1160
|
+
/**
|
|
1161
|
+
* The connection serves ACP v2 (`src/v2/`). The agent still speaks v1
|
|
1162
|
+
* types, except for the tool call content that v2 needs and v1 cannot
|
|
1163
|
+
* express: see {@link ToolCallClientCapabilities.v2}.
|
|
1164
|
+
*/
|
|
1165
|
+
v2;
|
|
1166
|
+
constructor(client, logger, options = {}) {
|
|
1167
|
+
this.v2 = options.v2 ?? false;
|
|
1155
1168
|
this.sessions = {};
|
|
1156
1169
|
this.client = new ChangedMetaClient(client, () => this.toolCallCapabilities.air.client);
|
|
1157
1170
|
this.logger = logger ?? console;
|
|
@@ -1208,7 +1221,9 @@ export class ClaudeAcpAgent {
|
|
|
1208
1221
|
}
|
|
1209
1222
|
async initialize(request) {
|
|
1210
1223
|
this.clientCapabilities = request.clientCapabilities;
|
|
1211
|
-
this.toolCallCapabilities = ToolCallClientCapabilities.from(request.clientCapabilities
|
|
1224
|
+
this.toolCallCapabilities = ToolCallClientCapabilities.from(request.clientCapabilities, {
|
|
1225
|
+
v2: this.v2,
|
|
1226
|
+
});
|
|
1212
1227
|
// Learn the auth identity in the background: `initialize` never waits on
|
|
1213
1228
|
// the CLI probe, and no snapshot rides in its response. When the probe
|
|
1214
1229
|
// lands it calls `setAuthStatus`, which pushes `_auth/status_update` — the
|
|
@@ -3130,11 +3145,18 @@ export class ClaudeAcpAgent {
|
|
|
3130
3145
|
.then((result) => ({ kind: "message", result }));
|
|
3131
3146
|
const nextMessage = pendingNext;
|
|
3132
3147
|
// Fresh abort listener per iteration, removed when next() wins, so a
|
|
3133
|
-
// long-lived session doesn't accumulate listeners on one signal.
|
|
3148
|
+
// long-lived session doesn't accumulate listeners on one signal. An
|
|
3149
|
+
// abort that fired while the consumer was busy elsewhere, such as
|
|
3150
|
+
// sending an update, still wakes it: a listener added to an aborted
|
|
3151
|
+
// signal never fires. The consumer re-arms after each abort it
|
|
3152
|
+
// handles, so an aborted signal here is always an unhandled abort.
|
|
3134
3153
|
let onAbort;
|
|
3135
3154
|
const abortRace = new Promise((resolve) => {
|
|
3136
3155
|
onAbort = () => resolve("abort");
|
|
3137
|
-
cancelController.signal.
|
|
3156
|
+
if (cancelController.signal.aborted)
|
|
3157
|
+
onAbort();
|
|
3158
|
+
else
|
|
3159
|
+
cancelController.signal.addEventListener("abort", onAbort, { once: true });
|
|
3138
3160
|
});
|
|
3139
3161
|
const raced = await Promise.race([nextMessage, abortRace]);
|
|
3140
3162
|
cancelController.signal.removeEventListener("abort", onAbort);
|
|
@@ -4723,6 +4745,7 @@ export class ClaudeAcpAgent {
|
|
|
4723
4745
|
}
|
|
4724
4746
|
for (const notification of streamEventToAcpNotifications(message, params.sessionId, session.toolUseCache, this.client, this.logger, {
|
|
4725
4747
|
clientCapabilities: this.clientCapabilities,
|
|
4748
|
+
toolCallCapabilities: this.toolCallCapabilities,
|
|
4726
4749
|
cwd: session.cwd,
|
|
4727
4750
|
taskState: session.taskState,
|
|
4728
4751
|
emittedToolCalls: session.emittedToolCalls,
|
|
@@ -4926,6 +4949,7 @@ export class ClaudeAcpAgent {
|
|
|
4926
4949
|
if (typeof stripped === "string") {
|
|
4927
4950
|
for (const notification of toAcpNotifications(stripped, message.message.role, params.sessionId, session.toolUseCache, routedNotificationClient, this.logger, {
|
|
4928
4951
|
clientCapabilities: this.clientCapabilities,
|
|
4952
|
+
toolCallCapabilities: this.toolCallCapabilities,
|
|
4929
4953
|
parentToolUseId: message.parent_tool_use_id,
|
|
4930
4954
|
cwd: session.cwd,
|
|
4931
4955
|
taskState: session.taskState,
|
|
@@ -5007,6 +5031,7 @@ export class ClaudeAcpAgent {
|
|
|
5007
5031
|
}
|
|
5008
5032
|
for (const notification of toAcpNotifications(content, message.message.role, params.sessionId, session.toolUseCache, routedNotificationClient, this.logger, {
|
|
5009
5033
|
clientCapabilities: this.clientCapabilities,
|
|
5034
|
+
toolCallCapabilities: this.toolCallCapabilities,
|
|
5010
5035
|
parentToolUseId: message.parent_tool_use_id,
|
|
5011
5036
|
cwd: session.cwd,
|
|
5012
5037
|
taskState: session.taskState,
|
|
@@ -5554,12 +5579,18 @@ export class ClaudeAcpAgent {
|
|
|
5554
5579
|
session.query.close();
|
|
5555
5580
|
}
|
|
5556
5581
|
/** Cleanly tear down a session: cancel in-flight work, release stream
|
|
5557
|
-
* resources, and remove it from the session map.
|
|
5582
|
+
* resources, and remove it from the session map. Returns once the turns it
|
|
5583
|
+
* cancels have ended, so their end (a v1 `session/prompt` response, a v2
|
|
5584
|
+
* `idle` state) goes out before the caller answers: ACP v2's
|
|
5585
|
+
* `session/close` cancels "as if `session/cancel` had been called", then
|
|
5586
|
+
* frees the session. A wedged consumer holds it at most
|
|
5587
|
+
* {@link TEARDOWN_TURN_END_TIMEOUT_MS}. */
|
|
5558
5588
|
async teardownSession(sessionId) {
|
|
5559
5589
|
const session = this.sessions[sessionId];
|
|
5560
5590
|
if (!session) {
|
|
5561
5591
|
return;
|
|
5562
5592
|
}
|
|
5593
|
+
const turnsEnded = Promise.all((session.turnQueue ?? []).flatMap((turn) => (turn.completion ? [turn.completion] : [])));
|
|
5563
5594
|
try {
|
|
5564
5595
|
await this.cancelTurns({ sessionId }, { awaitInterrupt: false });
|
|
5565
5596
|
}
|
|
@@ -5587,6 +5618,10 @@ export class ClaudeAcpAgent {
|
|
|
5587
5618
|
session.nativeSubagentRuntime?.clear();
|
|
5588
5619
|
session.asyncTaskRuntime?.clear();
|
|
5589
5620
|
delete this.sessions[sessionId];
|
|
5621
|
+
const ended = await raceTimeoutAndAbort(turnsEnded, TEARDOWN_TURN_END_TIMEOUT_MS, new AbortController().signal);
|
|
5622
|
+
if (ended.type === "timeout") {
|
|
5623
|
+
this.logger.error(`Session ${sessionId}: its cancelled turns did not end within ${TEARDOWN_TURN_END_TIMEOUT_MS}ms of the teardown`);
|
|
5624
|
+
}
|
|
5590
5625
|
}
|
|
5591
5626
|
/** Tear down all active sessions. Called when the ACP connection closes. */
|
|
5592
5627
|
async dispose() {
|
|
@@ -5981,6 +6016,7 @@ export class ClaudeAcpAgent {
|
|
|
5981
6016
|
registerHooks: false,
|
|
5982
6017
|
replay: true,
|
|
5983
6018
|
clientCapabilities: this.clientCapabilities,
|
|
6019
|
+
toolCallCapabilities: this.toolCallCapabilities,
|
|
5984
6020
|
cwd: replayState()?.cwd,
|
|
5985
6021
|
taskState: replayState()?.taskState,
|
|
5986
6022
|
messageId: replayMessageId,
|
|
@@ -6120,8 +6156,10 @@ export class ClaudeAcpAgent {
|
|
|
6120
6156
|
// Do not rely on every ACP client settling requestPermission after the
|
|
6121
6157
|
// cancellation signal. The local race guarantees that Claude's tool call
|
|
6122
6158
|
// is released even when an older or broken client ignores $/cancel_request.
|
|
6159
|
+
// The request goes to a subagent's child session for a tool call of that
|
|
6160
|
+
// subagent, but it blocks the turn of the owner session.
|
|
6123
6161
|
try {
|
|
6124
|
-
return await this.withPendingUserInput(
|
|
6162
|
+
return await this.withPendingUserInput(ownerSessionId, () => raceWithAbort(this.client.requestPermission(params, signal), signal));
|
|
6125
6163
|
}
|
|
6126
6164
|
catch (error) {
|
|
6127
6165
|
if (signal.aborted) {
|
|
@@ -6231,7 +6269,7 @@ export class ClaudeAcpAgent {
|
|
|
6231
6269
|
// Like permission requests, the elicitation references this toolUseID, so
|
|
6232
6270
|
// make sure the tool_call has surfaced to the client before we send it.
|
|
6233
6271
|
await this.ensureToolCallEmitted(sessionId, toolName, toolUseID, toolInput, parentToolUseId, signal, permissionSessionId);
|
|
6234
|
-
return this.handleAskUserQuestion(permissionSessionId, toolInput, toolUseID, signal);
|
|
6272
|
+
return this.handleAskUserQuestion(sessionId, permissionSessionId, toolInput, toolUseID, signal);
|
|
6235
6273
|
}
|
|
6236
6274
|
// Do not auto-allow here based on the session's advertised mode. Claude
|
|
6237
6275
|
// Code applies bypassPermissions before invoking canUseTool; a request
|
|
@@ -6247,8 +6285,8 @@ export class ClaudeAcpAgent {
|
|
|
6247
6285
|
const noPersistentRule = matchedAskRule !== undefined || suppressAlwaysAllowRule === true;
|
|
6248
6286
|
const durableChangeSet = normalizeDurablePermissionChangeSet(suggestions, noPersistentRule);
|
|
6249
6287
|
const capabilities = this.toolCallCapabilities;
|
|
6250
|
-
const previewContent = capabilities.diffPatch
|
|
6251
|
-
? await previewPatchContent(toolName, toolInput, session.cwd)
|
|
6288
|
+
const previewContent = capabilities.diffPatch || capabilities.v2
|
|
6289
|
+
? await previewPatchContent(toolName, toolInput, session.cwd, capabilities.v2 ? "v2" : "air")
|
|
6252
6290
|
: undefined;
|
|
6253
6291
|
const presentation = buildClaudePermissionPresentation({
|
|
6254
6292
|
toolName,
|
|
@@ -6385,13 +6423,15 @@ export class ClaudeAcpAgent {
|
|
|
6385
6423
|
* Present the built-in AskUserQuestion tool's questions as an ACP form
|
|
6386
6424
|
* elicitation and return the answers as the tool's `updatedInput`. Called from
|
|
6387
6425
|
* `canUseTool` since that is where the SDK routes the tool's permission check.
|
|
6426
|
+
* The elicitation goes to `requestSessionId`, a subagent's child session for
|
|
6427
|
+
* a question it asks, and blocks the turn of `sessionId`.
|
|
6388
6428
|
*/
|
|
6389
|
-
async handleAskUserQuestion(sessionId, toolInput, toolUseID, signal) {
|
|
6429
|
+
async handleAskUserQuestion(sessionId, requestSessionId, toolInput, toolUseID, signal) {
|
|
6390
6430
|
const questions = extractAskUserQuestions(toolInput);
|
|
6391
6431
|
if (!questions) {
|
|
6392
6432
|
return { behavior: "deny", message: "AskUserQuestion called with no valid questions." };
|
|
6393
6433
|
}
|
|
6394
|
-
const createRequest = askUserQuestionsToCreateRequest(questions,
|
|
6434
|
+
const createRequest = askUserQuestionsToCreateRequest(questions, requestSessionId, toolUseID, this.toolCallCapabilities.air.client);
|
|
6395
6435
|
let response;
|
|
6396
6436
|
try {
|
|
6397
6437
|
response = await this.withPendingUserInput(sessionId, () => this.client.createElicitation(createRequest, signal));
|
|
@@ -6479,15 +6519,21 @@ export class ClaudeAcpAgent {
|
|
|
6479
6519
|
});
|
|
6480
6520
|
}
|
|
6481
6521
|
/**
|
|
6482
|
-
*
|
|
6522
|
+
* Refine a heuristic context window with `getContextUsage().rawMaxTokens`,
|
|
6483
6523
|
* without blocking the caller. The text heuristic misses natively-1M models
|
|
6484
|
-
* whose picker rows carry no "1m" token (`sonnet`, and since CLI
|
|
6485
|
-
* `opus`/`default`),
|
|
6486
|
-
* result's modelUsage.
|
|
6487
|
-
*
|
|
6488
|
-
*
|
|
6489
|
-
*
|
|
6490
|
-
*
|
|
6524
|
+
* whose picker rows carry no "1m" token (e.g. `sonnet`, and since CLI
|
|
6525
|
+
* 2.1.283 `opus`/`default`), so those would otherwise show 200k until the
|
|
6526
|
+
* first result's modelUsage arrives.
|
|
6527
|
+
*
|
|
6528
|
+
* Never awaited: SDK control requests are serialized, so awaiting here
|
|
6529
|
+
* would delay session/new or a model switch (~15s on older CLIs, issues
|
|
6530
|
+
* #886/#880; ~0.5s on 2.1.283). Requests the `summary` detail instead of
|
|
6531
|
+
* the default `full` breakdown, which issues one `messages/count_tokens`
|
|
6532
|
+
* call per category (~18 for a bare session) and hit rate limits on every
|
|
6533
|
+
* model switch; `summary` answers locally with the same `rawMaxTokens`.
|
|
6534
|
+
*
|
|
6535
|
+
* Does not write `contextWindowCache` (that stays keyed to the
|
|
6536
|
+
* `result.modelUsage` spellings) — a later result still overwrites this.
|
|
6491
6537
|
*/
|
|
6492
6538
|
refreshContextWindowInBackground(sessionId, session) {
|
|
6493
6539
|
if (session.contextWindowAuthoritative)
|
|
@@ -6499,7 +6545,7 @@ export class ClaudeAcpAgent {
|
|
|
6499
6545
|
session.models.currentModelId === modelId;
|
|
6500
6546
|
// A synchronous throw must not fail the caller either.
|
|
6501
6547
|
Promise.resolve()
|
|
6502
|
-
.then(() => query.getContextUsage())
|
|
6548
|
+
.then(() => query.getContextUsage({ detail: "summary" }))
|
|
6503
6549
|
.then((usage) => {
|
|
6504
6550
|
if (!stillCurrent() || session.contextWindowAuthoritative)
|
|
6505
6551
|
return;
|
|
@@ -6569,7 +6615,7 @@ export class ClaudeAcpAgent {
|
|
|
6569
6615
|
const seedEffort = effortPinnedForNewModel
|
|
6570
6616
|
? pinnedEffort
|
|
6571
6617
|
: settingsEffortForModel(mergeEffortSettings(session.settingsManager.getSettings(), session.effortSettingsOverride), newModelInfo, value);
|
|
6572
|
-
session.configOptions = buildConfigOptions(session.modes, session.models, session.modelInfos, seedEffort, {
|
|
6618
|
+
session.configOptions = buildConfigOptions(session.modes, session.models, session.modelInfos, seedEffort, session.agents, session.currentAgent, {
|
|
6573
6619
|
// The toggle follows the newly selected model: it disappears when the
|
|
6574
6620
|
// model lacks fast support and reappears (with the retained user
|
|
6575
6621
|
// intent) when a supporting model is selected again.
|
|
@@ -6648,6 +6694,18 @@ export class ClaudeAcpAgent {
|
|
|
6648
6694
|
if (modelChanged)
|
|
6649
6695
|
this.refreshContextWindowInBackground(sessionId, session);
|
|
6650
6696
|
}
|
|
6697
|
+
else if (configId === AGENT_CONFIG_ID) {
|
|
6698
|
+
// Live agent switch — no subprocess restart needed. Apply the SDK flag
|
|
6699
|
+
// first so a rejected control request leaves both `currentAgent` and the
|
|
6700
|
+
// config option untouched (no UI/SDK desync). Passing `null` clears the
|
|
6701
|
+
// flag layer back to the standard Claude Code agent; the change takes
|
|
6702
|
+
// effect on the next turn (SDK >= 0.3.161).
|
|
6703
|
+
await session.query.applyFlagSettings({
|
|
6704
|
+
agent: value === DEFAULT_AGENT_ID ? null : value,
|
|
6705
|
+
});
|
|
6706
|
+
session.currentAgent = value;
|
|
6707
|
+
session.configOptions = session.configOptions.map((o) => o.id === configId && typeof o.currentValue === "string" ? { ...o, currentValue: value } : o);
|
|
6708
|
+
}
|
|
6651
6709
|
else if (configId === EFFORT_CONFIG_ID) {
|
|
6652
6710
|
// Apply first so a rejected control request cannot leave the displayed
|
|
6653
6711
|
// value ahead of the SDK flag layer.
|
|
@@ -6954,14 +7012,7 @@ export class ClaudeAcpAgent {
|
|
|
6954
7012
|
resumed: resumedPermissionMode,
|
|
6955
7013
|
defaultMode: settingsManager.getSettings().permissions?.defaultMode,
|
|
6956
7014
|
}, this.logger, allowBypass);
|
|
6957
|
-
const userProvidedOptions = sessionMeta?.claudeCode?.options
|
|
6958
|
-
? { ...sessionMeta.claudeCode.options }
|
|
6959
|
-
: undefined;
|
|
6960
|
-
// Main-thread agent selection is intentionally not part of this adapter's
|
|
6961
|
-
// ACP contract. Ignore the provider-specific option instead of forwarding
|
|
6962
|
-
// hidden state that the Client cannot inspect or change.
|
|
6963
|
-
if (userProvidedOptions)
|
|
6964
|
-
delete userProvidedOptions.agent;
|
|
7015
|
+
const userProvidedOptions = sessionMeta?.claudeCode?.options;
|
|
6965
7016
|
const forwardSubagentText = this.forwardsSubagentText(params._meta);
|
|
6966
7017
|
// Configure thinking behavior from environment variable
|
|
6967
7018
|
const thinking = resolveThinkingConfig(process.env.MAX_THINKING_TOKENS, this.logger);
|
|
@@ -7326,6 +7377,17 @@ export class ClaudeAcpAgent {
|
|
|
7326
7377
|
allowBypass,
|
|
7327
7378
|
});
|
|
7328
7379
|
timing.phase("modes");
|
|
7380
|
+
const agents = await discoverCustomAgents(q);
|
|
7381
|
+
timing.phase("agents");
|
|
7382
|
+
// Only adopt the requested agent as the selected value if it's one we
|
|
7383
|
+
// actually surface in the picker. A built-in (filtered out above) or
|
|
7384
|
+
// otherwise-unknown name would leave the config option's `currentValue`
|
|
7385
|
+
// pointing at an entry not in its own `options` list, which clients render
|
|
7386
|
+
// as a blank/invalid selection.
|
|
7387
|
+
const requestedAgent = userProvidedOptions?.agent;
|
|
7388
|
+
const currentAgent = requestedAgent && agents.some((a) => a.name === requestedAgent)
|
|
7389
|
+
? requestedAgent
|
|
7390
|
+
: DEFAULT_AGENT_ID;
|
|
7329
7391
|
// Seed Fast mode from the SDK's reported state so the UI reflects reality
|
|
7330
7392
|
// (the CLI may start a session with fast mode already on, or force it off
|
|
7331
7393
|
// when `fastModePerSessionOptIn` is set). The toggle is only surfaced while
|
|
@@ -7351,7 +7413,7 @@ export class ClaudeAcpAgent {
|
|
|
7351
7413
|
// Legacy clients still leave effort resolution entirely to the CLI.
|
|
7352
7414
|
const useRecommendedValue = clientSupportsRecommendedConfigValue(this.clientCapabilities);
|
|
7353
7415
|
const effortSettings = mergeEffortSettings(settingsManager.getSettings(), configuredSettingsObject);
|
|
7354
|
-
const configOptions = buildConfigOptions(modes, models, modelInfos, userProvidedOptions?.effort ?? settingsEffortForModel(effortSettings, currentModelInfo), fastMode, {
|
|
7416
|
+
const configOptions = buildConfigOptions(modes, models, modelInfos, userProvidedOptions?.effort ?? settingsEffortForModel(effortSettings, currentModelInfo), agents, currentAgent, fastMode, {
|
|
7355
7417
|
useRecommendedValue,
|
|
7356
7418
|
});
|
|
7357
7419
|
const initialEffort = configOptions.find((option) => option.id === EFFORT_CONFIG_ID);
|
|
@@ -7412,6 +7474,8 @@ export class ClaudeAcpAgent {
|
|
|
7412
7474
|
initialEffort?.currentValue === userProvidedOptions.effort
|
|
7413
7475
|
? userProvidedOptions.effort
|
|
7414
7476
|
: undefined,
|
|
7477
|
+
agents,
|
|
7478
|
+
currentAgent,
|
|
7415
7479
|
fastModeEnabled,
|
|
7416
7480
|
fastModeDisabledReason,
|
|
7417
7481
|
abortController,
|
|
@@ -7844,11 +7908,43 @@ function isValidBaseUrl(baseUrl) {
|
|
|
7844
7908
|
}
|
|
7845
7909
|
return parsed.protocol === "http:" || parsed.protocol === "https:";
|
|
7846
7910
|
}
|
|
7911
|
+
// `supportedAgents()` always returns Claude Code's built-in subagents — the
|
|
7912
|
+
// ones used for Task-tool delegation (Explore, Plan, etc.) — even when the user
|
|
7913
|
+
// has configured none of their own. Those aren't meaningful *main-thread*
|
|
7914
|
+
// personas, so we filter them out and only surface the Agent picker when the
|
|
7915
|
+
// user (or a plugin/project) has configured custom agents. Update this set if
|
|
7916
|
+
// the SDK's built-in roster changes.
|
|
7917
|
+
export const BUILTIN_AGENT_NAMES = new Set([
|
|
7918
|
+
"claude",
|
|
7919
|
+
"general-purpose",
|
|
7920
|
+
"Explore",
|
|
7921
|
+
"Plan",
|
|
7922
|
+
"statusline-setup",
|
|
7923
|
+
]);
|
|
7924
|
+
// Value of the synthetic "Default" entry in the agent picker, which maps to the
|
|
7925
|
+
// standard Claude Code agent (`applyFlagSettings({ agent: null })`). It is a
|
|
7926
|
+
// reserved sentinel: a custom agent named exactly this would collide with it
|
|
7927
|
+
// (two options sharing the value, selection silently routing to `null`), so we
|
|
7928
|
+
// exclude that name from discovery.
|
|
7929
|
+
/** Discover user/plugin/project-configured main-thread agents, excluding the
|
|
7930
|
+
* built-in subagents and the reserved "default" sentinel. Returns an empty
|
|
7931
|
+
* list if discovery fails so a flaky control request never blocks session
|
|
7932
|
+
* creation. */
|
|
7933
|
+
export async function discoverCustomAgents(q) {
|
|
7934
|
+
try {
|
|
7935
|
+
const agents = await q.supportedAgents();
|
|
7936
|
+
return agents.filter((a) => !BUILTIN_AGENT_NAMES.has(a.name) && a.name !== DEFAULT_AGENT_ID);
|
|
7937
|
+
}
|
|
7938
|
+
catch {
|
|
7939
|
+
return [];
|
|
7940
|
+
}
|
|
7941
|
+
}
|
|
7847
7942
|
/** Stable ids for the session config options surfaced via `configOptions`.
|
|
7848
7943
|
* Centralized so the option declarations in `buildConfigOptions` and the
|
|
7849
7944
|
* handlers in `setSessionConfigOption`/`applyConfigOptionValue` reference the
|
|
7850
7945
|
* same identifiers and can't drift apart. */
|
|
7851
7946
|
export { MODE_CONFIG_ID };
|
|
7947
|
+
export const AGENT_CONFIG_ID = "agent";
|
|
7852
7948
|
export const FAST_MODE_CONFIG_ID = "fast";
|
|
7853
7949
|
/** Select-fallback values used when the client has not opted into boolean
|
|
7854
7950
|
* config options (see {@link createFastModeConfigOption}). */
|
|
@@ -7950,7 +8046,7 @@ export function resolveFastModeEnabled(params) {
|
|
|
7950
8046
|
}
|
|
7951
8047
|
throw new Error(`Invalid value for config option ${FAST_MODE_CONFIG_ID}: ${value}`);
|
|
7952
8048
|
}
|
|
7953
|
-
export function buildConfigOptions(modes, models, modelInfos, currentEffortLevel, fastMode, presentation) {
|
|
8049
|
+
export function buildConfigOptions(modes, models, modelInfos, currentEffortLevel, agents = [], currentAgent = DEFAULT_AGENT_ID, fastMode, presentation) {
|
|
7954
8050
|
const options = [
|
|
7955
8051
|
SessionModeManager.configOption(modes),
|
|
7956
8052
|
buildModelConfigOption(models, modelInfos, presentation?.useRecommendedValue === true),
|
|
@@ -7964,6 +8060,27 @@ export function buildConfigOptions(modes, models, modelInfos, currentEffortLevel
|
|
|
7964
8060
|
if (fastMode?.supported) {
|
|
7965
8061
|
options.push(createFastModeConfigOption(fastMode.enabled, fastMode.useBooleanOption, fastMode.disabledReason));
|
|
7966
8062
|
}
|
|
8063
|
+
// Only surface the Agent picker when there's a real choice — i.e. the user
|
|
8064
|
+
// has configured at least one custom agent (built-ins are filtered out in
|
|
8065
|
+
// discoverCustomAgents). With none configured, "Default" would be the only
|
|
8066
|
+
// entry, so we omit the option entirely.
|
|
8067
|
+
if (agents.length > 0) {
|
|
8068
|
+
options.push({
|
|
8069
|
+
id: AGENT_CONFIG_ID,
|
|
8070
|
+
name: "Agent",
|
|
8071
|
+
description: "Main-thread agent persona",
|
|
8072
|
+
type: "select",
|
|
8073
|
+
currentValue: currentAgent,
|
|
8074
|
+
options: [
|
|
8075
|
+
{ value: DEFAULT_AGENT_ID, name: "Default", description: "Standard Claude Code agent" },
|
|
8076
|
+
...agents.map((a) => ({
|
|
8077
|
+
value: a.name,
|
|
8078
|
+
name: a.name,
|
|
8079
|
+
description: a.description || undefined,
|
|
8080
|
+
})),
|
|
8081
|
+
],
|
|
8082
|
+
});
|
|
8083
|
+
}
|
|
7967
8084
|
return options;
|
|
7968
8085
|
}
|
|
7969
8086
|
function getAvailableSlashCommands(commands,
|
|
@@ -8201,10 +8318,19 @@ function toolCallFieldsOf(session) {
|
|
|
8201
8318
|
* Convert an SDKAssistantMessage (Claude) to a SessionNotification (ACP).
|
|
8202
8319
|
* Only handles text, image, and thinking chunks for now.
|
|
8203
8320
|
*/
|
|
8321
|
+
/**
|
|
8322
|
+
* The renderer of the notification functions: the agent's tool call
|
|
8323
|
+
* capabilities when they are passed, else those of the ACP capabilities.
|
|
8324
|
+
*/
|
|
8325
|
+
function toolCallRenderer(options) {
|
|
8326
|
+
return options?.toolCallCapabilities
|
|
8327
|
+
? new AcpToolCallRenderer(options.toolCallCapabilities, options.replay)
|
|
8328
|
+
: AcpToolCallRenderer.for(options?.clientCapabilities, options?.replay);
|
|
8329
|
+
}
|
|
8204
8330
|
export function toAcpNotifications(content, role, sessionId, toolUseCache, client, logger, options) {
|
|
8205
8331
|
const taskState = options?.taskState ?? new Map();
|
|
8206
8332
|
const registerHooks = options?.registerHooks !== false;
|
|
8207
|
-
const renderer =
|
|
8333
|
+
const renderer = toolCallRenderer(options);
|
|
8208
8334
|
if (typeof content === "string") {
|
|
8209
8335
|
if (content.length === 0) {
|
|
8210
8336
|
return [];
|
|
@@ -8542,6 +8668,7 @@ export function streamEventToAcpNotifications(message, sessionId, toolUseCache,
|
|
|
8542
8668
|
const streamedToolInputs = options?.streamedToolInputs;
|
|
8543
8669
|
const forwardedOptions = {
|
|
8544
8670
|
clientCapabilities: options?.clientCapabilities,
|
|
8671
|
+
toolCallCapabilities: options?.toolCallCapabilities,
|
|
8545
8672
|
parentToolUseId: message.parent_tool_use_id,
|
|
8546
8673
|
cwd: options?.cwd,
|
|
8547
8674
|
taskState: options?.taskState,
|
|
@@ -8605,7 +8732,7 @@ export function streamEventToAcpNotifications(message, sessionId, toolUseCache,
|
|
|
8605
8732
|
// TodoWrite and the Task* tools never surfaced a tool_call to refine.
|
|
8606
8733
|
if (!shouldEmitToolCall(streamedInput.name))
|
|
8607
8734
|
return [];
|
|
8608
|
-
const update =
|
|
8735
|
+
const update = toolCallRenderer(options).partialRefinement(streamedInput, input, options?.cwd);
|
|
8609
8736
|
if (message.parent_tool_use_id)
|
|
8610
8737
|
stampParentToolUseId(update, message.parent_tool_use_id);
|
|
8611
8738
|
applyMessageId(update, options?.messageId);
|
|
@@ -29,6 +29,7 @@ export type ClearContextSession<Turn extends ClearContextTurn = ClearContextTurn
|
|
|
29
29
|
currentModelId: string;
|
|
30
30
|
};
|
|
31
31
|
configOptions: SessionConfigOption[];
|
|
32
|
+
currentAgent: string;
|
|
32
33
|
fastModeEnabled: boolean;
|
|
33
34
|
effortPinnedLevel?: string;
|
|
34
35
|
activeTurn?: Turn | null;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"clear-context-coordinator.d.ts","sourceRoot":"","sources":["../src/clear-context-coordinator.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AACvF,OAAO,KAAK,EAGV,cAAc,EACd,cAAc,EACf,MAAM,gCAAgC,CAAC;AAGxC,MAAM,MAAM,iBAAiB,GAAG;IAC9B,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,cAAc,CAAC;CACtB,CAAC;AAEF,KAAK,KAAK,GAAG;IACX,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,gBAAgB,EAAE,MAAM,CAAC;IACzB,iBAAiB,EAAE,MAAM,CAAC;CAC3B,CAAC;AAEF,MAAM,MAAM,gBAAgB,GAAG;IAC7B,OAAO,EAAE,OAAO,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,CAAC,EAAE,KAAK,CAAC;IACrB,iBAAiB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;CAC3C,CAAC;AAEF;;+EAE+E;AAC/E,MAAM,MAAM,mBAAmB,CAAC,IAAI,SAAS,gBAAgB,GAAG,gBAAgB,IAAI;IAClF,GAAG,EAAE,MAAM,CAAC;IACZ,cAAc,CAAC,EAAE,iBAAiB,CAAC;IACnC,gBAAgB,EAAE,KAAK,CAAC;IACxB,qBAAqB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;IAC9C,MAAM,EAAE;QAAE,cAAc,EAAE,MAAM,CAAA;KAAE,CAAC;IACnC,aAAa,EAAE,mBAAmB,EAAE,CAAC;IACrC,eAAe,EAAE,OAAO,CAAC;IACzB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,UAAU,CAAC,EAAE,IAAI,GAAG,IAAI,CAAC;IACzB,SAAS,CAAC,EAAE,IAAI,EAAE,CAAC;IACnB,2BAA2B,CAAC,EAAE,iBAAiB,CAAC;IAChD,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,KAAK,EAAE;QAAE,IAAI,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAAA;KAAE,CAAC;CACnD,CAAC;AAEF,MAAM,MAAM,2BAA2B,CACrC,OAAO,SAAS,mBAAmB,CAAC,IAAI,CAAC,EACzC,IAAI,SAAS,gBAAgB,IAC3B;IACF,cAAc,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,GAAG,SAAS,CAAC;IACvD,gBAAgB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAAC;IACzC,cAAc,CACZ,MAAM,EAAE,iBAAiB,EACzB,OAAO,EAAE;QAAE,eAAe,EAAE,MAAM,CAAC;QAAC,cAAc,EAAE,cAAc,CAAA;KAAE,GACnE,OAAO,CAAC,OAAO,CAAC,CAAC;IACpB,aAAa,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACjE,mBAAmB,CACjB,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,cAAc,EACpB,aAAa,EAAE,mBAAmB,EAAE,GACnC,OAAO,CAAC,IAAI,CAAC,CAAC;IACjB,mBAAmB,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,cAAc,CAAC;IACzF,cAAc,CAAC,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1D,QAAQ,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,IAAI,CAAC;CACjD,CAAC;
|
|
1
|
+
{"version":3,"file":"clear-context-coordinator.d.ts","sourceRoot":"","sources":["../src/clear-context-coordinator.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { DEFAULT_MODEL_ID } from "./session-config-ids.js";
|
|
1
|
+
import { DEFAULT_AGENT_ID, DEFAULT_MODEL_ID } from "./session-config-ids.js";
|
|
2
2
|
function restartParams(session) {
|
|
3
3
|
const originalParams = session.creationParams ?? { cwd: session.cwd, mcpServers: [] };
|
|
4
4
|
const originalMeta = originalParams._meta;
|
|
@@ -18,6 +18,7 @@ function restartParams(session) {
|
|
|
18
18
|
...(session.models.currentModelId !== DEFAULT_MODEL_ID
|
|
19
19
|
? { model: session.models.currentModelId }
|
|
20
20
|
: {}),
|
|
21
|
+
...(session.currentAgent !== DEFAULT_AGENT_ID ? { agent: session.currentAgent } : {}),
|
|
21
22
|
...(session.effortPinnedLevel !== undefined
|
|
22
23
|
? { effort: session.effortPinnedLevel }
|
|
23
24
|
: {}),
|
package/dist/diff.d.ts
CHANGED
|
@@ -23,6 +23,17 @@ interface PatchHunk {
|
|
|
23
23
|
}
|
|
24
24
|
/** The kind of file change that a git patch describes. */
|
|
25
25
|
type FileChange = "create" | "update";
|
|
26
|
+
/**
|
|
27
|
+
* The diff that carries an exact patch: AIR's `diffPatch` extension of a v1
|
|
28
|
+
* diff, or an ACP v2 diff.
|
|
29
|
+
*/
|
|
30
|
+
export type PatchForm = "air" | "v2";
|
|
31
|
+
/**
|
|
32
|
+
* How a git patch names its file. `git` is git's own form: the leading slash
|
|
33
|
+
* dropped and the `a/` and `b/` prefixes added. `absolute` is the form of an
|
|
34
|
+
* ACP v2 `git_patch`, whose paths must be absolute: the path itself.
|
|
35
|
+
*/
|
|
36
|
+
type GitPatchPaths = "git" | "absolute";
|
|
26
37
|
/**
|
|
27
38
|
* Builds the exact patch shown before Claude runs an Edit or Write tool.
|
|
28
39
|
*
|
|
@@ -35,14 +46,14 @@ type FileChange = "create" | "update";
|
|
|
35
46
|
* normalizes quotes or fails.
|
|
36
47
|
*
|
|
37
48
|
* A Write always gets content that shows the change: the patch, the standard
|
|
38
|
-
* diff of a text that cannot have an exact patch, or
|
|
39
|
-
* overwrites a file that the adapter cannot show.
|
|
49
|
+
* diff (in v2, the change alone) of a text that cannot have an exact patch, or
|
|
50
|
+
* a notice that the Write overwrites a file that the adapter cannot show.
|
|
40
51
|
*
|
|
41
52
|
* The preview uses the tool input as it is. Claude can still remove the
|
|
42
53
|
* trailing whitespace of a line before it writes. The PostToolUse hook then
|
|
43
54
|
* sends the patch of the written file.
|
|
44
55
|
*/
|
|
45
|
-
export declare function previewPatchContent(toolName: string, input: Record<string, unknown>, cwd?: string): Promise<ToolCallContent[] | undefined>;
|
|
56
|
+
export declare function previewPatchContent(toolName: string, input: Record<string, unknown>, cwd?: string, form?: PatchForm): Promise<ToolCallContent[] | undefined>;
|
|
46
57
|
/**
|
|
47
58
|
* Builds the git patch for a finished Edit or Write from the file on disk.
|
|
48
59
|
*
|
|
@@ -54,7 +65,7 @@ export declare function previewPatchContent(toolName: string, input: Record<stri
|
|
|
54
65
|
* A written file that contains a CR or a byte order mark is declined, because
|
|
55
66
|
* Claude removed those bytes from `originalFile`.
|
|
56
67
|
*/
|
|
57
|
-
export declare function patchUpdateFromDiffToolResponse(toolResponse: unknown): Promise<{
|
|
68
|
+
export declare function patchUpdateFromDiffToolResponse(toolResponse: unknown, form?: PatchForm): Promise<{
|
|
58
69
|
content: ToolCallContent[];
|
|
59
70
|
locations: ToolCallLocation[];
|
|
60
71
|
} | undefined>;
|
|
@@ -69,13 +80,39 @@ export declare function toolUpdateFromDiffToolResponse(toolResponse: unknown): {
|
|
|
69
80
|
content?: ToolCallContent[];
|
|
70
81
|
locations?: ToolCallLocation[];
|
|
71
82
|
};
|
|
83
|
+
/**
|
|
84
|
+
* The ACP v2 diff of a finished Edit or Write: the exact patch of
|
|
85
|
+
* {@link patchUpdateFromDiffToolResponse} when it can be built, else the
|
|
86
|
+
* change with a patch from what the toolResponse holds.
|
|
87
|
+
*
|
|
88
|
+
* The fallback patch of an update comes from the `structuredPatch`, which is
|
|
89
|
+
* display data (see {@link patchUpdateFromDiffToolResponse}). That is enough
|
|
90
|
+
* for a v2 patch, which is renderable text, not a patch to apply. An update
|
|
91
|
+
* without hunks, such as one whose previous content was too large to diff,
|
|
92
|
+
* gets the change alone. An Edit with an empty `old_string` reports the same
|
|
93
|
+
* response for a created file and a filled empty one, so it gets no diff.
|
|
94
|
+
*/
|
|
95
|
+
export declare function v2UpdateFromDiffToolResponse(toolResponse: unknown): Promise<{
|
|
96
|
+
content?: ToolCallContent[];
|
|
97
|
+
locations?: ToolCallLocation[];
|
|
98
|
+
}>;
|
|
72
99
|
/**
|
|
73
100
|
* The text of one git patch for `filePath`.
|
|
74
101
|
*
|
|
75
|
-
* The headers follow `git diff`: the path
|
|
76
|
-
*
|
|
77
|
-
*
|
|
102
|
+
* The headers follow `git diff`: the path is quoted when git would quote it,
|
|
103
|
+
* and a created file gets its mode line and a `/dev/null` side. With `git`
|
|
104
|
+
* paths, the path loses its leading slash and gets the `a/` and `b/` prefixes.
|
|
105
|
+
*/
|
|
106
|
+
export declare function gitPatchText(filePath: string, change: FileChange, hunks: PatchHunk[], paths?: GitPatchPaths): string;
|
|
107
|
+
/**
|
|
108
|
+
* The ACP v2 diff of a change to the text file `filePath`: the change and,
|
|
109
|
+
* given hunks, its git patch.
|
|
110
|
+
*
|
|
111
|
+
* The agent builds tool call content in v1 types, and v1 cannot express a v2
|
|
112
|
+
* diff, so the diff travels as v1 content. Nothing in the agent reads inside a
|
|
113
|
+
* diff, and only a v2 client gets one: the v2 surface sends it as it is
|
|
114
|
+
* (`src/v2/tool-call.ts`).
|
|
78
115
|
*/
|
|
79
|
-
export declare function
|
|
116
|
+
export declare function v2DiffContent(filePath: string, change: FileChange, hunks?: PatchHunk[]): ToolCallContent;
|
|
80
117
|
export {};
|
|
81
118
|
//# sourceMappingURL=diff.d.ts.map
|
package/dist/diff.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"diff.d.ts","sourceRoot":"","sources":["../src/diff.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;
|
|
1
|
+
{"version":3,"file":"diff.d.ts","sourceRoot":"","sources":["../src/diff.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAS7E;;;;;;;GAOG;AACH,eAAO,MAAM,oBAAoB,QAAc,CAAC;AAkBhD;;;;;GAKG;AACH,UAAU,SAAS;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,EAAE,CAAC;CACjB;AA0BD,0DAA0D;AAC1D,KAAK,UAAU,GAAG,QAAQ,GAAG,QAAQ,CAAC;AAQtC;;;GAGG;AACH,MAAM,MAAM,SAAS,GAAG,KAAK,GAAG,IAAI,CAAC;AAErC;;;;GAIG;AACH,KAAK,aAAa,GAAG,KAAK,GAAG,UAAU,CAAC;AAKxC;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAsB,mBAAmB,CACvC,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC9B,GAAG,CAAC,EAAE,MAAM,EACZ,IAAI,GAAE,SAAiB,GACtB,OAAO,CAAC,eAAe,EAAE,GAAG,SAAS,CAAC,CAoExC;AA0CD;;;;;;;;;;GAUG;AACH,wBAAsB,+BAA+B,CACnD,YAAY,EAAE,OAAO,EACrB,IAAI,GAAE,SAAiB,GACtB,OAAO,CAAC;IAAE,OAAO,EAAE,eAAe,EAAE,CAAC;IAAC,SAAS,EAAE,gBAAgB,EAAE,CAAA;CAAE,GAAG,SAAS,CAAC,CA0CpF;AAED;;;;;;GAMG;AACH,wBAAgB,8BAA8B,CAAC,YAAY,EAAE,OAAO,GAAG;IACrE,OAAO,CAAC,EAAE,eAAe,EAAE,CAAC;IAC5B,SAAS,CAAC,EAAE,gBAAgB,EAAE,CAAC;CAChC,CAoEA;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,4BAA4B,CAAC,YAAY,EAAE,OAAO,GAAG,OAAO,CAAC;IACjF,OAAO,CAAC,EAAE,eAAe,EAAE,CAAC;IAC5B,SAAS,CAAC,EAAE,gBAAgB,EAAE,CAAC;CAChC,CAAC,CAgCD;AAED;;;;;;GAMG;AACH,wBAAgB,YAAY,CAC1B,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,UAAU,EAClB,KAAK,EAAE,SAAS,EAAE,EAClB,KAAK,GAAE,aAAqB,GAC3B,MAAM,CAMR;AA2OD;;;;;;;;GAQG;AACH,wBAAgB,aAAa,CAC3B,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,UAAU,EAClB,KAAK,CAAC,EAAE,SAAS,EAAE,GAClB,eAAe,CAajB"}
|