@automatalabs/acp-agents 0.15.0 → 0.17.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-client.d.ts +19 -2
- package/dist/acp-client.d.ts.map +1 -1
- package/dist/acp-client.js +224 -9
- package/dist/capabilities.d.ts +21 -8
- package/dist/capabilities.d.ts.map +1 -1
- package/dist/capabilities.js +28 -9
- package/dist/client-handlers.d.ts +12 -3
- package/dist/client-handlers.d.ts.map +1 -1
- package/dist/client-handlers.js +22 -7
- package/dist/errors-map.d.ts +8 -1
- package/dist/errors-map.d.ts.map +1 -1
- package/dist/errors-map.js +23 -3
- package/dist/index.d.ts +6 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/pool.d.ts.map +1 -1
- package/dist/pool.js +13 -1
- package/dist/protocol-coverage.d.ts +3 -1
- package/dist/protocol-coverage.d.ts.map +1 -1
- package/dist/protocol-coverage.js +11 -9
- package/dist/runner.d.ts +46 -1
- package/dist/runner.d.ts.map +1 -1
- package/dist/runner.js +179 -31
- package/package.json +2 -2
package/dist/acp-client.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type CreateElicitationResponse, type ContentBlock, type AgentNotificationMethod, type AgentNotificationParamsByMethod, type AgentRequestMethod, type AgentRequestParamsByMethod, type AgentRequestResponsesByMethod, type DeleteSessionRequest, type ListSessionsRequest, type ListSessionsResponse, type PromptRequest, type PromptResponse, type RequestPermissionResponse, type SendRequestOptions, type SessionConfigOption, type SessionModeState, type SessionNotification, type SetSessionConfigOptionRequest, type SetSessionConfigOptionResponse, type SetSessionModeRequest, type SetSessionModeResponse } from "@agentclientprotocol/sdk";
|
|
1
|
+
import { type AuthenticateRequest, type AuthenticateResponse, type AuthMethod, type CreateElicitationResponse, type ContentBlock, type AgentNotificationMethod, type AgentNotificationParamsByMethod, type AgentRequestMethod, type AgentRequestParamsByMethod, type AgentRequestResponsesByMethod, type DeleteSessionRequest, type DisableProviderRequest, type DisableProviderResponse, type ListSessionsRequest, type ListSessionsResponse, type ListProvidersRequest, type ListProvidersResponse, type LogoutRequest, type LogoutResponse, type PromptRequest, type PromptResponse, type RequestPermissionResponse, type SendRequestOptions, type SessionConfigOption, type SessionModeState, type SessionNotification, type SetProviderRequest, type SetProviderResponse, type SetSessionConfigOptionRequest, type SetSessionConfigOptionResponse, type SetSessionModeRequest, type SetSessionModeResponse } from "@agentclientprotocol/sdk";
|
|
2
2
|
import type { TSchema } from "typebox";
|
|
3
3
|
import { type AgentHistoryEntry, type McpServerConfig } from "@automatalabs/shared-types";
|
|
4
4
|
import type { Backend, BackendId, StructuredSource } from "./backend.js";
|
|
@@ -21,6 +21,7 @@ declare class SessionState {
|
|
|
21
21
|
readonly elicitationResolver?: ElicitationResolver | undefined;
|
|
22
22
|
readonly label?: string | undefined;
|
|
23
23
|
readonly runId?: string | undefined;
|
|
24
|
+
readonly mcpServerIds: readonly string[];
|
|
24
25
|
private readonly retainSessionLog;
|
|
25
26
|
readonly textChunks: string[];
|
|
26
27
|
readonly history: AgentHistoryEntry[];
|
|
@@ -28,12 +29,13 @@ declare class SessionState {
|
|
|
28
29
|
readonly pendingPermissions: Set<(outcome: RequestPermissionResponse) => void>;
|
|
29
30
|
readonly pendingElicitations: Set<(outcome: CreateElicitationResponse) => void>;
|
|
30
31
|
readonly urlElicitationIds: Set<string>;
|
|
32
|
+
readonly mcpConnectionIds: Set<string>;
|
|
31
33
|
rawResultSuccess: RawResultSuccess | undefined;
|
|
32
34
|
modes: SessionModeState | null | undefined;
|
|
33
35
|
private turnStartIndex;
|
|
34
36
|
/** `label`/`runId` are carried here ONLY so the MultiplexClient can stamp them onto emitted
|
|
35
37
|
* events as context — they never affect routing or the wire request. */
|
|
36
|
-
constructor(cwd: string, policy: ToolPolicy, permissionResolver?: PermissionResolver | undefined, elicitationResolver?: ElicitationResolver | undefined, label?: string | undefined, runId?: string | undefined, modes?: SessionModeState | null, retainSessionLog?: boolean);
|
|
38
|
+
constructor(cwd: string, policy: ToolPolicy, permissionResolver?: PermissionResolver | undefined, elicitationResolver?: ElicitationResolver | undefined, label?: string | undefined, runId?: string | undefined, modes?: SessionModeState | null, mcpServerIds?: readonly string[], retainSessionLog?: boolean);
|
|
37
39
|
/** Mark the start of a new turn so currentTurnText()/structured_output read only this turn.
|
|
38
40
|
* Long-lived interactive sessions can opt out of retaining old text/history because hosts
|
|
39
41
|
* stream live events and keep their own transcript; clearing here prevents dead logs from
|
|
@@ -145,6 +147,7 @@ export declare class PooledConnection {
|
|
|
145
147
|
private assertSupportedMcpServers;
|
|
146
148
|
private sessionRequestMeta;
|
|
147
149
|
private assertLifecycleSupported;
|
|
150
|
+
private assertAuthProviderSupported;
|
|
148
151
|
/** Mark this connection dead exactly once, then ask the pool to evict it. Idempotent. */
|
|
149
152
|
private die;
|
|
150
153
|
private stderrSuffix;
|
|
@@ -168,6 +171,18 @@ export declare class PooledConnection {
|
|
|
168
171
|
listSessions(request: ListSessionsRequest, label?: string): Promise<ListSessionsResponse>;
|
|
169
172
|
/** session/delete on a dedicated connection, gated on the initialize advertisement. */
|
|
170
173
|
deleteSession(request: DeleteSessionRequest, label?: string): Promise<void>;
|
|
174
|
+
/** Authentication methods advertised in initialize, available without opening a session. */
|
|
175
|
+
authMethods(): Promise<AuthMethod[]>;
|
|
176
|
+
/** authenticate has no AgentCapabilities gate; authMethods advertises choices, not method support. */
|
|
177
|
+
authenticate(request: AuthenticateRequest, label?: string): Promise<AuthenticateResponse | void>;
|
|
178
|
+
/** providers/list on a dedicated connection, gated on the unstable providers advertisement. */
|
|
179
|
+
listProviders(request: ListProvidersRequest, label?: string): Promise<ListProvidersResponse>;
|
|
180
|
+
/** providers/set on a dedicated connection, gated on the unstable providers advertisement. */
|
|
181
|
+
setProvider(request: SetProviderRequest, label?: string): Promise<SetProviderResponse | void>;
|
|
182
|
+
/** providers/disable on a dedicated connection, gated on the unstable providers advertisement. */
|
|
183
|
+
disableProvider(request: DisableProviderRequest, label?: string): Promise<DisableProviderResponse | void>;
|
|
184
|
+
/** logout on a dedicated connection, gated on agentCapabilities.auth.logout. */
|
|
185
|
+
logout(request: LogoutRequest, label?: string): Promise<LogoutResponse | void>;
|
|
171
186
|
/** session/prompt on this connection, raced against process death. */
|
|
172
187
|
prompt(request: PromptRequest): Promise<PromptResponse>;
|
|
173
188
|
/** session/set_config_option on this connection, raced against process death. */
|
|
@@ -219,6 +234,8 @@ export declare class SessionHandle implements StructuredSource {
|
|
|
219
234
|
get text(): string;
|
|
220
235
|
/** Agent-advertised session mode catalog plus the currently active mode, if supported. */
|
|
221
236
|
get modes(): SessionModeState | null | undefined;
|
|
237
|
+
/** The connection-level initialize response parsed before this session was opened. */
|
|
238
|
+
get capabilities(): NegotiatedCapabilities | undefined;
|
|
222
239
|
/**
|
|
223
240
|
* Select the model for this session from the agent-advertised config options (§5.4).
|
|
224
241
|
* Returns `matched:false` (the caller fires onModelFallback) when the catalog has no value
|
package/dist/acp-client.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"acp-client.d.ts","sourceRoot":"","sources":["../src/acp-client.ts"],"names":[],"mappings":"AAwBA,OAAO,
|
|
1
|
+
{"version":3,"file":"acp-client.d.ts","sourceRoot":"","sources":["../src/acp-client.ts"],"names":[],"mappings":"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"}
|
package/dist/acp-client.js
CHANGED
|
@@ -24,11 +24,11 @@ import { spawn } from "node:child_process";
|
|
|
24
24
|
import { Readable, Writable } from "node:stream";
|
|
25
25
|
import { AGENT_METHODS, client, CLIENT_METHODS, ndJsonStream, PROTOCOL_VERSION, RequestError, } from "@agentclientprotocol/sdk";
|
|
26
26
|
import { META_KEYS, WorkflowError, WorkflowErrorCode, } from "@automatalabs/shared-types";
|
|
27
|
-
import { adaptPromptContent, describeLifecycleAdvertisement, gateCustomMeta, isSupportedProtocolVersion, negotiateCapabilities, unsupportedMcpServer, } from "./capabilities.js";
|
|
27
|
+
import { adaptPromptContent, describeAuthProviderAdvertisement, describeLifecycleAdvertisement, gateCustomMeta, isSupportedProtocolVersion, negotiateCapabilities, unsupportedMcpServer, } from "./capabilities.js";
|
|
28
28
|
import { emitSessionUpdate } from "./events.js";
|
|
29
29
|
import { decidePermission, } from "./permissions.js";
|
|
30
30
|
import { UsageAccumulator } from "./usage.js";
|
|
31
|
-
import { clientCapabilitiesFor, } from "./client-handlers.js";
|
|
31
|
+
import { clientCapabilitiesFor, hasFullMcpHandlers, } from "./client-handlers.js";
|
|
32
32
|
/** A benign client identity. NOT JetBrains/IntelliJ 2026.1 — that exact identity makes
|
|
33
33
|
* codex-acp disable session config options (our model/effort routing channel). */
|
|
34
34
|
const CLIENT_INFO = {
|
|
@@ -51,6 +51,10 @@ const GUARDED_STATEFUL_REQUESTS = new Map([
|
|
|
51
51
|
"no driven wrapper yet; raw forked sessions cannot be routed (permissions auto-cancel)",
|
|
52
52
|
],
|
|
53
53
|
]);
|
|
54
|
+
const parseConnectMcpRequest = (params) => params;
|
|
55
|
+
const parseMessageMcpRequest = (params) => params;
|
|
56
|
+
const parseMessageMcpNotification = (params) => params;
|
|
57
|
+
const parseDisconnectMcpRequest = (params) => params;
|
|
54
58
|
/** Per-session accumulator: assistant text, tool history, usage, the Claude raw structured_output,
|
|
55
59
|
* and the permission policy/resolver used to answer permission requests for THIS session. */
|
|
56
60
|
class SessionState {
|
|
@@ -60,6 +64,7 @@ class SessionState {
|
|
|
60
64
|
elicitationResolver;
|
|
61
65
|
label;
|
|
62
66
|
runId;
|
|
67
|
+
mcpServerIds;
|
|
63
68
|
retainSessionLog;
|
|
64
69
|
textChunks = [];
|
|
65
70
|
history = [];
|
|
@@ -67,18 +72,20 @@ class SessionState {
|
|
|
67
72
|
pendingPermissions = new Set();
|
|
68
73
|
pendingElicitations = new Set();
|
|
69
74
|
urlElicitationIds = new Set();
|
|
75
|
+
mcpConnectionIds = new Set();
|
|
70
76
|
rawResultSuccess;
|
|
71
77
|
modes;
|
|
72
78
|
turnStartIndex = 0;
|
|
73
79
|
/** `label`/`runId` are carried here ONLY so the MultiplexClient can stamp them onto emitted
|
|
74
80
|
* events as context — they never affect routing or the wire request. */
|
|
75
|
-
constructor(cwd, policy, permissionResolver, elicitationResolver, label, runId, modes, retainSessionLog = true) {
|
|
81
|
+
constructor(cwd, policy, permissionResolver, elicitationResolver, label, runId, modes, mcpServerIds = [], retainSessionLog = true) {
|
|
76
82
|
this.cwd = cwd;
|
|
77
83
|
this.policy = policy;
|
|
78
84
|
this.permissionResolver = permissionResolver;
|
|
79
85
|
this.elicitationResolver = elicitationResolver;
|
|
80
86
|
this.label = label;
|
|
81
87
|
this.runId = runId;
|
|
88
|
+
this.mcpServerIds = mcpServerIds;
|
|
82
89
|
this.retainSessionLog = retainSessionLog;
|
|
83
90
|
this.modes = modes;
|
|
84
91
|
}
|
|
@@ -172,6 +179,8 @@ class MultiplexClient {
|
|
|
172
179
|
elicitationResolver;
|
|
173
180
|
sessions = new Map();
|
|
174
181
|
urlElicitationContexts = new Map();
|
|
182
|
+
mcpServerSessions = new Map();
|
|
183
|
+
mcpConnectionSessions = new Map();
|
|
175
184
|
/** Recently unregistered sessions kept ONLY for the teardown window: ACP agents may
|
|
176
185
|
* legitimately release terminals (or finish fs/terminal cleanup) after this client releases
|
|
177
186
|
* the session because session/close is cancel + free resources and the Agent owns terminal
|
|
@@ -208,14 +217,22 @@ class MultiplexClient {
|
|
|
208
217
|
register(sessionId, state) {
|
|
209
218
|
this.tombstones.delete(sessionId);
|
|
210
219
|
this.sessions.set(sessionId, state);
|
|
220
|
+
for (const serverId of state.mcpServerIds)
|
|
221
|
+
this.mcpServerSessions.set(serverId, sessionId);
|
|
211
222
|
this.onEvent?.("session_open", this.contextFor(sessionId, state));
|
|
212
223
|
}
|
|
213
224
|
unregister(sessionId) {
|
|
214
225
|
const state = this.sessions.get(sessionId);
|
|
215
226
|
state?.settlePendingPermissions();
|
|
216
227
|
state?.settlePendingElicitations();
|
|
228
|
+
if (state)
|
|
229
|
+
this.disconnectMcpConnectionsForSession(sessionId, state);
|
|
217
230
|
this.sessions.delete(sessionId);
|
|
218
231
|
if (state) {
|
|
232
|
+
for (const serverId of state.mcpServerIds) {
|
|
233
|
+
if (this.mcpServerSessions.get(serverId) === sessionId)
|
|
234
|
+
this.mcpServerSessions.delete(serverId);
|
|
235
|
+
}
|
|
219
236
|
for (const elicitationId of state.urlElicitationIds)
|
|
220
237
|
this.urlElicitationContexts.delete(elicitationId);
|
|
221
238
|
this.tombstones.set(sessionId, {
|
|
@@ -248,6 +265,12 @@ class MultiplexClient {
|
|
|
248
265
|
state.settlePendingElicitations();
|
|
249
266
|
}
|
|
250
267
|
}
|
|
268
|
+
disconnectAllMcpConnections() {
|
|
269
|
+
for (const [sessionId, state] of this.sessions) {
|
|
270
|
+
this.disconnectMcpConnectionsForSession(sessionId, state);
|
|
271
|
+
}
|
|
272
|
+
this.mcpServerSessions.clear();
|
|
273
|
+
}
|
|
251
274
|
requestPermission(params) {
|
|
252
275
|
const state = this.sessions.get(params.sessionId);
|
|
253
276
|
// Unknown/closed session: refuse rather than silently allow a tool we can't attribute.
|
|
@@ -373,6 +396,51 @@ class MultiplexClient {
|
|
|
373
396
|
killTerminal(params) {
|
|
374
397
|
return this.dispatch(params, CLIENT_METHODS.terminal_kill, this.handlers?.terminal?.killTerminal);
|
|
375
398
|
}
|
|
399
|
+
async mcpConnect(params) {
|
|
400
|
+
const handler = this.handlers?.mcp?.connect;
|
|
401
|
+
if (typeof handler !== "function")
|
|
402
|
+
throw methodNotAdvertised(CLIENT_METHODS.mcp_connect);
|
|
403
|
+
const sessionId = this.mcpServerSessions.get(params.serverId);
|
|
404
|
+
if (!sessionId)
|
|
405
|
+
throw unknownMcpServer(params.serverId);
|
|
406
|
+
const response = await handler(params, this.handlerContext({ sessionId }));
|
|
407
|
+
this.mcpConnectionSessions.set(response.connectionId, sessionId);
|
|
408
|
+
this.sessions.get(sessionId)?.mcpConnectionIds.add(response.connectionId);
|
|
409
|
+
return response;
|
|
410
|
+
}
|
|
411
|
+
async mcpMessage(params) {
|
|
412
|
+
const handler = this.handlers?.mcp?.message;
|
|
413
|
+
if (typeof handler !== "function")
|
|
414
|
+
throw methodNotAdvertised(CLIENT_METHODS.mcp_message);
|
|
415
|
+
const ctx = this.handlerContext({ sessionId: this.sessionIdForMcpConnection(params.connectionId) });
|
|
416
|
+
return handler(params, ctx);
|
|
417
|
+
}
|
|
418
|
+
mcpMessageNotification(params) {
|
|
419
|
+
const handler = this.handlers?.mcp?.message;
|
|
420
|
+
if (typeof handler !== "function")
|
|
421
|
+
return;
|
|
422
|
+
const sessionId = this.mcpConnectionSessions.get(params.connectionId);
|
|
423
|
+
if (!sessionId)
|
|
424
|
+
return;
|
|
425
|
+
try {
|
|
426
|
+
Promise.resolve(handler(params, this.handlerContext({ sessionId }))).catch(() => { });
|
|
427
|
+
}
|
|
428
|
+
catch {
|
|
429
|
+
// Notifications have no response path; teardown remains best-effort and non-fatal.
|
|
430
|
+
}
|
|
431
|
+
}
|
|
432
|
+
async mcpDisconnect(params) {
|
|
433
|
+
const handler = this.handlers?.mcp?.disconnect;
|
|
434
|
+
if (typeof handler !== "function")
|
|
435
|
+
throw methodNotAdvertised(CLIENT_METHODS.mcp_disconnect);
|
|
436
|
+
const sessionId = this.sessionIdForMcpConnection(params.connectionId);
|
|
437
|
+
try {
|
|
438
|
+
return (await handler(params, this.handlerContext({ sessionId }))) ?? {};
|
|
439
|
+
}
|
|
440
|
+
finally {
|
|
441
|
+
this.dropMcpConnection(params.connectionId, sessionId);
|
|
442
|
+
}
|
|
443
|
+
}
|
|
376
444
|
sessionUpdate(params) {
|
|
377
445
|
const state = this.sessions.get(params.sessionId);
|
|
378
446
|
// Fold into the accumulator FIRST (the drain contract), THEN bubble the event up unchanged.
|
|
@@ -406,10 +474,42 @@ class MultiplexClient {
|
|
|
406
474
|
this.sessions.get(ctx.sessionId)?.urlElicitationIds.delete(params.elicitationId);
|
|
407
475
|
this.onEvent?.("elicitation_complete", { ...ctx, notification: params });
|
|
408
476
|
}
|
|
477
|
+
sessionIdForMcpConnection(connectionId) {
|
|
478
|
+
const sessionId = this.mcpConnectionSessions.get(connectionId);
|
|
479
|
+
if (!sessionId)
|
|
480
|
+
throw unknownMcpConnection(connectionId);
|
|
481
|
+
return sessionId;
|
|
482
|
+
}
|
|
483
|
+
dropMcpConnection(connectionId, sessionId) {
|
|
484
|
+
this.mcpConnectionSessions.delete(connectionId);
|
|
485
|
+
this.sessions.get(sessionId)?.mcpConnectionIds.delete(connectionId);
|
|
486
|
+
}
|
|
487
|
+
disconnectMcpConnectionsForSession(sessionId, state) {
|
|
488
|
+
const handler = this.handlers?.mcp?.disconnect;
|
|
489
|
+
const ctx = { sessionId, cwd: state.cwd, label: state.label, runId: state.runId };
|
|
490
|
+
for (const connectionId of [...state.mcpConnectionIds]) {
|
|
491
|
+
this.mcpConnectionSessions.delete(connectionId);
|
|
492
|
+
state.mcpConnectionIds.delete(connectionId);
|
|
493
|
+
if (typeof handler !== "function")
|
|
494
|
+
continue;
|
|
495
|
+
try {
|
|
496
|
+
Promise.resolve(handler({ connectionId }, ctx)).catch(() => { });
|
|
497
|
+
}
|
|
498
|
+
catch {
|
|
499
|
+
// Best-effort teardown: a broken MCP cleanup hook must not block session release/death.
|
|
500
|
+
}
|
|
501
|
+
}
|
|
502
|
+
}
|
|
409
503
|
}
|
|
410
504
|
function unknownSession(sessionId) {
|
|
411
505
|
return RequestError.invalidParams({ sessionId }, `unknown session: ${sessionId}`);
|
|
412
506
|
}
|
|
507
|
+
function unknownMcpServer(serverId) {
|
|
508
|
+
return RequestError.invalidParams({ serverId }, `unknown MCP-over-ACP server: ${serverId}`);
|
|
509
|
+
}
|
|
510
|
+
function unknownMcpConnection(connectionId) {
|
|
511
|
+
return RequestError.invalidParams({ connectionId }, `unknown MCP-over-ACP connection: ${connectionId}`);
|
|
512
|
+
}
|
|
413
513
|
function cancelledPermissionResponse() {
|
|
414
514
|
return { outcome: { outcome: "cancelled" } };
|
|
415
515
|
}
|
|
@@ -452,6 +552,18 @@ function lifecycleCapabilityError(backendId, method, capabilities, label) {
|
|
|
452
552
|
: "initialize did not complete";
|
|
453
553
|
return new WorkflowError(`ACP agent (${backendId}) does not advertise ${method}; advertised lifecycle capabilities: ${advertised}`, WorkflowErrorCode.SCRIPT_VALIDATION_ERROR, { recoverable: false, agentLabel: label });
|
|
454
554
|
}
|
|
555
|
+
function authProviderCapabilityError(backendId, method, capabilities, label) {
|
|
556
|
+
const advertised = capabilities
|
|
557
|
+
? describeAuthProviderAdvertisement(capabilities.agent, capabilities.authMethods)
|
|
558
|
+
: "initialize did not complete";
|
|
559
|
+
return new WorkflowError(`ACP agent (${backendId}) does not advertise ${method}; advertised auth/provider capabilities: ${advertised}`, WorkflowErrorCode.SCRIPT_VALIDATION_ERROR, { recoverable: false, agentLabel: label });
|
|
560
|
+
}
|
|
561
|
+
function isMethodNotFound(error) {
|
|
562
|
+
return Boolean(error && typeof error === "object" && error.code === -32601);
|
|
563
|
+
}
|
|
564
|
+
function agentMethodNotFoundError(backendId, method, label, cause) {
|
|
565
|
+
return new WorkflowError(`ACP agent (${backendId}) does not implement ${method}: ${thrownMessage(cause)}`, WorkflowErrorCode.SCRIPT_VALIDATION_ERROR, { recoverable: false, agentLabel: label, details: cause });
|
|
566
|
+
}
|
|
455
567
|
function thrownMessage(error) {
|
|
456
568
|
if (error instanceof Error)
|
|
457
569
|
return error.message;
|
|
@@ -479,6 +591,11 @@ function layerMeta(...layers) {
|
|
|
479
591
|
return undefined;
|
|
480
592
|
return Object.assign({}, ...present);
|
|
481
593
|
}
|
|
594
|
+
function acpMcpServerIds(servers) {
|
|
595
|
+
return servers
|
|
596
|
+
?.filter((server) => "type" in server && server.type === "acp")
|
|
597
|
+
.map((server) => server.serverId) ?? [];
|
|
598
|
+
}
|
|
482
599
|
/** Merge the engine runId correlation stamp into a backend's session/new `_meta`. Returns the
|
|
483
600
|
* meta unchanged when no runId is given (so a backend that sends no `_meta` keeps sending none). */
|
|
484
601
|
function stampRunId(meta, runId) {
|
|
@@ -583,6 +700,10 @@ export class PooledConnection {
|
|
|
583
700
|
.onRequest(CLIENT_METHODS.terminal_release, ({ params }) => this.client.releaseTerminal(params))
|
|
584
701
|
.onRequest(CLIENT_METHODS.terminal_wait_for_exit, ({ params }) => this.client.waitForTerminalExit(params))
|
|
585
702
|
.onRequest(CLIENT_METHODS.terminal_kill, ({ params }) => this.client.killTerminal(params))
|
|
703
|
+
.onRequest(CLIENT_METHODS.mcp_connect, parseConnectMcpRequest, ({ params }) => this.client.mcpConnect(params))
|
|
704
|
+
.onRequest(CLIENT_METHODS.mcp_message, parseMessageMcpRequest, ({ params }) => this.client.mcpMessage(params))
|
|
705
|
+
.onRequest(CLIENT_METHODS.mcp_disconnect, parseDisconnectMcpRequest, ({ params }) => this.client.mcpDisconnect(params))
|
|
706
|
+
.onNotification(CLIENT_METHODS.mcp_message, parseMessageMcpNotification, ({ params }) => this.client.mcpMessageNotification(params))
|
|
586
707
|
.connect(stream);
|
|
587
708
|
// Death detection. The connection's `signal` aborts the INSTANT the underlying stream closes
|
|
588
709
|
// (process crash or our own dispose) — in the SAME close() that rejects pending requests — so
|
|
@@ -622,10 +743,16 @@ export class PooledConnection {
|
|
|
622
743
|
}
|
|
623
744
|
assertSupportedMcpServers(opts) {
|
|
624
745
|
const unsupported = this.negotiated
|
|
625
|
-
? unsupportedMcpServer(opts.mcpServers, this.negotiated.agent
|
|
746
|
+
? unsupportedMcpServer(opts.mcpServers, this.negotiated.agent, {
|
|
747
|
+
clientCanServeAcp: hasFullMcpHandlers(this.clientHandlers?.mcp),
|
|
748
|
+
})
|
|
626
749
|
: undefined;
|
|
627
750
|
if (!unsupported)
|
|
628
751
|
return;
|
|
752
|
+
if (unsupported.reason === "client") {
|
|
753
|
+
throw new WorkflowError(`MCP server "${unsupported.name}" uses the "acp" transport, but this runner has no ` +
|
|
754
|
+
"complete clientHandlers.mcp implementation to serve it", WorkflowErrorCode.SCRIPT_VALIDATION_ERROR, { recoverable: false, agentLabel: opts.label });
|
|
755
|
+
}
|
|
629
756
|
throw new WorkflowError(`MCP server "${unsupported.name}" uses the "${unsupported.transport}" transport, which the ` +
|
|
630
757
|
`${this.backendId} agent does not support`, WorkflowErrorCode.SCRIPT_VALIDATION_ERROR, { recoverable: false, agentLabel: opts.label });
|
|
631
758
|
}
|
|
@@ -649,6 +776,18 @@ export class PooledConnection {
|
|
|
649
776
|
return;
|
|
650
777
|
throw lifecycleCapabilityError(this.backendId, method, this.negotiated, label);
|
|
651
778
|
}
|
|
779
|
+
assertAuthProviderSupported(method, label) {
|
|
780
|
+
const supported = method === AGENT_METHODS.logout
|
|
781
|
+
? this.negotiated?.supportsLogout
|
|
782
|
+
: method === AGENT_METHODS.providers_list ||
|
|
783
|
+
method === AGENT_METHODS.providers_set ||
|
|
784
|
+
method === AGENT_METHODS.providers_disable
|
|
785
|
+
? this.negotiated?.supportsProviders
|
|
786
|
+
: true;
|
|
787
|
+
if (supported)
|
|
788
|
+
return;
|
|
789
|
+
throw authProviderCapabilityError(this.backendId, method, this.negotiated, label);
|
|
790
|
+
}
|
|
652
791
|
/** Mark this connection dead exactly once, then ask the pool to evict it. Idempotent. */
|
|
653
792
|
die(error) {
|
|
654
793
|
if (!this._alive)
|
|
@@ -658,6 +797,7 @@ export class PooledConnection {
|
|
|
658
797
|
this.resolveDead();
|
|
659
798
|
this.client.settleAllPendingPermissions();
|
|
660
799
|
this.client.settleAllPendingElicitations();
|
|
800
|
+
this.client.disconnectAllMcpConnections();
|
|
661
801
|
// A crash (not a graceful dispose) is worth surfacing for observability; the engine still
|
|
662
802
|
// handles it by retrying the run on a fresh process. Best-effort, after death is recorded.
|
|
663
803
|
if (this.onEvent && !this.disposing) {
|
|
@@ -754,7 +894,7 @@ export class PooledConnection {
|
|
|
754
894
|
...(meta ? { _meta: meta } : {}),
|
|
755
895
|
};
|
|
756
896
|
const response = await this.race(this.connection.agent.request(AGENT_METHODS.session_new, request));
|
|
757
|
-
const state = new SessionState(opts.cwd, opts.policy, opts.permissionResolver, opts.elicitationResolver, opts.label, opts.runId, response.modes, opts.retainSessionLog ?? true);
|
|
897
|
+
const state = new SessionState(opts.cwd, opts.policy, opts.permissionResolver, opts.elicitationResolver, opts.label, opts.runId, response.modes, acpMcpServerIds(opts.mcpServers), opts.retainSessionLog ?? true);
|
|
758
898
|
this.client.register(response.sessionId, state);
|
|
759
899
|
return new SessionHandle(this, response.sessionId, state, response.configOptions ?? [], opts);
|
|
760
900
|
}
|
|
@@ -772,16 +912,17 @@ export class PooledConnection {
|
|
|
772
912
|
return this.reattachSession(AGENT_METHODS.session_resume, sessionId, opts);
|
|
773
913
|
}
|
|
774
914
|
rawAgentRequest(method, params) {
|
|
775
|
-
// SDK
|
|
776
|
-
//
|
|
777
|
-
//
|
|
915
|
+
// Some SDK ClientContext convenience methods collapse responses through emptyObjectResponse
|
|
916
|
+
// (session/load in 1.2.0, plus auth/provider methods with optional _meta). Driven wrappers
|
|
917
|
+
// need the wire response as-is. This bypasses only the SDK response mapper, not JSON-RPC
|
|
918
|
+
// validation/racing.
|
|
778
919
|
const agent = this.connection.agent;
|
|
779
920
|
return this.race(agent.sendRequest(method, params));
|
|
780
921
|
}
|
|
781
922
|
async reattachSession(method, sessionId, opts) {
|
|
782
923
|
this._activeSessions += 1;
|
|
783
924
|
let registered = false;
|
|
784
|
-
const state = new SessionState(opts.cwd, opts.policy, opts.permissionResolver, opts.elicitationResolver, opts.label, opts.runId, undefined, opts.retainSessionLog ?? true);
|
|
925
|
+
const state = new SessionState(opts.cwd, opts.policy, opts.permissionResolver, opts.elicitationResolver, opts.label, opts.runId, undefined, acpMcpServerIds(opts.mcpServers), opts.retainSessionLog ?? true);
|
|
785
926
|
try {
|
|
786
927
|
await this.ready;
|
|
787
928
|
this.assertLifecycleSupported(method, opts.label);
|
|
@@ -828,6 +969,76 @@ export class PooledConnection {
|
|
|
828
969
|
this.assertLifecycleSupported(AGENT_METHODS.session_delete, label);
|
|
829
970
|
await this.race(this.connection.agent.request(AGENT_METHODS.session_delete, request));
|
|
830
971
|
}
|
|
972
|
+
/** Authentication methods advertised in initialize, available without opening a session. */
|
|
973
|
+
async authMethods() {
|
|
974
|
+
await this.ready;
|
|
975
|
+
return [...(this.negotiated?.authMethods ?? [])];
|
|
976
|
+
}
|
|
977
|
+
/** authenticate has no AgentCapabilities gate; authMethods advertises choices, not method support. */
|
|
978
|
+
async authenticate(request, label) {
|
|
979
|
+
await this.ready;
|
|
980
|
+
try {
|
|
981
|
+
return await this.rawAgentRequest(AGENT_METHODS.authenticate, request);
|
|
982
|
+
}
|
|
983
|
+
catch (error) {
|
|
984
|
+
if (isMethodNotFound(error))
|
|
985
|
+
throw agentMethodNotFoundError(this.backendId, AGENT_METHODS.authenticate, label, error);
|
|
986
|
+
throw error;
|
|
987
|
+
}
|
|
988
|
+
}
|
|
989
|
+
/** providers/list on a dedicated connection, gated on the unstable providers advertisement. */
|
|
990
|
+
async listProviders(request, label) {
|
|
991
|
+
await this.ready;
|
|
992
|
+
this.assertAuthProviderSupported(AGENT_METHODS.providers_list, label);
|
|
993
|
+
try {
|
|
994
|
+
return await this.rawAgentRequest(AGENT_METHODS.providers_list, request);
|
|
995
|
+
}
|
|
996
|
+
catch (error) {
|
|
997
|
+
if (isMethodNotFound(error))
|
|
998
|
+
throw agentMethodNotFoundError(this.backendId, AGENT_METHODS.providers_list, label, error);
|
|
999
|
+
throw error;
|
|
1000
|
+
}
|
|
1001
|
+
}
|
|
1002
|
+
/** providers/set on a dedicated connection, gated on the unstable providers advertisement. */
|
|
1003
|
+
async setProvider(request, label) {
|
|
1004
|
+
await this.ready;
|
|
1005
|
+
this.assertAuthProviderSupported(AGENT_METHODS.providers_set, label);
|
|
1006
|
+
try {
|
|
1007
|
+
return await this.rawAgentRequest(AGENT_METHODS.providers_set, request);
|
|
1008
|
+
}
|
|
1009
|
+
catch (error) {
|
|
1010
|
+
if (isMethodNotFound(error))
|
|
1011
|
+
throw agentMethodNotFoundError(this.backendId, AGENT_METHODS.providers_set, label, error);
|
|
1012
|
+
throw error;
|
|
1013
|
+
}
|
|
1014
|
+
}
|
|
1015
|
+
/** providers/disable on a dedicated connection, gated on the unstable providers advertisement. */
|
|
1016
|
+
async disableProvider(request, label) {
|
|
1017
|
+
await this.ready;
|
|
1018
|
+
this.assertAuthProviderSupported(AGENT_METHODS.providers_disable, label);
|
|
1019
|
+
try {
|
|
1020
|
+
return await this.rawAgentRequest(AGENT_METHODS.providers_disable, request);
|
|
1021
|
+
}
|
|
1022
|
+
catch (error) {
|
|
1023
|
+
if (isMethodNotFound(error)) {
|
|
1024
|
+
throw agentMethodNotFoundError(this.backendId, AGENT_METHODS.providers_disable, label, error);
|
|
1025
|
+
}
|
|
1026
|
+
throw error;
|
|
1027
|
+
}
|
|
1028
|
+
}
|
|
1029
|
+
/** logout on a dedicated connection, gated on agentCapabilities.auth.logout. */
|
|
1030
|
+
async logout(request, label) {
|
|
1031
|
+
await this.ready;
|
|
1032
|
+
this.assertAuthProviderSupported(AGENT_METHODS.logout, label);
|
|
1033
|
+
try {
|
|
1034
|
+
return await this.rawAgentRequest(AGENT_METHODS.logout, request);
|
|
1035
|
+
}
|
|
1036
|
+
catch (error) {
|
|
1037
|
+
if (isMethodNotFound(error))
|
|
1038
|
+
throw agentMethodNotFoundError(this.backendId, AGENT_METHODS.logout, label, error);
|
|
1039
|
+
throw error;
|
|
1040
|
+
}
|
|
1041
|
+
}
|
|
831
1042
|
/** session/prompt on this connection, raced against process death. */
|
|
832
1043
|
prompt(request) {
|
|
833
1044
|
return this.race(this.connection.agent.request(AGENT_METHODS.session_prompt, request));
|
|
@@ -971,6 +1182,10 @@ export class SessionHandle {
|
|
|
971
1182
|
get modes() {
|
|
972
1183
|
return this.state.modes;
|
|
973
1184
|
}
|
|
1185
|
+
/** The connection-level initialize response parsed before this session was opened. */
|
|
1186
|
+
get capabilities() {
|
|
1187
|
+
return this.pooled.capabilities;
|
|
1188
|
+
}
|
|
974
1189
|
/**
|
|
975
1190
|
* Select the model for this session from the agent-advertised config options (§5.4).
|
|
976
1191
|
* Returns `matched:false` (the caller fires onModelFallback) when the catalog has no value
|
package/dist/capabilities.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type AgentCapabilities, type ContentBlock, type Implementation, type InitializeResponse } from "@agentclientprotocol/sdk";
|
|
1
|
+
import { type AgentCapabilities, type AuthMethod, type ContentBlock, type Implementation, type InitializeResponse } from "@agentclientprotocol/sdk";
|
|
2
2
|
import { type McpServerConfig } from "@automatalabs/shared-types";
|
|
3
3
|
import type { Backend } from "./backend.js";
|
|
4
4
|
/** The bare `_meta` keys whose emission is gated by Codex's custom-capability advertisement.
|
|
@@ -16,6 +16,10 @@ export interface NegotiatedCapabilities {
|
|
|
16
16
|
agent: AgentCapabilities;
|
|
17
17
|
/** The agent's self-identification, when it sent agentInfo. */
|
|
18
18
|
agentInfo: Implementation | undefined;
|
|
19
|
+
/** Authentication methods advertised by the agent in initialize, defaulting to [] when absent. */
|
|
20
|
+
authMethods: AuthMethod[];
|
|
21
|
+
/** Initialize-response `_meta`, when the agent sent it. */
|
|
22
|
+
initializeMeta: InitializeResponse["_meta"] | undefined;
|
|
19
23
|
/** Whether session/close is advertised (gates the best-effort release-time close). */
|
|
20
24
|
supportsClose: boolean;
|
|
21
25
|
/** Whether session/load is advertised. The current SDK keeps this as the legacy top-level
|
|
@@ -27,6 +31,10 @@ export interface NegotiatedCapabilities {
|
|
|
27
31
|
supportsDeleteSession: boolean;
|
|
28
32
|
/** Whether session/resume is advertised. */
|
|
29
33
|
supportsResumeSession: boolean;
|
|
34
|
+
/** Whether logout is advertised under agentCapabilities.auth.logout. */
|
|
35
|
+
supportsLogout: boolean;
|
|
36
|
+
/** Whether the unstable provider-configuration block is advertised. */
|
|
37
|
+
supportsProviders: boolean;
|
|
30
38
|
/** The parsed backend-declared custom-capability block (the namespaced `_meta` object), or
|
|
31
39
|
* undefined when the backend declared none or the agent did not advertise it — passthrough. */
|
|
32
40
|
customMetaSupport: Record<string, unknown> | undefined;
|
|
@@ -38,6 +46,8 @@ export interface NegotiatedCapabilities {
|
|
|
38
46
|
export declare function negotiateCapabilities(response: InitializeResponse, customCapabilities?: Backend["customCapabilities"]): NegotiatedCapabilities;
|
|
39
47
|
/** Human-readable lifecycle advertisement summary for strict wrapper gate errors. */
|
|
40
48
|
export declare function describeLifecycleAdvertisement(agent: AgentCapabilities): string;
|
|
49
|
+
/** Human-readable auth/provider advertisement summary for strict wrapper gate errors. */
|
|
50
|
+
export declare function describeAuthProviderAdvertisement(agent: AgentCapabilities, authMethods?: readonly AuthMethod[]): string;
|
|
41
51
|
/** True only when the agent selected EXACTLY PROTOCOL_VERSION. This client implements that one wire
|
|
42
52
|
* version and adapts its behavior to no other, so any other selected version — older or newer —
|
|
43
53
|
* means close the connection per the ACP spec's SHOULD-close rule. Per the spec the agent echoes
|
|
@@ -56,13 +66,16 @@ export declare function gateCustomMeta(meta: Record<string, unknown> | undefined
|
|
|
56
66
|
* bracketed text notes so context is never silently lost. Returns the SAME array reference when
|
|
57
67
|
* no block changes and never mutates the input or any surviving block. */
|
|
58
68
|
export declare function adaptPromptContent(blocks: ContentBlock[], agent: AgentCapabilities, backendId: string): ContentBlock[];
|
|
59
|
-
/** The first client-provided MCP server whose transport
|
|
60
|
-
*
|
|
61
|
-
*
|
|
62
|
-
*
|
|
63
|
-
*
|
|
64
|
-
export declare function unsupportedMcpServer(servers: McpServerConfig[] | undefined, agent: AgentCapabilities
|
|
69
|
+
/** The first client-provided MCP server whose transport cannot be served, or undefined when every
|
|
70
|
+
* server is serviceable. stdio is ALWAYS serviceable (the baseline transport); http/sse keep the
|
|
71
|
+
* legacy leniency and gate only after any mcpCapabilities block exists. ACP transport is stricter:
|
|
72
|
+
* both sides must be explicit because the client is the MCP server host and an unwired declaration
|
|
73
|
+
* would otherwise spend tokens before failing at mcp/connect. */
|
|
74
|
+
export declare function unsupportedMcpServer(servers: McpServerConfig[] | undefined, agent: AgentCapabilities, options?: {
|
|
75
|
+
clientCanServeAcp?: boolean;
|
|
76
|
+
}): {
|
|
65
77
|
name: string;
|
|
66
|
-
transport: "http" | "sse";
|
|
78
|
+
transport: "http" | "sse" | "acp";
|
|
79
|
+
reason?: "client";
|
|
67
80
|
} | undefined;
|
|
68
81
|
//# sourceMappingURL=capabilities.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"capabilities.d.ts","sourceRoot":"","sources":["../src/capabilities.ts"],"names":[],"mappings":"AAkBA,OAAO,EAEL,KAAK,iBAAiB,EACtB,KAAK,YAAY,EACjB,KAAK,cAAc,EACnB,KAAK,kBAAkB,EACxB,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAGL,KAAK,eAAe,EACrB,MAAM,4BAA4B,CAAC;AACpC,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAQ5C;;;iGAGiG;AACjG,eAAO,MAAM,sBAAsB,EAAE,SAAS,MAAM,EAInD,CAAC;AAEF,qFAAqF;AACrF,MAAM,WAAW,sBAAsB;IACrC;0FACsF;IACtF,eAAe,EAAE,MAAM,CAAC;IACxB;4DACwD;IACxD,KAAK,EAAE,iBAAiB,CAAC;IACzB,+DAA+D;IAC/D,SAAS,EAAE,cAAc,GAAG,SAAS,CAAC;IACtC,sFAAsF;IACtF,aAAa,EAAE,OAAO,CAAC;IACvB;mGAC+F;IAC/F,mBAAmB,EAAE,OAAO,CAAC;IAC7B,0CAA0C;IAC1C,oBAAoB,EAAE,OAAO,CAAC;IAC9B,4CAA4C;IAC5C,qBAAqB,EAAE,OAAO,CAAC;IAC/B,4CAA4C;IAC5C,qBAAqB,EAAE,OAAO,CAAC;IAC/B;oGACgG;IAChG,iBAAiB,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,CAAC;IACvD;+EAC2E;IAC3E,SAAS,EAAE,SAAS,MAAM,EAAE,GAAG,SAAS,CAAC;CAC1C;AAED,mFAAmF;AACnF,wBAAgB,qBAAqB,CACnC,QAAQ,EAAE,kBAAkB,EAC5B,kBAAkB,CAAC,EAAE,OAAO,CAAC,oBAAoB,CAAC,GACjD,sBAAsB,
|
|
1
|
+
{"version":3,"file":"capabilities.d.ts","sourceRoot":"","sources":["../src/capabilities.ts"],"names":[],"mappings":"AAkBA,OAAO,EAEL,KAAK,iBAAiB,EACtB,KAAK,UAAU,EACf,KAAK,YAAY,EACjB,KAAK,cAAc,EACnB,KAAK,kBAAkB,EACxB,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAGL,KAAK,eAAe,EACrB,MAAM,4BAA4B,CAAC;AACpC,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAQ5C;;;iGAGiG;AACjG,eAAO,MAAM,sBAAsB,EAAE,SAAS,MAAM,EAInD,CAAC;AAEF,qFAAqF;AACrF,MAAM,WAAW,sBAAsB;IACrC;0FACsF;IACtF,eAAe,EAAE,MAAM,CAAC;IACxB;4DACwD;IACxD,KAAK,EAAE,iBAAiB,CAAC;IACzB,+DAA+D;IAC/D,SAAS,EAAE,cAAc,GAAG,SAAS,CAAC;IACtC,kGAAkG;IAClG,WAAW,EAAE,UAAU,EAAE,CAAC;IAC1B,2DAA2D;IAC3D,cAAc,EAAE,kBAAkB,CAAC,OAAO,CAAC,GAAG,SAAS,CAAC;IACxD,sFAAsF;IACtF,aAAa,EAAE,OAAO,CAAC;IACvB;mGAC+F;IAC/F,mBAAmB,EAAE,OAAO,CAAC;IAC7B,0CAA0C;IAC1C,oBAAoB,EAAE,OAAO,CAAC;IAC9B,4CAA4C;IAC5C,qBAAqB,EAAE,OAAO,CAAC;IAC/B,4CAA4C;IAC5C,qBAAqB,EAAE,OAAO,CAAC;IAC/B,wEAAwE;IACxE,cAAc,EAAE,OAAO,CAAC;IACxB,uEAAuE;IACvE,iBAAiB,EAAE,OAAO,CAAC;IAC3B;oGACgG;IAChG,iBAAiB,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,CAAC;IACvD;+EAC2E;IAC3E,SAAS,EAAE,SAAS,MAAM,EAAE,GAAG,SAAS,CAAC;CAC1C;AAED,mFAAmF;AACnF,wBAAgB,qBAAqB,CACnC,QAAQ,EAAE,kBAAkB,EAC5B,kBAAkB,CAAC,EAAE,OAAO,CAAC,oBAAoB,CAAC,GACjD,sBAAsB,CAsBxB;AAMD,qFAAqF;AACrF,wBAAgB,8BAA8B,CAAC,KAAK,EAAE,iBAAiB,GAAG,MAAM,CAiB/E;AAED,yFAAyF;AACzF,wBAAgB,iCAAiC,CAC/C,KAAK,EAAE,iBAAiB,EACxB,WAAW,GAAE,SAAS,UAAU,EAAO,GACtC,MAAM,CAOR;AAaD;;;;+DAI+D;AAC/D,wBAAgB,0BAA0B,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAEnE;AAED;;;gEAGgE;AAChE,wBAAgB,cAAc,CAC5B,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,EACzC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,EAC5C,SAAS,GAAE,SAAS,MAAM,EAA2B,GACpD,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,CAWrC;AAED;;;;;2EAK2E;AAC3E,wBAAgB,kBAAkB,CAChC,MAAM,EAAE,YAAY,EAAE,EACtB,KAAK,EAAE,iBAAiB,EACxB,SAAS,EAAE,MAAM,GAChB,YAAY,EAAE,CAchB;AAkCD;;;;kEAIkE;AAClE,wBAAgB,oBAAoB,CAClC,OAAO,EAAE,eAAe,EAAE,GAAG,SAAS,EACtC,KAAK,EAAE,iBAAiB,EACxB,OAAO,GAAE;IAAE,iBAAiB,CAAC,EAAE,OAAO,CAAA;CAAO,GAC5C;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,GAAG,KAAK,GAAG,KAAK,CAAC;IAAC,MAAM,CAAC,EAAE,QAAQ,CAAA;CAAE,GAAG,SAAS,CAkBpF"}
|
package/dist/capabilities.js
CHANGED
|
@@ -40,11 +40,15 @@ export function negotiateCapabilities(response, customCapabilities) {
|
|
|
40
40
|
protocolVersion: response.protocolVersion,
|
|
41
41
|
agent,
|
|
42
42
|
agentInfo: response.agentInfo ?? undefined,
|
|
43
|
+
authMethods: response.authMethods ?? [],
|
|
44
|
+
initializeMeta: response._meta ?? undefined,
|
|
43
45
|
supportsClose: advertised(sessionCapabilities?.close),
|
|
44
46
|
supportsLoadSession: agent.loadSession === true || advertised(sessionCapabilities?.load),
|
|
45
47
|
supportsListSessions: advertised(sessionCapabilities?.list),
|
|
46
48
|
supportsDeleteSession: advertised(sessionCapabilities?.delete),
|
|
47
49
|
supportsResumeSession: advertised(sessionCapabilities?.resume),
|
|
50
|
+
supportsLogout: advertised(agent.auth?.logout),
|
|
51
|
+
supportsProviders: advertised(agent.providers),
|
|
48
52
|
customMetaSupport: customCapabilities
|
|
49
53
|
? readCustomNamespace(agent._meta, customCapabilities.namespace)
|
|
50
54
|
: undefined,
|
|
@@ -73,6 +77,15 @@ export function describeLifecycleAdvertisement(agent) {
|
|
|
73
77
|
`sessionCapabilities=${session.length > 0 ? session.join(", ") : "none"}`,
|
|
74
78
|
].join("; ");
|
|
75
79
|
}
|
|
80
|
+
/** Human-readable auth/provider advertisement summary for strict wrapper gate errors. */
|
|
81
|
+
export function describeAuthProviderAdvertisement(agent, authMethods = []) {
|
|
82
|
+
const methodIds = authMethods.map((method) => method.id).filter(Boolean);
|
|
83
|
+
return [
|
|
84
|
+
`authMethods=${methodIds.length > 0 ? methodIds.join(", ") : "none"}`,
|
|
85
|
+
`auth.logout=${advertised(agent.auth?.logout) ? "true" : "false"}`,
|
|
86
|
+
`providers=${advertised(agent.providers) ? "true" : "false"}`,
|
|
87
|
+
].join("; ");
|
|
88
|
+
}
|
|
76
89
|
function readCustomNamespace(meta, namespace) {
|
|
77
90
|
if (!meta || typeof meta !== "object")
|
|
78
91
|
return undefined;
|
|
@@ -153,22 +166,28 @@ function unsupportedPromptBlockNote(block, agent, backendId) {
|
|
|
153
166
|
return undefined;
|
|
154
167
|
}
|
|
155
168
|
}
|
|
156
|
-
/** The first client-provided MCP server whose transport
|
|
157
|
-
*
|
|
158
|
-
*
|
|
159
|
-
*
|
|
160
|
-
*
|
|
161
|
-
export function unsupportedMcpServer(servers, agent) {
|
|
169
|
+
/** The first client-provided MCP server whose transport cannot be served, or undefined when every
|
|
170
|
+
* server is serviceable. stdio is ALWAYS serviceable (the baseline transport); http/sse keep the
|
|
171
|
+
* legacy leniency and gate only after any mcpCapabilities block exists. ACP transport is stricter:
|
|
172
|
+
* both sides must be explicit because the client is the MCP server host and an unwired declaration
|
|
173
|
+
* would otherwise spend tokens before failing at mcp/connect. */
|
|
174
|
+
export function unsupportedMcpServer(servers, agent, options = {}) {
|
|
162
175
|
const mcp = agent.mcpCapabilities;
|
|
163
|
-
if (!
|
|
176
|
+
if (!servers)
|
|
164
177
|
return undefined;
|
|
165
178
|
for (const server of servers) {
|
|
166
|
-
if ("type" in server && server.type === "http" && mcp.http !== true) {
|
|
179
|
+
if ("type" in server && server.type === "http" && mcp && mcp.http !== true) {
|
|
167
180
|
return { name: server.name, transport: "http" };
|
|
168
181
|
}
|
|
169
|
-
if ("type" in server && server.type === "sse" && mcp.sse !== true) {
|
|
182
|
+
if ("type" in server && server.type === "sse" && mcp && mcp.sse !== true) {
|
|
170
183
|
return { name: server.name, transport: "sse" };
|
|
171
184
|
}
|
|
185
|
+
if ("type" in server && server.type === "acp" && mcp?.acp !== true) {
|
|
186
|
+
return { name: server.name, transport: "acp" };
|
|
187
|
+
}
|
|
188
|
+
if ("type" in server && server.type === "acp" && options.clientCanServeAcp !== true) {
|
|
189
|
+
return { name: server.name, transport: "acp", reason: "client" };
|
|
190
|
+
}
|
|
172
191
|
}
|
|
173
192
|
return undefined;
|
|
174
193
|
}
|