@band-ai/sdk 0.3.0 → 0.3.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/dist/adapters.cjs +68 -31
- package/dist/adapters.d.cts +11 -4
- package/dist/adapters.d.ts +11 -4
- package/dist/adapters.js +68 -31
- package/package.json +1 -1
package/dist/adapters.cjs
CHANGED
|
@@ -2167,8 +2167,8 @@ var ACPClientAdapter = class extends SimpleAdapter {
|
|
|
2167
2167
|
bootstrappedSessions = /* @__PURE__ */ new Set();
|
|
2168
2168
|
pendingPermissions = /* @__PURE__ */ new Map();
|
|
2169
2169
|
resolvePermission;
|
|
2170
|
+
resolveSessionMode;
|
|
2170
2171
|
permissionTimeoutMs;
|
|
2171
|
-
requestedPermissionMode;
|
|
2172
2172
|
logger;
|
|
2173
2173
|
backend = null;
|
|
2174
2174
|
backendPromise = null;
|
|
@@ -2197,13 +2197,10 @@ var ACPClientAdapter = class extends SimpleAdapter {
|
|
|
2197
2197
|
this.clientCapabilities = options.clientCapabilities;
|
|
2198
2198
|
this.connectionFactory = options.connectionFactory ?? createSubprocessConnection;
|
|
2199
2199
|
this.resolvePermission = options.resolvePermission;
|
|
2200
|
+
this.resolveSessionMode = options.resolveSessionMode;
|
|
2200
2201
|
this.logger = options.logger ?? new NoopLogger();
|
|
2201
2202
|
this.permissionTimeoutMs = options.permissionTimeoutMs ?? DEFAULT_PERMISSION_TIMEOUT_MS;
|
|
2202
|
-
this.
|
|
2203
|
-
if (this.requestedPermissionMode !== void 0 && this.requestedPermissionMode.length === 0) {
|
|
2204
|
-
throw new ValidationError("requestedPermissionMode must be a non-empty mode id, got an empty string");
|
|
2205
|
-
}
|
|
2206
|
-
if (this.resolvePermission && (!Number.isFinite(this.permissionTimeoutMs) || this.permissionTimeoutMs <= 0)) {
|
|
2203
|
+
if ((this.resolvePermission || this.resolveSessionMode) && (!Number.isFinite(this.permissionTimeoutMs) || this.permissionTimeoutMs <= 0)) {
|
|
2207
2204
|
throw new ValidationError(`permissionTimeoutMs must be a positive finite number, got ${options.permissionTimeoutMs}`);
|
|
2208
2205
|
}
|
|
2209
2206
|
}
|
|
@@ -2367,7 +2364,7 @@ ${messageWithContext}`;
|
|
|
2367
2364
|
if (restored.ok) {
|
|
2368
2365
|
this.activeSessions.add(existingSessionId);
|
|
2369
2366
|
this.bootstrappedSessions.add(existingSessionId);
|
|
2370
|
-
await this.
|
|
2367
|
+
await this.configureSessionMode(roomId, existingSessionId, restored.modes, connection);
|
|
2371
2368
|
return existingSessionId;
|
|
2372
2369
|
}
|
|
2373
2370
|
}
|
|
@@ -2377,53 +2374,93 @@ ${messageWithContext}`;
|
|
|
2377
2374
|
});
|
|
2378
2375
|
this.roomToSession.set(roomId, created.sessionId);
|
|
2379
2376
|
this.activeSessions.add(created.sessionId);
|
|
2380
|
-
await this.
|
|
2377
|
+
await this.configureSessionMode(roomId, created.sessionId, created.modes, connection);
|
|
2381
2378
|
return created.sessionId;
|
|
2382
2379
|
}
|
|
2383
|
-
async tryRestoreSession(connection, sessionId, mcpServers) {
|
|
2384
|
-
const capabilities = this.connectionState?.agentCapabilities;
|
|
2385
|
-
const params = { cwd: this.cwd, mcpServers, sessionId };
|
|
2386
|
-
const restore = capabilities?.loadSession ? () => connection.loadSession(params) : capabilities?.sessionCapabilities?.resume ? () => connection.unstable_resumeSession(params) : null;
|
|
2387
|
-
if (!restore) {
|
|
2388
|
-
return { ok: false };
|
|
2389
|
-
}
|
|
2390
|
-
try {
|
|
2391
|
-
const restored = await restore();
|
|
2392
|
-
return { ok: true, modes: restored?.modes };
|
|
2393
|
-
} catch {
|
|
2394
|
-
return { ok: false };
|
|
2395
|
-
}
|
|
2396
|
-
}
|
|
2397
2380
|
// Best-effort: never throws, so a mode switch going wrong can't take a
|
|
2398
2381
|
// session establishment down with it.
|
|
2399
|
-
async
|
|
2400
|
-
|
|
2401
|
-
if (!requestedModeId || !modes || modes.currentModeId === requestedModeId) {
|
|
2382
|
+
async configureSessionMode(roomId, sessionId, modes, connection) {
|
|
2383
|
+
if (!this.resolveSessionMode || !modes) {
|
|
2402
2384
|
return;
|
|
2403
2385
|
}
|
|
2404
2386
|
const availableModes = Array.isArray(modes.availableModes) ? modes.availableModes : [];
|
|
2405
|
-
if (
|
|
2406
|
-
|
|
2387
|
+
if (availableModes.length === 0) {
|
|
2388
|
+
return;
|
|
2389
|
+
}
|
|
2390
|
+
const selectedModeId = await this.resolveSessionModeManually(
|
|
2391
|
+
(signal) => this.resolveSessionMode({
|
|
2392
|
+
roomId,
|
|
2407
2393
|
sessionId,
|
|
2408
|
-
|
|
2394
|
+
currentModeId: modes.currentModeId,
|
|
2395
|
+
modes: availableModes
|
|
2396
|
+
}, signal),
|
|
2397
|
+
connection.signal
|
|
2398
|
+
);
|
|
2399
|
+
if (!selectedModeId || selectedModeId === modes.currentModeId) {
|
|
2400
|
+
return;
|
|
2401
|
+
}
|
|
2402
|
+
if (!availableModes.some((mode) => mode?.id === selectedModeId)) {
|
|
2403
|
+
this.safeWarn("resolveSessionMode selected a mode id this session does not advertise", {
|
|
2404
|
+
sessionId,
|
|
2405
|
+
selectedModeId,
|
|
2409
2406
|
availableModeIds: availableModes.map((mode) => mode?.id)
|
|
2410
2407
|
});
|
|
2411
2408
|
return;
|
|
2412
2409
|
}
|
|
2413
2410
|
try {
|
|
2414
2411
|
await withTimeout(
|
|
2415
|
-
connection.setSessionMode({ sessionId, modeId:
|
|
2412
|
+
connection.setSessionMode({ sessionId, modeId: selectedModeId }),
|
|
2416
2413
|
SET_SESSION_MODE_TIMEOUT_MS,
|
|
2417
2414
|
`setSessionMode did not respond within ${SET_SESSION_MODE_TIMEOUT_MS}ms`
|
|
2418
2415
|
);
|
|
2419
2416
|
} catch (error) {
|
|
2420
|
-
this.safeWarn("failed to switch session into the
|
|
2417
|
+
this.safeWarn("failed to switch session into the selected mode", {
|
|
2421
2418
|
sessionId,
|
|
2422
|
-
|
|
2419
|
+
selectedModeId,
|
|
2423
2420
|
error: String(error)
|
|
2424
2421
|
});
|
|
2425
2422
|
}
|
|
2426
2423
|
}
|
|
2424
|
+
async resolveSessionModeManually(resolver, signal) {
|
|
2425
|
+
const controller = new AbortController();
|
|
2426
|
+
const abort = () => controller.abort();
|
|
2427
|
+
signal.addEventListener("abort", abort, { once: true });
|
|
2428
|
+
let timer;
|
|
2429
|
+
try {
|
|
2430
|
+
const cancelled = new Promise((resolve) => {
|
|
2431
|
+
controller.signal.addEventListener("abort", () => resolve(void 0), { once: true });
|
|
2432
|
+
});
|
|
2433
|
+
const timeout = new Promise((resolve) => {
|
|
2434
|
+
timer = setTimeout(() => resolve(void 0), this.permissionTimeoutMs);
|
|
2435
|
+
});
|
|
2436
|
+
return await Promise.race([
|
|
2437
|
+
Promise.resolve().then(() => resolver(controller.signal)).catch((error) => {
|
|
2438
|
+
this.safeWarn("resolveSessionMode threw; preserving the harness default", { error: String(error) });
|
|
2439
|
+
return void 0;
|
|
2440
|
+
}),
|
|
2441
|
+
timeout,
|
|
2442
|
+
cancelled
|
|
2443
|
+
]);
|
|
2444
|
+
} finally {
|
|
2445
|
+
clearTimeout(timer);
|
|
2446
|
+
signal.removeEventListener("abort", abort);
|
|
2447
|
+
controller.abort();
|
|
2448
|
+
}
|
|
2449
|
+
}
|
|
2450
|
+
async tryRestoreSession(connection, sessionId, mcpServers) {
|
|
2451
|
+
const capabilities = this.connectionState?.agentCapabilities;
|
|
2452
|
+
const params = { cwd: this.cwd, mcpServers, sessionId };
|
|
2453
|
+
const restore = capabilities?.loadSession ? () => connection.loadSession(params) : capabilities?.sessionCapabilities?.resume ? () => connection.unstable_resumeSession(params) : null;
|
|
2454
|
+
if (!restore) {
|
|
2455
|
+
return { ok: false };
|
|
2456
|
+
}
|
|
2457
|
+
try {
|
|
2458
|
+
const restored = await restore();
|
|
2459
|
+
return { ok: true, modes: restored?.modes };
|
|
2460
|
+
} catch {
|
|
2461
|
+
return { ok: false };
|
|
2462
|
+
}
|
|
2463
|
+
}
|
|
2427
2464
|
async buildSessionMcpServers() {
|
|
2428
2465
|
const mcpServers = [...this.mcpServers];
|
|
2429
2466
|
if (!this.enableMcpTools) {
|
package/dist/adapters.d.cts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export { A as A2AAdapter, a as A2AAdapterOptions, K as A2AClientFactory, M as A2AClientLike, b as A2AGatewayAdapter, c as AnthropicAdapter, d as AnthropicAdapterOptions, N as AnthropicClientFactory, Q as AnthropicToolCallingModel, R as AnthropicToolCallingModelOptions, C as CODEX_REASONING_EFFORTS, e as CODEX_REASONING_SUMMARIES, f as CODEX_WEB_SEARCH_MODES, g as ClaudePermissionMode, h as ClaudeSDKAdapter, i as ClaudeSDKAdapterOptions, S as ClaudeSDKQuery, U as ClaudeSDKQueryParams, j as CodexAdapter, k as CodexAdapterConfig, W as CodexAppServerStdioClient, l as CodexApprovalPolicy, X as CodexClientLike, Y as CodexJsonRpcError, m as CodexReasoningEffort, n as CodexReasoningSummary, o as CodexSandboxMode, p as CodexWebSearchMode, Z as DynamicToolCallParams, _ as DynamicToolCallResponse, $ as DynamicToolSpec, G as GeminiAdapter, q as GeminiAdapterOptions, a0 as GeminiClientFactory, a1 as GeminiToolCallingModel, a2 as GeminiToolCallingModelOptions, r as GenericAdapter, s as GenericAdapterHandler, t as GoogleADKAdapter, u as GoogleADKAdapterOptions, a3 as HttpOpencodeClient, a4 as HttpOpencodeClientOptions, a5 as HttpStatusError, L as LangGraphAdapter, v as LangGraphAdapterOptions, w as LangGraphGraph, x as LettaAdapter, y as LettaAdapterOptions, a6 as LettaAgentCreateParams, a7 as LettaClientFactory, a8 as LettaClientLike, a9 as LettaHistoryConverter, aa as LettaMessage, ab as LettaMessageCreateParams, ac as LettaMessages, ad as LettaRequestOptions, ae as LettaResponse, af as LettaResponseMessage, O as OpenAIAdapter, z as OpenAIAdapterOptions, ag as OpenAIClientFactory, ah as OpenAIToolCallingModel, ai as OpenAIToolCallingModelOptions, B as OpencodeAdapter, D as OpencodeAdapterConfig, E as OpencodeApprovalMode, F as OpencodeApprovalReply, aj as OpencodeClientLike, H as OpencodeQuestionMode, P as ParlantAdapter, I as ParlantAdapterOptions, ak as ParlantClientFactory, al as ParlantClientLike, am as ToolCall, an as ToolCallingAdapter, ao as ToolCallingAdapterOptions, T as ToolCallingModel, ap as ToolCallingModelRequest, aq as ToolCallingResponse, ar as ToolResult, as as TurnStartParams, V as VercelAISDKAdapter, J as VercelAISDKAdapterOptions, at as VercelAISDKToolCallingModel, au as VercelAISDKToolCallingModelOptions, av as runSingleToolRound } from './ClaudeSDKAdapter-Cx6zhSaG.cjs';
|
|
2
2
|
import * as _agentclientprotocol_sdk from '@agentclientprotocol/sdk';
|
|
3
|
-
import { Client, ClientSideConnection, McpServer, ClientCapabilities, RequestPermissionRequest,
|
|
3
|
+
import { Client, ClientSideConnection, McpServer, ClientCapabilities, RequestPermissionRequest, SessionMode, AgentSideConnection, SessionModeState, Agent, InitializeResponse, Implementation, Stream, InitializeRequest, LoadSessionRequest, LoadSessionResponse, ListSessionsRequest, ListSessionsResponse, ForkSessionRequest, ForkSessionResponse, ResumeSessionRequest, ResumeSessionResponse, SetSessionModeRequest, SetSessionModeResponse, SetSessionModelRequest, SetSessionModelResponse, SetSessionConfigOptionRequest, SetSessionConfigOptionResponse, AuthenticateRequest, AuthenticateResponse, PromptRequest, PromptResponse } from '@agentclientprotocol/sdk';
|
|
4
4
|
import { A as ACPClientSessionState, a as ACPServerSessionState } from './acp-server-Dlj7D563.cjs';
|
|
5
5
|
export { G as GatewayHistoryConverter } from './acp-server-Dlj7D563.cjs';
|
|
6
6
|
import { S as SimpleAdapter } from './simpleAdapter-BpT4XbZC.cjs';
|
|
@@ -41,6 +41,12 @@ type ACPClientConnectionFactory = (client: Client, options: {
|
|
|
41
41
|
env?: Record<string, string>;
|
|
42
42
|
}) => Promise<ACPClientConnectionHandle>;
|
|
43
43
|
|
|
44
|
+
interface ACPModeRequest {
|
|
45
|
+
roomId: string;
|
|
46
|
+
sessionId: string;
|
|
47
|
+
currentModeId: string;
|
|
48
|
+
modes: readonly SessionMode[];
|
|
49
|
+
}
|
|
44
50
|
interface ACPClientAdapterOptions {
|
|
45
51
|
command: string | string[];
|
|
46
52
|
cwd?: string;
|
|
@@ -54,7 +60,7 @@ interface ACPClientAdapterOptions {
|
|
|
54
60
|
connectionFactory?: ACPClientConnectionFactory;
|
|
55
61
|
resolvePermission?: (request: RequestPermissionRequest, signal: AbortSignal) => Promise<string | undefined>;
|
|
56
62
|
permissionTimeoutMs?: number;
|
|
57
|
-
|
|
63
|
+
resolveSessionMode?: (request: ACPModeRequest, signal: AbortSignal) => Promise<string | undefined>;
|
|
58
64
|
logger?: Logger;
|
|
59
65
|
}
|
|
60
66
|
declare class ACPClientAdapter extends SimpleAdapter<ACPClientSessionState, AdapterToolsProtocol> {
|
|
@@ -74,8 +80,8 @@ declare class ACPClientAdapter extends SimpleAdapter<ACPClientSessionState, Adap
|
|
|
74
80
|
private readonly bootstrappedSessions;
|
|
75
81
|
private readonly pendingPermissions;
|
|
76
82
|
private readonly resolvePermission?;
|
|
83
|
+
private readonly resolveSessionMode?;
|
|
77
84
|
private readonly permissionTimeoutMs;
|
|
78
|
-
private readonly requestedPermissionMode?;
|
|
79
85
|
private readonly logger;
|
|
80
86
|
private backend;
|
|
81
87
|
private backendPromise;
|
|
@@ -99,8 +105,9 @@ declare class ACPClientAdapter extends SimpleAdapter<ACPClientSessionState, Adap
|
|
|
99
105
|
private ensureConnection;
|
|
100
106
|
private spawnConnection;
|
|
101
107
|
private getOrCreateSession;
|
|
108
|
+
private configureSessionMode;
|
|
109
|
+
private resolveSessionModeManually;
|
|
102
110
|
private tryRestoreSession;
|
|
103
|
-
private applyRequestedPermissionMode;
|
|
104
111
|
private buildSessionMcpServers;
|
|
105
112
|
private getOrCreateBackend;
|
|
106
113
|
private createBackend;
|
package/dist/adapters.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export { A as A2AAdapter, a as A2AAdapterOptions, K as A2AClientFactory, M as A2AClientLike, b as A2AGatewayAdapter, c as AnthropicAdapter, d as AnthropicAdapterOptions, N as AnthropicClientFactory, Q as AnthropicToolCallingModel, R as AnthropicToolCallingModelOptions, C as CODEX_REASONING_EFFORTS, e as CODEX_REASONING_SUMMARIES, f as CODEX_WEB_SEARCH_MODES, g as ClaudePermissionMode, h as ClaudeSDKAdapter, i as ClaudeSDKAdapterOptions, S as ClaudeSDKQuery, U as ClaudeSDKQueryParams, j as CodexAdapter, k as CodexAdapterConfig, W as CodexAppServerStdioClient, l as CodexApprovalPolicy, X as CodexClientLike, Y as CodexJsonRpcError, m as CodexReasoningEffort, n as CodexReasoningSummary, o as CodexSandboxMode, p as CodexWebSearchMode, Z as DynamicToolCallParams, _ as DynamicToolCallResponse, $ as DynamicToolSpec, G as GeminiAdapter, q as GeminiAdapterOptions, a0 as GeminiClientFactory, a1 as GeminiToolCallingModel, a2 as GeminiToolCallingModelOptions, r as GenericAdapter, s as GenericAdapterHandler, t as GoogleADKAdapter, u as GoogleADKAdapterOptions, a3 as HttpOpencodeClient, a4 as HttpOpencodeClientOptions, a5 as HttpStatusError, L as LangGraphAdapter, v as LangGraphAdapterOptions, w as LangGraphGraph, x as LettaAdapter, y as LettaAdapterOptions, a6 as LettaAgentCreateParams, a7 as LettaClientFactory, a8 as LettaClientLike, a9 as LettaHistoryConverter, aa as LettaMessage, ab as LettaMessageCreateParams, ac as LettaMessages, ad as LettaRequestOptions, ae as LettaResponse, af as LettaResponseMessage, O as OpenAIAdapter, z as OpenAIAdapterOptions, ag as OpenAIClientFactory, ah as OpenAIToolCallingModel, ai as OpenAIToolCallingModelOptions, B as OpencodeAdapter, D as OpencodeAdapterConfig, E as OpencodeApprovalMode, F as OpencodeApprovalReply, aj as OpencodeClientLike, H as OpencodeQuestionMode, P as ParlantAdapter, I as ParlantAdapterOptions, ak as ParlantClientFactory, al as ParlantClientLike, am as ToolCall, an as ToolCallingAdapter, ao as ToolCallingAdapterOptions, T as ToolCallingModel, ap as ToolCallingModelRequest, aq as ToolCallingResponse, ar as ToolResult, as as TurnStartParams, V as VercelAISDKAdapter, J as VercelAISDKAdapterOptions, at as VercelAISDKToolCallingModel, au as VercelAISDKToolCallingModelOptions, av as runSingleToolRound } from './ClaudeSDKAdapter-CXud2DBE.js';
|
|
2
2
|
import * as _agentclientprotocol_sdk from '@agentclientprotocol/sdk';
|
|
3
|
-
import { Client, ClientSideConnection, McpServer, ClientCapabilities, RequestPermissionRequest,
|
|
3
|
+
import { Client, ClientSideConnection, McpServer, ClientCapabilities, RequestPermissionRequest, SessionMode, AgentSideConnection, SessionModeState, Agent, InitializeResponse, Implementation, Stream, InitializeRequest, LoadSessionRequest, LoadSessionResponse, ListSessionsRequest, ListSessionsResponse, ForkSessionRequest, ForkSessionResponse, ResumeSessionRequest, ResumeSessionResponse, SetSessionModeRequest, SetSessionModeResponse, SetSessionModelRequest, SetSessionModelResponse, SetSessionConfigOptionRequest, SetSessionConfigOptionResponse, AuthenticateRequest, AuthenticateResponse, PromptRequest, PromptResponse } from '@agentclientprotocol/sdk';
|
|
4
4
|
import { A as ACPClientSessionState, a as ACPServerSessionState } from './acp-server-CiUqN3G3.js';
|
|
5
5
|
export { G as GatewayHistoryConverter } from './acp-server-CiUqN3G3.js';
|
|
6
6
|
import { S as SimpleAdapter } from './simpleAdapter--wznuoOw.js';
|
|
@@ -41,6 +41,12 @@ type ACPClientConnectionFactory = (client: Client, options: {
|
|
|
41
41
|
env?: Record<string, string>;
|
|
42
42
|
}) => Promise<ACPClientConnectionHandle>;
|
|
43
43
|
|
|
44
|
+
interface ACPModeRequest {
|
|
45
|
+
roomId: string;
|
|
46
|
+
sessionId: string;
|
|
47
|
+
currentModeId: string;
|
|
48
|
+
modes: readonly SessionMode[];
|
|
49
|
+
}
|
|
44
50
|
interface ACPClientAdapterOptions {
|
|
45
51
|
command: string | string[];
|
|
46
52
|
cwd?: string;
|
|
@@ -54,7 +60,7 @@ interface ACPClientAdapterOptions {
|
|
|
54
60
|
connectionFactory?: ACPClientConnectionFactory;
|
|
55
61
|
resolvePermission?: (request: RequestPermissionRequest, signal: AbortSignal) => Promise<string | undefined>;
|
|
56
62
|
permissionTimeoutMs?: number;
|
|
57
|
-
|
|
63
|
+
resolveSessionMode?: (request: ACPModeRequest, signal: AbortSignal) => Promise<string | undefined>;
|
|
58
64
|
logger?: Logger;
|
|
59
65
|
}
|
|
60
66
|
declare class ACPClientAdapter extends SimpleAdapter<ACPClientSessionState, AdapterToolsProtocol> {
|
|
@@ -74,8 +80,8 @@ declare class ACPClientAdapter extends SimpleAdapter<ACPClientSessionState, Adap
|
|
|
74
80
|
private readonly bootstrappedSessions;
|
|
75
81
|
private readonly pendingPermissions;
|
|
76
82
|
private readonly resolvePermission?;
|
|
83
|
+
private readonly resolveSessionMode?;
|
|
77
84
|
private readonly permissionTimeoutMs;
|
|
78
|
-
private readonly requestedPermissionMode?;
|
|
79
85
|
private readonly logger;
|
|
80
86
|
private backend;
|
|
81
87
|
private backendPromise;
|
|
@@ -99,8 +105,9 @@ declare class ACPClientAdapter extends SimpleAdapter<ACPClientSessionState, Adap
|
|
|
99
105
|
private ensureConnection;
|
|
100
106
|
private spawnConnection;
|
|
101
107
|
private getOrCreateSession;
|
|
108
|
+
private configureSessionMode;
|
|
109
|
+
private resolveSessionModeManually;
|
|
102
110
|
private tryRestoreSession;
|
|
103
|
-
private applyRequestedPermissionMode;
|
|
104
111
|
private buildSessionMcpServers;
|
|
105
112
|
private getOrCreateBackend;
|
|
106
113
|
private createBackend;
|
package/dist/adapters.js
CHANGED
|
@@ -387,8 +387,8 @@ var ACPClientAdapter = class extends SimpleAdapter {
|
|
|
387
387
|
bootstrappedSessions = /* @__PURE__ */ new Set();
|
|
388
388
|
pendingPermissions = /* @__PURE__ */ new Map();
|
|
389
389
|
resolvePermission;
|
|
390
|
+
resolveSessionMode;
|
|
390
391
|
permissionTimeoutMs;
|
|
391
|
-
requestedPermissionMode;
|
|
392
392
|
logger;
|
|
393
393
|
backend = null;
|
|
394
394
|
backendPromise = null;
|
|
@@ -417,13 +417,10 @@ var ACPClientAdapter = class extends SimpleAdapter {
|
|
|
417
417
|
this.clientCapabilities = options.clientCapabilities;
|
|
418
418
|
this.connectionFactory = options.connectionFactory ?? createSubprocessConnection;
|
|
419
419
|
this.resolvePermission = options.resolvePermission;
|
|
420
|
+
this.resolveSessionMode = options.resolveSessionMode;
|
|
420
421
|
this.logger = options.logger ?? new NoopLogger();
|
|
421
422
|
this.permissionTimeoutMs = options.permissionTimeoutMs ?? DEFAULT_PERMISSION_TIMEOUT_MS;
|
|
422
|
-
this.
|
|
423
|
-
if (this.requestedPermissionMode !== void 0 && this.requestedPermissionMode.length === 0) {
|
|
424
|
-
throw new ValidationError("requestedPermissionMode must be a non-empty mode id, got an empty string");
|
|
425
|
-
}
|
|
426
|
-
if (this.resolvePermission && (!Number.isFinite(this.permissionTimeoutMs) || this.permissionTimeoutMs <= 0)) {
|
|
423
|
+
if ((this.resolvePermission || this.resolveSessionMode) && (!Number.isFinite(this.permissionTimeoutMs) || this.permissionTimeoutMs <= 0)) {
|
|
427
424
|
throw new ValidationError(`permissionTimeoutMs must be a positive finite number, got ${options.permissionTimeoutMs}`);
|
|
428
425
|
}
|
|
429
426
|
}
|
|
@@ -587,7 +584,7 @@ ${messageWithContext}`;
|
|
|
587
584
|
if (restored.ok) {
|
|
588
585
|
this.activeSessions.add(existingSessionId);
|
|
589
586
|
this.bootstrappedSessions.add(existingSessionId);
|
|
590
|
-
await this.
|
|
587
|
+
await this.configureSessionMode(roomId, existingSessionId, restored.modes, connection);
|
|
591
588
|
return existingSessionId;
|
|
592
589
|
}
|
|
593
590
|
}
|
|
@@ -597,53 +594,93 @@ ${messageWithContext}`;
|
|
|
597
594
|
});
|
|
598
595
|
this.roomToSession.set(roomId, created.sessionId);
|
|
599
596
|
this.activeSessions.add(created.sessionId);
|
|
600
|
-
await this.
|
|
597
|
+
await this.configureSessionMode(roomId, created.sessionId, created.modes, connection);
|
|
601
598
|
return created.sessionId;
|
|
602
599
|
}
|
|
603
|
-
async tryRestoreSession(connection, sessionId, mcpServers) {
|
|
604
|
-
const capabilities = this.connectionState?.agentCapabilities;
|
|
605
|
-
const params = { cwd: this.cwd, mcpServers, sessionId };
|
|
606
|
-
const restore = capabilities?.loadSession ? () => connection.loadSession(params) : capabilities?.sessionCapabilities?.resume ? () => connection.unstable_resumeSession(params) : null;
|
|
607
|
-
if (!restore) {
|
|
608
|
-
return { ok: false };
|
|
609
|
-
}
|
|
610
|
-
try {
|
|
611
|
-
const restored = await restore();
|
|
612
|
-
return { ok: true, modes: restored?.modes };
|
|
613
|
-
} catch {
|
|
614
|
-
return { ok: false };
|
|
615
|
-
}
|
|
616
|
-
}
|
|
617
600
|
// Best-effort: never throws, so a mode switch going wrong can't take a
|
|
618
601
|
// session establishment down with it.
|
|
619
|
-
async
|
|
620
|
-
|
|
621
|
-
if (!requestedModeId || !modes || modes.currentModeId === requestedModeId) {
|
|
602
|
+
async configureSessionMode(roomId, sessionId, modes, connection) {
|
|
603
|
+
if (!this.resolveSessionMode || !modes) {
|
|
622
604
|
return;
|
|
623
605
|
}
|
|
624
606
|
const availableModes = Array.isArray(modes.availableModes) ? modes.availableModes : [];
|
|
625
|
-
if (
|
|
626
|
-
|
|
607
|
+
if (availableModes.length === 0) {
|
|
608
|
+
return;
|
|
609
|
+
}
|
|
610
|
+
const selectedModeId = await this.resolveSessionModeManually(
|
|
611
|
+
(signal) => this.resolveSessionMode({
|
|
612
|
+
roomId,
|
|
627
613
|
sessionId,
|
|
628
|
-
|
|
614
|
+
currentModeId: modes.currentModeId,
|
|
615
|
+
modes: availableModes
|
|
616
|
+
}, signal),
|
|
617
|
+
connection.signal
|
|
618
|
+
);
|
|
619
|
+
if (!selectedModeId || selectedModeId === modes.currentModeId) {
|
|
620
|
+
return;
|
|
621
|
+
}
|
|
622
|
+
if (!availableModes.some((mode) => mode?.id === selectedModeId)) {
|
|
623
|
+
this.safeWarn("resolveSessionMode selected a mode id this session does not advertise", {
|
|
624
|
+
sessionId,
|
|
625
|
+
selectedModeId,
|
|
629
626
|
availableModeIds: availableModes.map((mode) => mode?.id)
|
|
630
627
|
});
|
|
631
628
|
return;
|
|
632
629
|
}
|
|
633
630
|
try {
|
|
634
631
|
await withTimeout(
|
|
635
|
-
connection.setSessionMode({ sessionId, modeId:
|
|
632
|
+
connection.setSessionMode({ sessionId, modeId: selectedModeId }),
|
|
636
633
|
SET_SESSION_MODE_TIMEOUT_MS,
|
|
637
634
|
`setSessionMode did not respond within ${SET_SESSION_MODE_TIMEOUT_MS}ms`
|
|
638
635
|
);
|
|
639
636
|
} catch (error) {
|
|
640
|
-
this.safeWarn("failed to switch session into the
|
|
637
|
+
this.safeWarn("failed to switch session into the selected mode", {
|
|
641
638
|
sessionId,
|
|
642
|
-
|
|
639
|
+
selectedModeId,
|
|
643
640
|
error: String(error)
|
|
644
641
|
});
|
|
645
642
|
}
|
|
646
643
|
}
|
|
644
|
+
async resolveSessionModeManually(resolver, signal) {
|
|
645
|
+
const controller = new AbortController();
|
|
646
|
+
const abort = () => controller.abort();
|
|
647
|
+
signal.addEventListener("abort", abort, { once: true });
|
|
648
|
+
let timer;
|
|
649
|
+
try {
|
|
650
|
+
const cancelled = new Promise((resolve) => {
|
|
651
|
+
controller.signal.addEventListener("abort", () => resolve(void 0), { once: true });
|
|
652
|
+
});
|
|
653
|
+
const timeout = new Promise((resolve) => {
|
|
654
|
+
timer = setTimeout(() => resolve(void 0), this.permissionTimeoutMs);
|
|
655
|
+
});
|
|
656
|
+
return await Promise.race([
|
|
657
|
+
Promise.resolve().then(() => resolver(controller.signal)).catch((error) => {
|
|
658
|
+
this.safeWarn("resolveSessionMode threw; preserving the harness default", { error: String(error) });
|
|
659
|
+
return void 0;
|
|
660
|
+
}),
|
|
661
|
+
timeout,
|
|
662
|
+
cancelled
|
|
663
|
+
]);
|
|
664
|
+
} finally {
|
|
665
|
+
clearTimeout(timer);
|
|
666
|
+
signal.removeEventListener("abort", abort);
|
|
667
|
+
controller.abort();
|
|
668
|
+
}
|
|
669
|
+
}
|
|
670
|
+
async tryRestoreSession(connection, sessionId, mcpServers) {
|
|
671
|
+
const capabilities = this.connectionState?.agentCapabilities;
|
|
672
|
+
const params = { cwd: this.cwd, mcpServers, sessionId };
|
|
673
|
+
const restore = capabilities?.loadSession ? () => connection.loadSession(params) : capabilities?.sessionCapabilities?.resume ? () => connection.unstable_resumeSession(params) : null;
|
|
674
|
+
if (!restore) {
|
|
675
|
+
return { ok: false };
|
|
676
|
+
}
|
|
677
|
+
try {
|
|
678
|
+
const restored = await restore();
|
|
679
|
+
return { ok: true, modes: restored?.modes };
|
|
680
|
+
} catch {
|
|
681
|
+
return { ok: false };
|
|
682
|
+
}
|
|
683
|
+
}
|
|
647
684
|
async buildSessionMcpServers() {
|
|
648
685
|
const mcpServers = [...this.mcpServers];
|
|
649
686
|
if (!this.enableMcpTools) {
|