@agentclientprotocol/claude-agent-acp 0.90.1-preview.9 → 0.91.1-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.
- package/README.md +14 -5
- package/dist/acp-agent.d.ts +94 -11
- package/dist/acp-agent.d.ts.map +1 -1
- package/dist/acp-agent.js +246 -76
- package/dist/air-extension.d.ts +6 -0
- package/dist/air-extension.d.ts.map +1 -1
- package/dist/air-extension.js +6 -0
- package/dist/file-change-audit.d.ts +17 -0
- package/dist/file-change-audit.d.ts.map +1 -1
- package/dist/file-change-audit.js +62 -20
- package/dist/gateway-models.d.ts +62 -0
- package/dist/gateway-models.d.ts.map +1 -0
- package/dist/gateway-models.js +180 -0
- package/dist/native-subagents.d.ts +34 -9
- package/dist/native-subagents.d.ts.map +1 -1
- package/dist/native-subagents.js +55 -11
- package/dist/session-index/connection.d.ts +4 -3
- package/dist/session-index/connection.d.ts.map +1 -1
- package/dist/session-index/connection.js +8 -7
- package/dist/session-index/list-subscriptions.d.ts.map +1 -1
- package/dist/session-index/list-subscriptions.js +4 -1
- package/dist/session-index/service.d.ts +10 -0
- package/dist/session-index/service.d.ts.map +1 -1
- package/dist/session-index/service.js +21 -0
- package/dist/session-index/session-index.d.ts +10 -2
- package/dist/session-index/session-index.d.ts.map +1 -1
- package/dist/session-index/session-index.js +21 -5
- package/dist/session-index/session-info.d.ts.map +1 -1
- package/dist/session-index/session-info.js +1 -0
- package/dist/session-index/transcript-scan.d.ts +25 -1
- package/dist/session-index/transcript-scan.d.ts.map +1 -1
- package/dist/session-index/transcript-scan.js +57 -1
- package/dist/session-index/worktrees.d.ts +6 -0
- package/dist/session-index/worktrees.d.ts.map +1 -1
- package/dist/session-index/worktrees.js +12 -0
- package/dist/session-model.d.ts +21 -1
- package/dist/session-model.d.ts.map +1 -1
- package/dist/session-model.js +89 -11
- package/dist/turn-events.d.ts +5 -1
- package/dist/turn-events.d.ts.map +1 -1
- package/dist/v2/prompt.d.ts +2 -1
- package/dist/v2/prompt.d.ts.map +1 -1
- package/dist/v2/prompt.js +2 -1
- package/package.json +3 -3
package/dist/acp-agent.js
CHANGED
|
@@ -28,7 +28,7 @@ import { decodeClaudePermissionResponse } from "./permissions/response.js";
|
|
|
28
28
|
import { SettingsManager } from "./settings.js";
|
|
29
29
|
import { activeUsageLimitMessage, airSessionFailureCapabilityMeta, assistantMessageText, createSessionFailureState, isSyntheticUsageLimitMessage, providerFailureCategory, SessionFailureController, sessionFailureMeta, supportsAirSessionFailures, } from "./session-failure-extension.js";
|
|
30
30
|
import { billsClaudeSubscription, claudeLoginRequiredError, claudeSubscriptionNotSupportedError, holdsNonSubscriptionCredential, refuseClaudeSubscriptionTurn, shouldHideClaudeAuth, warnClaudeSubscriptionGuardDegraded, } from "./hide-claude-auth.js";
|
|
31
|
-
import { AGENT_FILE_CHANGE_REPORT_CAPABILITY, agentFileChangeReportMeta, createNativeFileChangeReporter, supportsAgentFileChangeReport, } from "./file-change-audit.js";
|
|
31
|
+
import { AGENT_FILE_CHANGE_REPORT_CAPABILITY, agentFileChangeReportMeta, createNativeFileChangeReporter, recordSubagentFileEdits, supportsAgentFileChangeReport, } from "./file-change-audit.js";
|
|
32
32
|
import { ContextCompactionLifecycle, clientSupportsCompactionUpdates, contextCompactionMetadataFromBoundary, isCompactSummaryMessage, } from "./context-compaction.js";
|
|
33
33
|
import { clientSupportsNotices, MAX_NOTICE_TITLE_LENGTH, normalizeNoticeText, noticeOrTranscriptUpdate, sentenceCase, splitNoticeText, } from "./session-notices.js";
|
|
34
34
|
import { applyTaskCreate, applyTaskList, applyTaskUpdate, clearHookCallbacks, completeHookCallback, createPostToolUseHook, hasHookCallback, createTaskHook, parseTaskCreateOutput, parseTaskListOutput, parseTaskUpdateOutput, planEntries, registerHookCallback, changedTaskPlanEntries, forgetPublishedTaskPlan, unregisterHookCallback, } from "./tools.js";
|
|
@@ -47,7 +47,8 @@ import { formatUsageResponse, isUsageCommandText, parseUsageResponse } from "./u
|
|
|
47
47
|
export { DEFAULT_AGENT_ID } from "./session-config-ids.js";
|
|
48
48
|
import { MCP_AVAILABLE_COMMAND, parseMcpCommand, runMcpCommand } from "./mcp-command.js";
|
|
49
49
|
import { MODE_CONFIG_ID, resolveInitialPermissionMode, SessionModeManager, } from "./session-mode.js";
|
|
50
|
-
import { applyAvailableModelsAllowlist, buildModelConfigOption, getAvailableModels, MODEL_CONFIG_ID, resolveModelPreference, } from "./session-model.js";
|
|
50
|
+
import { applyAvailableModelsAllowlist, buildModelConfigOption, getAvailableModels, MODEL_CONFIG_ID, narrowToGatewayModels, resolveModelPreference, } from "./session-model.js";
|
|
51
|
+
import { GatewayListingError, listBedrockModels, listGatewayModels, PROVIDER_AUTH_TOKEN_PLACEHOLDER, selectBedrockRegion, } from "./gateway-models.js";
|
|
51
52
|
import { buildEffortConfigOption, EFFORT_CONFIG_ID, effortFlagSettings, mergeEffortSettings, settingsEffortForModel, } from "./session-effort.js";
|
|
52
53
|
export { EFFORT_CONFIG_ID, settingsEffortForModel } from "./session-effort.js";
|
|
53
54
|
export { applyAvailableModelsAllowlist, matchResumedModel, MODEL_CONFIG_ID, resolveModelPreference, } from "./session-model.js";
|
|
@@ -1437,7 +1438,7 @@ export class ClaudeAcpAgent {
|
|
|
1437
1438
|
};
|
|
1438
1439
|
}
|
|
1439
1440
|
async newSession(params) {
|
|
1440
|
-
|
|
1441
|
+
while (this.providerUpdate)
|
|
1441
1442
|
await this.providerUpdate;
|
|
1442
1443
|
const response = await this.createSession(params, {
|
|
1443
1444
|
// Revisit these meta values once we support resume
|
|
@@ -1504,7 +1505,7 @@ export class ClaudeAcpAgent {
|
|
|
1504
1505
|
* later load or resume with the same settings reuses it.
|
|
1505
1506
|
*/
|
|
1506
1507
|
async unstable_forkSession(params) {
|
|
1507
|
-
|
|
1508
|
+
while (this.providerUpdate)
|
|
1508
1509
|
await this.providerUpdate;
|
|
1509
1510
|
const { sessionId } = await forkSession(params, {
|
|
1510
1511
|
liveMessageIdToUuid: this.sessions[params.sessionId]?.messageIdToUuid,
|
|
@@ -1522,7 +1523,7 @@ export class ClaudeAcpAgent {
|
|
|
1522
1523
|
return { sessionId, modes, configOptions };
|
|
1523
1524
|
}
|
|
1524
1525
|
async resumeSession(params) {
|
|
1525
|
-
|
|
1526
|
+
while (this.providerUpdate)
|
|
1526
1527
|
await this.providerUpdate;
|
|
1527
1528
|
const result = await this.getOrCreateSession(params);
|
|
1528
1529
|
this.afterSetupResponse(params.sessionId, params.mcpServers ?? []);
|
|
@@ -1530,7 +1531,7 @@ export class ClaudeAcpAgent {
|
|
|
1530
1531
|
}
|
|
1531
1532
|
async loadSession(params) {
|
|
1532
1533
|
const timing = new SessionTiming(this.logger, "load", params.sessionId);
|
|
1533
|
-
|
|
1534
|
+
while (this.providerUpdate)
|
|
1534
1535
|
await this.providerUpdate;
|
|
1535
1536
|
let result;
|
|
1536
1537
|
if (this.sessions[params.sessionId]) {
|
|
@@ -1912,6 +1913,42 @@ export class ClaudeAcpAgent {
|
|
|
1912
1913
|
// Unknown provider: idempotent success.
|
|
1913
1914
|
return {};
|
|
1914
1915
|
}
|
|
1916
|
+
/**
|
|
1917
|
+
* The model ids the gateway in `config` lists, read before `providers/set`
|
|
1918
|
+
* returns so the sessions it recreates already offer only those, and for
|
|
1919
|
+
* `bedrock` the region prefix picked from them. Setting the same gateway
|
|
1920
|
+
* again reuses the previous listing. `vertex` gateways are not listed.
|
|
1921
|
+
* Throws a {@link GatewayListingError} when the listing fails.
|
|
1922
|
+
*/
|
|
1923
|
+
async listProviderModels(config) {
|
|
1924
|
+
// Reuse needs the very same headers, so a rotated token lists again, and a
|
|
1925
|
+
// failed listing then fails that `providers/set`. Deliberate: AIR keeps its
|
|
1926
|
+
// proxy key for the IDE's lifetime and does not rotate it.
|
|
1927
|
+
const current = this.providerConfig;
|
|
1928
|
+
if (current?.listedModels &&
|
|
1929
|
+
current.apiType === config.apiType &&
|
|
1930
|
+
current.baseUrl === config.baseUrl &&
|
|
1931
|
+
sameHeaders(current.headers, config.headers)) {
|
|
1932
|
+
return {
|
|
1933
|
+
listedModels: current.listedModels,
|
|
1934
|
+
bedrockRegionPrefix: current.bedrockRegionPrefix,
|
|
1935
|
+
};
|
|
1936
|
+
}
|
|
1937
|
+
if (config.apiType === "anthropic") {
|
|
1938
|
+
return { listedModels: await listGatewayModels(config.baseUrl, config.headers, this.logger) };
|
|
1939
|
+
}
|
|
1940
|
+
if (config.apiType === "bedrock") {
|
|
1941
|
+
const modelIds = await listBedrockModels(config.baseUrl, config.headers, this.logger);
|
|
1942
|
+
if (!modelIds)
|
|
1943
|
+
return {};
|
|
1944
|
+
const region = selectBedrockRegion(modelIds);
|
|
1945
|
+
if (region.modelIds.length < modelIds.length) {
|
|
1946
|
+
this.logger.log(`[providers/set] Bedrock models span several region prefixes; using ${region.regionPrefix} and dropping ${modelIds.length - region.modelIds.length} id(s) of other prefixes`);
|
|
1947
|
+
}
|
|
1948
|
+
return { listedModels: region.modelIds, bedrockRegionPrefix: region.regionPrefix };
|
|
1949
|
+
}
|
|
1950
|
+
return {};
|
|
1951
|
+
}
|
|
1915
1952
|
resolveProviderConfig() {
|
|
1916
1953
|
return this.providerConfig ?? gatewayRequestToProviderConfig(this.gatewayAuthRequest);
|
|
1917
1954
|
}
|
|
@@ -1945,7 +1982,9 @@ export class ClaudeAcpAgent {
|
|
|
1945
1982
|
// provider routing set via `providers/set`. Neither touches the on-disk
|
|
1946
1983
|
// credential store, so dropping these references is the whole logout for
|
|
1947
1984
|
// those paths.
|
|
1948
|
-
|
|
1985
|
+
// A queued `providers/set` may still be listing and apply after this point,
|
|
1986
|
+
// so a busy queue counts as an override to clear.
|
|
1987
|
+
const hadRoutingOverride = this.resolveProviderConfig() !== null || this.providerUpdate !== null;
|
|
1949
1988
|
this.gatewayAuthRequest = undefined;
|
|
1950
1989
|
this.providerConfig = undefined;
|
|
1951
1990
|
// Any probe already running read the pre-logout world; the bump makes its
|
|
@@ -2050,7 +2089,7 @@ export class ClaudeAcpAgent {
|
|
|
2050
2089
|
* before this resolves.
|
|
2051
2090
|
*/
|
|
2052
2091
|
async startTurn(params, events) {
|
|
2053
|
-
|
|
2092
|
+
while (this.providerUpdate)
|
|
2054
2093
|
await this.providerUpdate;
|
|
2055
2094
|
let session = this.sessions[params.sessionId];
|
|
2056
2095
|
if (!session) {
|
|
@@ -2227,34 +2266,13 @@ export class ClaudeAcpAgent {
|
|
|
2227
2266
|
// husk that reached this by another route still releases its resources.
|
|
2228
2267
|
this.closeQueryStream(session);
|
|
2229
2268
|
try {
|
|
2230
|
-
//
|
|
2231
|
-
//
|
|
2232
|
-
await this.
|
|
2233
|
-
resume: sessionId,
|
|
2269
|
+
// The very first turn may be the one that signed out, so the CLI may
|
|
2270
|
+
// never have written the conversation.
|
|
2271
|
+
await this.recreateLiveSession(creationParams, sessionId, {
|
|
2234
2272
|
permissionMode: session.modes.currentModeId,
|
|
2235
2273
|
});
|
|
2236
2274
|
}
|
|
2237
2275
|
catch (error) {
|
|
2238
|
-
if (error instanceof RequestError && error.code === RequestError.resourceNotFound().code) {
|
|
2239
|
-
// The CLI never wrote this conversation, because the very first turn
|
|
2240
|
-
// was the one that signed out. Resuming it fails for ever, so start a
|
|
2241
|
-
// fresh query under the same ACP session id: an empty history is a far
|
|
2242
|
-
// better answer than a session the client can never use again.
|
|
2243
|
-
this.logger.log(`session ${sessionId} was never persisted; starting a fresh query under the same id`);
|
|
2244
|
-
try {
|
|
2245
|
-
await this.createSession(creationParams, {
|
|
2246
|
-
reuseSessionId: sessionId,
|
|
2247
|
-
permissionMode: session.modes.currentModeId,
|
|
2248
|
-
});
|
|
2249
|
-
return;
|
|
2250
|
-
}
|
|
2251
|
-
catch (fallbackError) {
|
|
2252
|
-
if (!this.sessions[sessionId]) {
|
|
2253
|
-
this.sessions[sessionId] = session;
|
|
2254
|
-
}
|
|
2255
|
-
throw fallbackError;
|
|
2256
|
-
}
|
|
2257
|
-
}
|
|
2258
2276
|
// Keep the husk addressable: the client answers the refusal with its own
|
|
2259
2277
|
// auth flow and then retries this session.
|
|
2260
2278
|
if (!this.sessions[sessionId]) {
|
|
@@ -2263,6 +2281,31 @@ export class ClaudeAcpAgent {
|
|
|
2263
2281
|
throw error;
|
|
2264
2282
|
}
|
|
2265
2283
|
}
|
|
2284
|
+
/**
|
|
2285
|
+
* Starts a new query for the session `sessionId`, which ran on this
|
|
2286
|
+
* connection and whose query is gone: it resumes the stored conversation.
|
|
2287
|
+
* `resume` names the Claude session, which shares the ACP session id, so the
|
|
2288
|
+
* new query continues the same conversation under the same id. Claude Code
|
|
2289
|
+
* writes the conversation at the first prompt, so resuming a session that was
|
|
2290
|
+
* never prompted fails with `resourceNotFound`, and keeps failing. Such a
|
|
2291
|
+
* session starts a fresh query under the same id instead: it has no history
|
|
2292
|
+
* to lose, and the client keeps a session it can use.
|
|
2293
|
+
*/
|
|
2294
|
+
async recreateLiveSession(params, sessionId, options) {
|
|
2295
|
+
try {
|
|
2296
|
+
return await this.createSession(params, { resume: sessionId, ...options });
|
|
2297
|
+
}
|
|
2298
|
+
catch (error) {
|
|
2299
|
+
if (!(error instanceof RequestError && error.code === RequestError.resourceNotFound().code)) {
|
|
2300
|
+
throw error;
|
|
2301
|
+
}
|
|
2302
|
+
this.logger.log(`session ${sessionId} was never persisted; starting a fresh query under the same id`);
|
|
2303
|
+
return await this.createSession(params, {
|
|
2304
|
+
reuseSessionId: sessionId,
|
|
2305
|
+
permissionMode: options.permissionMode,
|
|
2306
|
+
});
|
|
2307
|
+
}
|
|
2308
|
+
}
|
|
2266
2309
|
/** Run the `--hide-claude-auth` guard before a turn starts. The returned
|
|
2267
2310
|
* promise rejects with the `authRequired` error when a claude.ai
|
|
2268
2311
|
* subscription would pay, or when the account holds no credential this
|
|
@@ -3055,6 +3098,7 @@ export class ClaudeAcpAgent {
|
|
|
3055
3098
|
session.liveBackgroundTasks.set(taskId, {
|
|
3056
3099
|
parentToolUseId,
|
|
3057
3100
|
isSubagent,
|
|
3101
|
+
...(placement.taskType !== undefined ? { taskType: placement.taskType } : {}),
|
|
3058
3102
|
...(placement.backgrounded !== undefined ? { backgrounded: placement.backgrounded } : {}),
|
|
3059
3103
|
...(placement.parentTaskId !== undefined ? { parentTaskId: placement.parentTaskId } : {}),
|
|
3060
3104
|
});
|
|
@@ -3295,27 +3339,46 @@ export class ClaudeAcpAgent {
|
|
|
3295
3339
|
await sendUpdate(notification);
|
|
3296
3340
|
}
|
|
3297
3341
|
};
|
|
3298
|
-
/**
|
|
3299
|
-
*
|
|
3300
|
-
*
|
|
3301
|
-
* `closeCancelledToolCalls`
|
|
3302
|
-
*
|
|
3303
|
-
*
|
|
3304
|
-
*
|
|
3305
|
-
*
|
|
3306
|
-
*
|
|
3307
|
-
* cycle
|
|
3308
|
-
*
|
|
3309
|
-
*
|
|
3310
|
-
*
|
|
3311
|
-
|
|
3312
|
-
|
|
3342
|
+
/** The model cycle that Claude Code started on its own ends, and its end is
|
|
3343
|
+
* about to be reported: closes the tool calls that it left open first. A
|
|
3344
|
+
* cycle is foreground work that no turn settles, so neither
|
|
3345
|
+
* `closeCancelledToolCalls` nor the check of `settleActive` for unfinished
|
|
3346
|
+
* tools runs for it. A turn that took the cycle over closes its own calls,
|
|
3347
|
+
* when it settles.
|
|
3348
|
+
*
|
|
3349
|
+
* After a cancel, Claude Code's interrupt gives the tools of the main
|
|
3350
|
+
* conversation results, which `sendInterruptedToolResults` delivers while
|
|
3351
|
+
* the cycle runs. What is still open has none, such as the command of a
|
|
3352
|
+
* foreground subagent. The follow-up of a turn that v1 holds for its
|
|
3353
|
+
* background subagents is a cycle too, and the cancel ends the held turn
|
|
3354
|
+
* as well, possibly in `cancelTurns` while these reports are in flight. So
|
|
3355
|
+
* the cycle's calls close with the held turn's closing, which each settle
|
|
3356
|
+
* of the turn waits for, and the response never comes before them.
|
|
3357
|
+
*
|
|
3358
|
+
* At any other end, every call that ran has its result. What is open is a
|
|
3359
|
+
* call of the main conversation that Claude abandoned before it ran, such
|
|
3360
|
+
* as a streamed tool_use that never reached a complete message, which a
|
|
3361
|
+
* turn's end closes the same way (`closeUnfinished`). The calls of a
|
|
3362
|
+
* subagent are not the cycle's: a background subagent runs on. */
|
|
3363
|
+
const closeCycleToolCalls = async () => {
|
|
3364
|
+
if (!this.runsAutonomousCycle(params.sessionId))
|
|
3365
|
+
return;
|
|
3366
|
+
if (session.cancelled) {
|
|
3367
|
+
const held = session.activeTurn;
|
|
3368
|
+
if (held && !held.settled)
|
|
3369
|
+
await closeCancelledToolCalls(held);
|
|
3370
|
+
else
|
|
3371
|
+
await closeOpenToolCalls(closedAtCancel);
|
|
3313
3372
|
return;
|
|
3314
|
-
|
|
3315
|
-
|
|
3316
|
-
|
|
3317
|
-
|
|
3318
|
-
|
|
3373
|
+
}
|
|
3374
|
+
const renderer = new AcpToolCallRenderer(this.toolCallCapabilities);
|
|
3375
|
+
for (const toolCallId of [...session.emittedToolCalls]) {
|
|
3376
|
+
if (session.toolCallParents?.has(toolCallId))
|
|
3377
|
+
continue;
|
|
3378
|
+
if (session.dispatchedToolCalls?.has(toolCallId))
|
|
3379
|
+
continue;
|
|
3380
|
+
await closeToolCall(toolCallId, renderer.unfinished({ toolCallId, ran: false }));
|
|
3381
|
+
}
|
|
3319
3382
|
};
|
|
3320
3383
|
/** At the actual turn boundary, preview its checkpoint, settle the active
|
|
3321
3384
|
* turn exactly once, disarm the force-cancel backstop, and drop it from
|
|
@@ -3966,7 +4029,7 @@ export class ClaudeAcpAgent {
|
|
|
3966
4029
|
// here. An owed idle belongs to an earlier result: it can lag
|
|
3967
4030
|
// past the cycle's first output.
|
|
3968
4031
|
if (session.owedTrailingIdles === 0) {
|
|
3969
|
-
await
|
|
4032
|
+
await closeCycleToolCalls();
|
|
3970
4033
|
this.endAutonomousCycle(params.sessionId, {
|
|
3971
4034
|
outcome: { stopReason: session.cancelled ? "cancelled" : "end_turn" },
|
|
3972
4035
|
});
|
|
@@ -4271,6 +4334,7 @@ export class ClaudeAcpAgent {
|
|
|
4271
4334
|
registerLiveTask(message.task_id, message.tool_use_id, !!message.subagent_type, {
|
|
4272
4335
|
backgrounded: message.is_backgrounded,
|
|
4273
4336
|
parentTaskId: message.parent_task_id,
|
|
4337
|
+
taskType: message.task_type,
|
|
4274
4338
|
});
|
|
4275
4339
|
await subagents.taskStarted({
|
|
4276
4340
|
taskId: message.task_id,
|
|
@@ -4789,7 +4853,7 @@ export class ClaudeAcpAgent {
|
|
|
4789
4853
|
pendingExitPlanContextReset?.toolUseId ===
|
|
4790
4854
|
pendingExitPlanModeInterruption?.toolUseId;
|
|
4791
4855
|
if (!continuesPlan && !(isAutonomousResult && message.num_turns === 0)) {
|
|
4792
|
-
await
|
|
4856
|
+
await closeCycleToolCalls();
|
|
4793
4857
|
this.endAutonomousCycle(params.sessionId, autonomousCycleEnd(message, resultModelUsage, session.cancelled || exitPlanInterruption || isAbortedResult(message)));
|
|
4794
4858
|
}
|
|
4795
4859
|
if (session.cancelled) {
|
|
@@ -5609,6 +5673,7 @@ export class ClaudeAcpAgent {
|
|
|
5609
5673
|
let runningTerminal;
|
|
5610
5674
|
if (message.type === "user") {
|
|
5611
5675
|
rememberResolvedToolNames(session, content);
|
|
5676
|
+
recordSubagentFileEdits(session.activeTurn, message.parent_tool_use_id, content, session.toolUseCache);
|
|
5612
5677
|
const backgroundBashTask = backgroundBashTaskFromToolResult(content, message.tool_use_result, session.toolUseCache);
|
|
5613
5678
|
if (backgroundBashTask)
|
|
5614
5679
|
await asyncTasks.taskBackgrounded(backgroundBashTask);
|
|
@@ -5875,8 +5940,46 @@ export class ClaudeAcpAgent {
|
|
|
5875
5940
|
}
|
|
5876
5941
|
}
|
|
5877
5942
|
async cancel(params) {
|
|
5943
|
+
if (!this.sessions[params.sessionId] && (await this.cancelChildSession(params.sessionId))) {
|
|
5944
|
+
return;
|
|
5945
|
+
}
|
|
5878
5946
|
await this.cancelTurns(params, { awaitInterrupt: true });
|
|
5879
5947
|
}
|
|
5948
|
+
/**
|
|
5949
|
+
* Cancels the current work of the subagent child session `sessionId`, which
|
|
5950
|
+
* its `cancel` capability permits on the subagents RFD form, without
|
|
5951
|
+
* cancelling its parent (see `NativeSubagentRuntime.cancelChild`). Returns
|
|
5952
|
+
* false when no session has such a child.
|
|
5953
|
+
*/
|
|
5954
|
+
async cancelChildSession(sessionId) {
|
|
5955
|
+
for (const [rootSessionId, session] of Object.entries(this.sessions)) {
|
|
5956
|
+
const cancelled = await session.nativeSubagentRuntime?.cancelChild(sessionId, (taskId) => session.query.stopTask(taskId).catch((error) => {
|
|
5957
|
+
this.logger.error(`Session ${rootSessionId}: failed to stop the task ${taskId} of subagent session ${sessionId}`, error);
|
|
5958
|
+
}));
|
|
5959
|
+
if (cancelled)
|
|
5960
|
+
return true;
|
|
5961
|
+
}
|
|
5962
|
+
return false;
|
|
5963
|
+
}
|
|
5964
|
+
/**
|
|
5965
|
+
* Stops each background workflow of the session that still runs, after the
|
|
5966
|
+
* interrupt of a `session/cancel` spared it (see
|
|
5967
|
+
* `Session.stopsWorkflowsOnCancel`). Claude Code reports each one
|
|
5968
|
+
* `stopped`, along with the commands inside it, and starts no model cycle
|
|
5969
|
+
* for it, as when the interrupt killed it. Every background workflow is
|
|
5970
|
+
* stopped, whoever launched it, because the interrupt killed them all.
|
|
5971
|
+
*/
|
|
5972
|
+
stopBackgroundWorkflows(sessionId, session) {
|
|
5973
|
+
if (!session.stopsWorkflowsOnCancel)
|
|
5974
|
+
return;
|
|
5975
|
+
for (const [taskId, task] of session.liveBackgroundTasks) {
|
|
5976
|
+
if (task.taskType !== "local_workflow")
|
|
5977
|
+
continue;
|
|
5978
|
+
session.query.stopTask(taskId).catch((error) => {
|
|
5979
|
+
this.logger.error(`Session ${sessionId}: failed to stop the background workflow ${taskId}`, error);
|
|
5980
|
+
});
|
|
5981
|
+
}
|
|
5982
|
+
}
|
|
5880
5983
|
/** Cancel the session's turns and interrupt the SDK query. With
|
|
5881
5984
|
* `awaitInterrupt: false` the interrupt is sent, but its reply is not
|
|
5882
5985
|
* awaited. `teardownSession` uses that: it closes the query right after, and
|
|
@@ -5889,6 +5992,10 @@ export class ClaudeAcpAgent {
|
|
|
5889
5992
|
return;
|
|
5890
5993
|
}
|
|
5891
5994
|
session.cancelled = true;
|
|
5995
|
+
// The interrupt below makes Claude Code withdraw the requests that are open
|
|
5996
|
+
// now (see `withPendingUserInput`).
|
|
5997
|
+
for (const input of session.openUserInputs ?? [])
|
|
5998
|
+
input.cancelled = true;
|
|
5892
5999
|
// Before anything awaits, so a model request that the consumer reads in
|
|
5893
6000
|
// the meantime is already judged against these prompts.
|
|
5894
6001
|
session.cancelledPrompts ??= new Set();
|
|
@@ -6157,6 +6264,7 @@ export class ClaudeAcpAgent {
|
|
|
6157
6264
|
Promise.resolve(interrupt).catch(() => { });
|
|
6158
6265
|
return;
|
|
6159
6266
|
}
|
|
6267
|
+
this.stopBackgroundWorkflows(params.sessionId, session);
|
|
6160
6268
|
const receipt = await interrupt;
|
|
6161
6269
|
// On CLIs advertising `interrupt_receipt_v1`, the receipt's `still_queued`
|
|
6162
6270
|
// lists exactly which queued messages survive the interrupt and will still
|
|
@@ -6829,8 +6937,17 @@ export class ClaudeAcpAgent {
|
|
|
6829
6937
|
* conversation) as awaiting user input for exactly the lifetime of its
|
|
6830
6938
|
* promise (see `Session.openUserInputs`). Steering consults the open
|
|
6831
6939
|
* requests synchronously, so a message arriving while any permission or
|
|
6832
|
-
* elicitation card is open uses non-interrupting SDK delivery.
|
|
6833
|
-
|
|
6940
|
+
* elicitation card is open uses non-interrupting SDK delivery.
|
|
6941
|
+
*
|
|
6942
|
+
* `signal` aborts when Claude Code withdraws the request, which is not an
|
|
6943
|
+
* answer. Example: the user cancels while a permission request is open.
|
|
6944
|
+
* Claude Code's interrupt withdraws it as it stops the work, and the work
|
|
6945
|
+
* ends `idle cancelled` right after. The end of the request then reports
|
|
6946
|
+
* no `running`: the client would see `requires_action`, `running`, `idle
|
|
6947
|
+
* cancelled`. A withdrawal without a cancel means that something else
|
|
6948
|
+
* answered the request in the user's place, such as a `PermissionRequest`
|
|
6949
|
+
* hook, and the work goes on, so the end reports `running`. */
|
|
6950
|
+
async withPendingUserInput(sessionId, signal, request, agentID) {
|
|
6834
6951
|
const session = this.sessions[sessionId];
|
|
6835
6952
|
if (!session)
|
|
6836
6953
|
return request();
|
|
@@ -6842,7 +6959,8 @@ export class ClaudeAcpAgent {
|
|
|
6842
6959
|
}
|
|
6843
6960
|
finally {
|
|
6844
6961
|
session.openUserInputs.delete(input);
|
|
6845
|
-
|
|
6962
|
+
const withdrawnByCancel = signal.aborted && input.cancelled === true;
|
|
6963
|
+
this.syncAwaitingUser(sessionId, session, withdrawnByCancel);
|
|
6846
6964
|
}
|
|
6847
6965
|
}
|
|
6848
6966
|
/** Report whether the session's foreground work awaits the user: exactly
|
|
@@ -6851,8 +6969,13 @@ export class ClaudeAcpAgent {
|
|
|
6851
6969
|
* and Claude Code can ask for a queued prompt before the consumer activates
|
|
6852
6970
|
* it, so a request is not tied to the work that was running when it
|
|
6853
6971
|
* opened. Called when a request opens or closes, when a turn activates, and
|
|
6854
|
-
* when a task registers or moves to the background.
|
|
6855
|
-
|
|
6972
|
+
* when a task registers or moves to the background.
|
|
6973
|
+
*
|
|
6974
|
+
* When the last request ends, the work reports `running` again, unless a
|
|
6975
|
+
* cancel withdrew that request (`withdrawnByCancel`, see
|
|
6976
|
+
* {@link withPendingUserInput}): the work is being stopped, and reports its
|
|
6977
|
+
* end next. */
|
|
6978
|
+
syncAwaitingUser(sessionId, session, withdrawnByCancel = false) {
|
|
6856
6979
|
const work = this.foregroundWork.get(sessionId);
|
|
6857
6980
|
if (!work)
|
|
6858
6981
|
return;
|
|
@@ -6862,7 +6985,7 @@ export class ClaudeAcpAgent {
|
|
|
6862
6985
|
work.awaitingUser = waiting;
|
|
6863
6986
|
if (waiting)
|
|
6864
6987
|
work.events.awaitingUser();
|
|
6865
|
-
else
|
|
6988
|
+
else if (!withdrawnByCancel)
|
|
6866
6989
|
work.events.running();
|
|
6867
6990
|
}
|
|
6868
6991
|
/** Make `owner` the foreground work of the session `sessionId` (see
|
|
@@ -7017,7 +7140,7 @@ export class ClaudeAcpAgent {
|
|
|
7017
7140
|
// The request goes to a subagent's child session for a tool call of that
|
|
7018
7141
|
// subagent, but it blocks the turn of the owner session.
|
|
7019
7142
|
try {
|
|
7020
|
-
return await this.withChildAwaitingUser(ownerSessionId, params.sessionId, signal, () => this.withPendingUserInput(ownerSessionId, () => raceWithAbort(this.client.requestPermission(params, signal), signal), agentID));
|
|
7143
|
+
return await this.withChildAwaitingUser(ownerSessionId, params.sessionId, signal, () => this.withPendingUserInput(ownerSessionId, signal, () => raceWithAbort(this.client.requestPermission(params, signal), signal), agentID));
|
|
7021
7144
|
}
|
|
7022
7145
|
catch (error) {
|
|
7023
7146
|
if (signal.aborted) {
|
|
@@ -7349,7 +7472,7 @@ export class ClaudeAcpAgent {
|
|
|
7349
7472
|
return { action: "decline" };
|
|
7350
7473
|
}
|
|
7351
7474
|
try {
|
|
7352
|
-
const response = await this.withPendingUserInput(sessionId, () => this.elicitFromClient(createRequest, signal));
|
|
7475
|
+
const response = await this.withPendingUserInput(sessionId, signal, () => this.elicitFromClient(createRequest, signal));
|
|
7353
7476
|
if (signal.aborted) {
|
|
7354
7477
|
return { action: "cancel" };
|
|
7355
7478
|
}
|
|
@@ -7381,7 +7504,7 @@ export class ClaudeAcpAgent {
|
|
|
7381
7504
|
const createRequest = askUserQuestionsToCreateRequest(questions, requestSessionId, toolUseID, this.toolCallCapabilities.air.client);
|
|
7382
7505
|
let response;
|
|
7383
7506
|
try {
|
|
7384
|
-
response = await this.withChildAwaitingUser(sessionId, requestSessionId, signal, () => this.withPendingUserInput(sessionId, () => this.elicitFromClient(createRequest, signal), agentID));
|
|
7507
|
+
response = await this.withChildAwaitingUser(sessionId, requestSessionId, signal, () => this.withPendingUserInput(sessionId, signal, () => this.elicitFromClient(createRequest, signal), agentID));
|
|
7385
7508
|
}
|
|
7386
7509
|
catch (error) {
|
|
7387
7510
|
// A cancellation we requested (signal aborted) settles as an aborted tool
|
|
@@ -7421,7 +7544,7 @@ export class ClaudeAcpAgent {
|
|
|
7421
7544
|
}
|
|
7422
7545
|
let response;
|
|
7423
7546
|
try {
|
|
7424
|
-
response = await this.withPendingUserInput(sessionId, () => this.elicitFromClient(refusalFallbackToCreateRequest(prompt, sessionId), signal));
|
|
7547
|
+
response = await this.withPendingUserInput(sessionId, signal, () => this.elicitFromClient(refusalFallbackToCreateRequest(prompt, sessionId), signal));
|
|
7425
7548
|
}
|
|
7426
7549
|
catch (error) {
|
|
7427
7550
|
// A cancellation we requested (signal aborted) is expected teardown;
|
|
@@ -7826,16 +7949,22 @@ export class ClaudeAcpAgent {
|
|
|
7826
7949
|
// up the new values.
|
|
7827
7950
|
await this.teardownSession(params.sessionId);
|
|
7828
7951
|
}
|
|
7829
|
-
const
|
|
7952
|
+
const sessionParams = {
|
|
7830
7953
|
cwd: params.cwd,
|
|
7831
7954
|
mcpServers: params.mcpServers ?? [],
|
|
7832
7955
|
additionalDirectories: params.additionalDirectories,
|
|
7833
7956
|
_meta: params._meta,
|
|
7834
|
-
}
|
|
7835
|
-
|
|
7957
|
+
};
|
|
7958
|
+
const creation = {
|
|
7836
7959
|
permissionMode: livePermissionMode,
|
|
7837
7960
|
...(resumedSession ? { resumedModelHint: resumedSession.model } : {}),
|
|
7838
|
-
}
|
|
7961
|
+
};
|
|
7962
|
+
// A live session may never have been prompted, so it may have no stored
|
|
7963
|
+
// conversation to resume (see `recreateLiveSession`). For a session that
|
|
7964
|
+
// is not loaded here, a missing conversation means an unknown session.
|
|
7965
|
+
const response = existingSession
|
|
7966
|
+
? await this.recreateLiveSession(sessionParams, params.sessionId, creation)
|
|
7967
|
+
: await this.createSession(sessionParams, { resume: params.sessionId, ...creation });
|
|
7839
7968
|
return {
|
|
7840
7969
|
sessionId: response.sessionId,
|
|
7841
7970
|
modes: response.modes,
|
|
@@ -8081,6 +8210,17 @@ export class ClaudeAcpAgent {
|
|
|
8081
8210
|
systemPrompt,
|
|
8082
8211
|
settingSources: ["user", "project", "local"],
|
|
8083
8212
|
...(thinking !== undefined && { thinking }),
|
|
8213
|
+
// A client on the subagents RFD form can stop one subagent with
|
|
8214
|
+
// `session/cancel` on its child session (see
|
|
8215
|
+
// `NativeSubagentRuntime.cancelChild`). Declaring that makes Claude
|
|
8216
|
+
// Code's interrupt spare background subagents, so they keep running
|
|
8217
|
+
// after a parent cancel, as the RFD prescribes
|
|
8218
|
+
// (agentclientprotocol/agent-client-protocol#2308). Without it, the
|
|
8219
|
+
// interrupt kills them. It spares background workflows too, which
|
|
8220
|
+
// `stopBackgroundWorkflows` stops instead. Background commands survive an
|
|
8221
|
+
// interrupt either way. Before `userProvidedOptions`, so a client's own
|
|
8222
|
+
// `perTaskStopAffordance` wins.
|
|
8223
|
+
...(subagentForm(this.clientCapabilities) === "rfd" ? { perTaskStopAffordance: true } : {}),
|
|
8084
8224
|
...userProvidedOptions,
|
|
8085
8225
|
// Claude Code uses the same checkpoint store for /rewind. Enable it only
|
|
8086
8226
|
// for clients that negotiated per-turn file-change reports; this avoids
|
|
@@ -8311,10 +8451,14 @@ export class ClaudeAcpAgent {
|
|
|
8311
8451
|
// configured. Managed `deniedModels` drops entries the CLI would refuse.
|
|
8312
8452
|
const settingsAvailableModels = settingsManager.getSettings().availableModels;
|
|
8313
8453
|
const settingsModelOverrides = settingsManager.getSettings().modelOverrides;
|
|
8314
|
-
const
|
|
8454
|
+
const settingsAllowedModels = Array.isArray(settingsAvailableModels)
|
|
8315
8455
|
? applyAvailableModelsAllowlist(initializationResult.models, settingsAvailableModels, settingsModelOverrides, settingsManager.getManagedDeniedModels())
|
|
8316
8456
|
: initializationResult.models;
|
|
8317
|
-
|
|
8457
|
+
// Then keep only the models the `providers/set` gateway listed.
|
|
8458
|
+
const allowedModels = resolvedProvider?.listedModels
|
|
8459
|
+
? narrowToGatewayModels(settingsAllowedModels, resolvedProvider.listedModels, resolvedProvider.bedrockRegionPrefix)
|
|
8460
|
+
: settingsAllowedModels;
|
|
8461
|
+
const models = await getAvailableModels(q, allowedModels, initializationResult.models, settingsManager, this.logger, creationOpts.resume !== undefined, sessionId, await resumedModelHint, resolvedProvider?.listedModels !== undefined);
|
|
8318
8462
|
timing.phase("models");
|
|
8319
8463
|
// Resolve the current model's capabilities separately from the stable
|
|
8320
8464
|
// permission-mode catalog advertised to ACP clients.
|
|
@@ -8472,6 +8616,8 @@ export class ClaudeAcpAgent {
|
|
|
8472
8616
|
emittedToolCalls: new Set(),
|
|
8473
8617
|
eagerToolCallSessions: new Map(),
|
|
8474
8618
|
liveBackgroundTasks: new Map(),
|
|
8619
|
+
stopsWorkflowsOnCancel: options.perTaskStopAffordance === true &&
|
|
8620
|
+
!clientSupportsAsyncTasks(this.clientCapabilities),
|
|
8475
8621
|
nativeSubagentsByTaskId: new Map(),
|
|
8476
8622
|
nativeSubagentTaskIdByToolUseId: new Map(),
|
|
8477
8623
|
nativeSubagentParentByToolUseId: new Map(),
|
|
@@ -8504,6 +8650,21 @@ export class ClaudeAcpAgent {
|
|
|
8504
8650
|
async enqueueProviderUpdate(config) {
|
|
8505
8651
|
const previous = this.providerUpdate?.catch(() => undefined) ?? Promise.resolve();
|
|
8506
8652
|
const update = previous.then(async () => {
|
|
8653
|
+
// The listing runs in the queue, so `providers/set`, `providers/disable`
|
|
8654
|
+
// and logout apply in the order they arrived. A failed listing fails this
|
|
8655
|
+
// `providers/set` before the provider replaces the current one.
|
|
8656
|
+
if (config) {
|
|
8657
|
+
try {
|
|
8658
|
+
Object.assign(config, await this.listProviderModels(config));
|
|
8659
|
+
}
|
|
8660
|
+
catch (error) {
|
|
8661
|
+
if (error instanceof GatewayListingError) {
|
|
8662
|
+
throw RequestError.internalError({ providerId: PROVIDER_ID, apiType: config.apiType, baseUrl: config.baseUrl }, `Model discovery for provider "${PROVIDER_ID}" failed: ${error.message}`);
|
|
8663
|
+
}
|
|
8664
|
+
throw error;
|
|
8665
|
+
}
|
|
8666
|
+
this.logger.log(`[providers/set] listedModels=${config.listedModels?.length ?? "none"} bedrockRegionPrefix=${config.bedrockRegionPrefix ?? "none"}`);
|
|
8667
|
+
}
|
|
8507
8668
|
const sessions = Object.entries(this.sessions);
|
|
8508
8669
|
const activeTurns = sessions.flatMap(([, session]) => (session.turnQueue ?? []).flatMap((turn) => (turn.completion ? [turn.completion] : [])));
|
|
8509
8670
|
if (activeTurns.length > 0) {
|
|
@@ -8948,9 +9109,12 @@ function createEnvForProvider(config) {
|
|
|
8948
9109
|
return {
|
|
8949
9110
|
...resetRouting,
|
|
8950
9111
|
CLAUDE_CODE_USE_BEDROCK: "1",
|
|
8951
|
-
AWS_BEARER_TOKEN_BEDROCK:
|
|
9112
|
+
AWS_BEARER_TOKEN_BEDROCK: PROVIDER_AUTH_TOKEN_PLACEHOLDER, // Bypass local AWS credential checks
|
|
8952
9113
|
ANTHROPIC_BEDROCK_BASE_URL: config.baseUrl,
|
|
8953
9114
|
ANTHROPIC_CUSTOM_HEADERS: customHeaders,
|
|
9115
|
+
...(config.bedrockRegionPrefix
|
|
9116
|
+
? { ANTHROPIC_BEDROCK_REGION_PREFIX: config.bedrockRegionPrefix }
|
|
9117
|
+
: {}),
|
|
8954
9118
|
};
|
|
8955
9119
|
}
|
|
8956
9120
|
if (config.apiType === "vertex") {
|
|
@@ -8975,9 +9139,13 @@ function createEnvForProvider(config) {
|
|
|
8975
9139
|
...resetRouting,
|
|
8976
9140
|
ANTHROPIC_BASE_URL: config.baseUrl,
|
|
8977
9141
|
ANTHROPIC_CUSTOM_HEADERS: customHeaders,
|
|
8978
|
-
ANTHROPIC_AUTH_TOKEN:
|
|
9142
|
+
ANTHROPIC_AUTH_TOKEN: PROVIDER_AUTH_TOKEN_PLACEHOLDER, // Bypass local Claude login checks
|
|
8979
9143
|
};
|
|
8980
9144
|
}
|
|
9145
|
+
function sameHeaders(a, b) {
|
|
9146
|
+
const aKeys = Object.keys(a);
|
|
9147
|
+
return aKeys.length === Object.keys(b).length && aKeys.every((key) => b[key] === a[key]);
|
|
9148
|
+
}
|
|
8981
9149
|
/**
|
|
8982
9150
|
* Validate a provider base URL: must be a non-empty absolute http(s) URL.
|
|
8983
9151
|
*/
|
|
@@ -9133,10 +9301,12 @@ export function resolveFastModeEnabled(params) {
|
|
|
9133
9301
|
throw new Error(`Invalid value for config option ${FAST_MODE_CONFIG_ID}: ${value}`);
|
|
9134
9302
|
}
|
|
9135
9303
|
export function buildConfigOptions(modes, models, modelInfos, currentEffortLevel, agents = [], currentAgent = DEFAULT_AGENT_ID, fastMode, presentation) {
|
|
9136
|
-
const options = [
|
|
9137
|
-
|
|
9138
|
-
|
|
9139
|
-
|
|
9304
|
+
const options = [SessionModeManager.configOption(modes)];
|
|
9305
|
+
// A gateway that lists none of the SDK's models leaves no model to offer, so
|
|
9306
|
+
// there is no model option at all.
|
|
9307
|
+
if (models.availableModels.length > 0) {
|
|
9308
|
+
options.push(buildModelConfigOption(models, modelInfos, presentation?.useRecommendedValue === true));
|
|
9309
|
+
}
|
|
9140
9310
|
const effort = buildEffortConfigOption(modelInfos, models.currentModelId, currentEffortLevel, presentation?.useRecommendedValue === true);
|
|
9141
9311
|
if (effort)
|
|
9142
9312
|
options.push(effort);
|
package/dist/air-extension.d.ts
CHANGED
|
@@ -34,6 +34,12 @@ export declare const AIR_SESSION_RENAME_CAPABILITY = "sessionRename";
|
|
|
34
34
|
* {@link AIR_SESSION_INDEX_CAPABILITY} is; the client does not declare it.
|
|
35
35
|
*/
|
|
36
36
|
export declare const AIR_SESSION_LIST_SUBSCRIBE_CAPABILITY = "sessionListSubscribe";
|
|
37
|
+
/**
|
|
38
|
+
* Session index rows carry `agentWorktree: true` when the session runs in a
|
|
39
|
+
* linked git worktree that Claude Code made for it. Advertised exactly when
|
|
40
|
+
* {@link AIR_SESSION_INDEX_CAPABILITY} is; the client does not declare it.
|
|
41
|
+
*/
|
|
42
|
+
export declare const AIR_SESSION_WORKTREES_CAPABILITY = "sessionWorktrees";
|
|
37
43
|
/** The `_meta.jetbrains.air` keys that the ACP tool call contract defines. */
|
|
38
44
|
export declare const AIR_COMMAND_TITLE_KEY = "commandTitle";
|
|
39
45
|
export declare const AIR_SUBAGENT_KEY = "subagent";
|
|
@@ -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,kCAAkC,uBAAuB,CAAC;AACvE,eAAO,MAAM,yBAAyB,cAAc,CAAC;AACrD,4EAA4E;AAC5E,eAAO,MAAM,kCAAkC,sBAAsB,CAAC;AACtE;;;GAGG;AACH,eAAO,MAAM,wBAAwB,aAAa,CAAC;AACnD;;;;GAIG;AACH,eAAO,MAAM,4BAA4B,iBAAiB,CAAC;AAC3D;;;;GAIG;AACH,eAAO,MAAM,8BAA8B,mBAAmB,CAAC;AAC/D;;;GAGG;AACH,eAAO,MAAM,6BAA6B,kBAAkB,CAAC;AAC7D;;;;GAIG;AACH,eAAO,MAAM,qCAAqC,yBAAyB,CAAC;
|
|
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,kCAAkC,uBAAuB,CAAC;AACvE,eAAO,MAAM,yBAAyB,cAAc,CAAC;AACrD,4EAA4E;AAC5E,eAAO,MAAM,kCAAkC,sBAAsB,CAAC;AACtE;;;GAGG;AACH,eAAO,MAAM,wBAAwB,aAAa,CAAC;AACnD;;;;GAIG;AACH,eAAO,MAAM,4BAA4B,iBAAiB,CAAC;AAC3D;;;;GAIG;AACH,eAAO,MAAM,8BAA8B,mBAAmB,CAAC;AAC/D;;;GAGG;AACH,eAAO,MAAM,6BAA6B,kBAAkB,CAAC;AAC7D;;;;GAIG;AACH,eAAO,MAAM,qCAAqC,yBAAyB,CAAC;AAC5E;;;;GAIG;AACH,eAAO,MAAM,gCAAgC,qBAAqB,CAAC;AAEnE,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;AAED,4DAA4D;AAC5D,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAIvE"}
|
package/dist/air-extension.js
CHANGED
|
@@ -34,6 +34,12 @@ export const AIR_SESSION_RENAME_CAPABILITY = "sessionRename";
|
|
|
34
34
|
* {@link AIR_SESSION_INDEX_CAPABILITY} is; the client does not declare it.
|
|
35
35
|
*/
|
|
36
36
|
export const AIR_SESSION_LIST_SUBSCRIBE_CAPABILITY = "sessionListSubscribe";
|
|
37
|
+
/**
|
|
38
|
+
* Session index rows carry `agentWorktree: true` when the session runs in a
|
|
39
|
+
* linked git worktree that Claude Code made for it. Advertised exactly when
|
|
40
|
+
* {@link AIR_SESSION_INDEX_CAPABILITY} is; the client does not declare it.
|
|
41
|
+
*/
|
|
42
|
+
export const AIR_SESSION_WORKTREES_CAPABILITY = "sessionWorktrees";
|
|
37
43
|
/** The `_meta.jetbrains.air` keys that the ACP tool call contract defines. */
|
|
38
44
|
export const AIR_COMMAND_TITLE_KEY = "commandTitle";
|
|
39
45
|
export const AIR_SUBAGENT_KEY = "subagent";
|