@pwrdrvr/agent-acp 0.8.0 → 0.9.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/index.d.ts +43 -13
- package/dist/index.js +226 -83
- package/dist/index.js.map +1 -1
- package/package.json +2 -1
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
+
import { Client } from '@zed-industries/agent-client-protocol';
|
|
1
2
|
import { Logger, AgentBackend, NormalizedThreadEvent, Unsubscribe, AgentBackendToolCallHandler, AgentBackendApprovalHandler, AgentStartThreadOptions, AgentBackendStartThreadResult, AgentStartTurnOptions, NormalizedTokenUsage, NormalizedToolCall } from '@pwrdrvr/agent-core';
|
|
2
|
-
import { JsonRpcId
|
|
3
|
+
import { JsonRpcId } from '@pwrdrvr/agent-transport';
|
|
3
4
|
|
|
4
|
-
/** The bidirectional transport shape the ACP client drives. */
|
|
5
5
|
interface AcpJsonRpcTransport {
|
|
6
6
|
request(method: string, params?: Record<string, unknown>, timeoutMs?: number): Promise<unknown>;
|
|
7
7
|
notify?(method: string, params?: Record<string, unknown>): Promise<void>;
|
|
@@ -9,23 +9,53 @@ interface AcpJsonRpcTransport {
|
|
|
9
9
|
onNotification(listener: (method: string, params: Record<string, unknown>) => void): () => void;
|
|
10
10
|
onRequest?(listener: (method: string, params: Record<string, unknown>, id?: JsonRpcId) => Promise<unknown> | unknown): () => void;
|
|
11
11
|
}
|
|
12
|
-
|
|
12
|
+
|
|
13
|
+
/** The subset of the library's client→agent surface that `AcpConnection`
|
|
14
|
+
* drives. Injectable (via `createConnection`) so the adapter can be unit-tested
|
|
15
|
+
* without spawning a real agent. The library's `ClientSideConnection` satisfies
|
|
16
|
+
* this structurally (its methods take typed schema params; we pass records that
|
|
17
|
+
* match at runtime). */
|
|
18
|
+
interface AcpAgentConnection {
|
|
19
|
+
initialize(params: Record<string, unknown>): Promise<unknown>;
|
|
20
|
+
newSession(params: Record<string, unknown>): Promise<unknown>;
|
|
21
|
+
loadSession(params: Record<string, unknown>): Promise<unknown>;
|
|
22
|
+
prompt(params: Record<string, unknown>): Promise<unknown>;
|
|
23
|
+
cancel(params: Record<string, unknown>): Promise<void>;
|
|
24
|
+
setSessionMode(params: Record<string, unknown>): Promise<unknown>;
|
|
25
|
+
setSessionModel(params: Record<string, unknown>): Promise<unknown>;
|
|
26
|
+
authenticate(params: Record<string, unknown>): Promise<unknown>;
|
|
27
|
+
extMethod(method: string, params: Record<string, unknown>): Promise<Record<string, unknown>>;
|
|
28
|
+
extNotification(method: string, params: Record<string, unknown>): Promise<void>;
|
|
29
|
+
}
|
|
30
|
+
/** Built connection + a teardown handle (kills the child / closes streams). */
|
|
31
|
+
type AcpAgentConnectionHandle = {
|
|
32
|
+
connection: AcpAgentConnection;
|
|
33
|
+
dispose: () => void;
|
|
34
|
+
};
|
|
35
|
+
type AcpConnectionOptions = {
|
|
13
36
|
command: string;
|
|
14
37
|
args: string[];
|
|
15
38
|
env?: NodeJS.ProcessEnv;
|
|
16
|
-
requestTimeoutMs?: number;
|
|
17
|
-
observer?: JsonRpcObserver;
|
|
18
39
|
logger?: Logger;
|
|
19
|
-
/**
|
|
20
|
-
|
|
40
|
+
/** Test seam: build the underlying connection. Defaults to spawning the agent
|
|
41
|
+
* and wiring its stdio through the library's `ClientSideConnection`. */
|
|
42
|
+
createConnection?: (client: Client) => AcpAgentConnectionHandle;
|
|
21
43
|
};
|
|
22
|
-
declare class
|
|
23
|
-
private readonly
|
|
44
|
+
declare class AcpConnection implements AcpJsonRpcTransport {
|
|
45
|
+
private readonly options;
|
|
46
|
+
private readonly logger;
|
|
47
|
+
private connection;
|
|
48
|
+
private dispose;
|
|
49
|
+
private connecting;
|
|
24
50
|
private readonly notificationListeners;
|
|
25
51
|
private requestHandler;
|
|
26
|
-
constructor(options:
|
|
27
|
-
|
|
28
|
-
|
|
52
|
+
constructor(options: AcpConnectionOptions);
|
|
53
|
+
/** The `Client` handler the library invokes for agent→client traffic. */
|
|
54
|
+
private buildClient;
|
|
55
|
+
private ensureConnected;
|
|
56
|
+
private connect;
|
|
57
|
+
private defaultCreateConnection;
|
|
58
|
+
request(method: string, params?: Record<string, unknown>, _timeoutMs?: number): Promise<unknown>;
|
|
29
59
|
notify(method: string, params?: Record<string, unknown>): Promise<void>;
|
|
30
60
|
close(): Promise<void>;
|
|
31
61
|
onNotification(listener: (method: string, params: Record<string, unknown>) => void): () => void;
|
|
@@ -757,4 +787,4 @@ declare class AcpRegistryService {
|
|
|
757
787
|
declare function evaluateAcpDistributionPolicy(distribution: AcpRegistryDistribution, allowlist: AcpAllowlistDecision): AcpDistributionPolicy;
|
|
758
788
|
declare function normalizeRegistry(raw: unknown): AcpRegistryAgent[];
|
|
759
789
|
|
|
760
|
-
export { ACP_REGISTRY_URL, AcpAgentAllowlist, type AcpAgentAllowlistRule, AcpAgentClient, type AcpAgentClientFactory, type AcpAgentClientOptions, AcpAgentClientPool, type AcpAgentClientPoolOptions, type AcpAgentInstanceSource, type AcpAgentQuirks, type AcpAgentStrategy, type AcpAllowlistDecision, type AcpApplyContext, type AcpBinaryPlatformDistribution, type AcpDiscoveryProbe, type AcpDistributionKind, type AcpDistributionPolicy, type AcpJsonRpcTransport, type AcpMcpServerConfig, type AcpNormalizeResult, type AcpNormalizerOptions, AcpOneShotClient, type AcpOneShotClientOptions, type AcpOneShotRequest, type AcpOneShotResponse, type AcpPackageDistribution, type AcpPathExecutableLister, type AcpPromptContentBlock, type AcpRegistryAgent, type AcpRegistryAgentWithPolicy, type AcpRegistryAuthDescriptor, type AcpRegistryAuthMethod, type AcpRegistryDistribution, type AcpRegistryFetch, AcpRegistryService, type AcpRegistryServiceOptions, type AcpRegistrySnapshot, type AcpRuntimeAgentCapabilities, type AcpRuntimeAgentInfo, type AcpRuntimeCapabilities, type AcpRuntimeCapabilitiesHandler, type AcpRuntimeCapabilitiesSource, type AcpRuntimeConfigOption, type AcpRuntimeConfigOptionValue, type AcpRuntimeMode, type AcpRuntimeModel, type AcpRuntimeModels, type AcpRuntimeModes, type AcpRuntimeOptionSource, AcpSessionNormalizer, type AcpSessionRuntimeState, type AcpSpawnSpec, type AcpStartThreadOptions, type AcpStartTurnOptions,
|
|
790
|
+
export { ACP_REGISTRY_URL, AcpAgentAllowlist, type AcpAgentAllowlistRule, AcpAgentClient, type AcpAgentClientFactory, type AcpAgentClientOptions, AcpAgentClientPool, type AcpAgentClientPoolOptions, type AcpAgentConnection, type AcpAgentConnectionHandle, type AcpAgentInstanceSource, type AcpAgentQuirks, type AcpAgentStrategy, type AcpAllowlistDecision, type AcpApplyContext, type AcpBinaryPlatformDistribution, AcpConnection, type AcpConnectionOptions, type AcpDiscoveryProbe, type AcpDistributionKind, type AcpDistributionPolicy, type AcpJsonRpcTransport, type AcpMcpServerConfig, type AcpNormalizeResult, type AcpNormalizerOptions, AcpOneShotClient, type AcpOneShotClientOptions, type AcpOneShotRequest, type AcpOneShotResponse, type AcpPackageDistribution, type AcpPathExecutableLister, type AcpPromptContentBlock, type AcpRegistryAgent, type AcpRegistryAgentWithPolicy, type AcpRegistryAuthDescriptor, type AcpRegistryAuthMethod, type AcpRegistryDistribution, type AcpRegistryFetch, AcpRegistryService, type AcpRegistryServiceOptions, type AcpRegistrySnapshot, type AcpRuntimeAgentCapabilities, type AcpRuntimeAgentInfo, type AcpRuntimeCapabilities, type AcpRuntimeCapabilitiesHandler, type AcpRuntimeCapabilitiesSource, type AcpRuntimeConfigOption, type AcpRuntimeConfigOptionValue, type AcpRuntimeMode, type AcpRuntimeModel, type AcpRuntimeModels, type AcpRuntimeModes, type AcpRuntimeOptionSource, AcpSessionNormalizer, type AcpSessionRuntimeState, type AcpSpawnSpec, type AcpStartThreadOptions, type AcpStartTurnOptions, type AcpTitleHandler, type AcpVerificationStatus, BANNED_ACP_REGISTRY_IDS, BUILT_IN_ACP_STRATEGIES, DEFAULT_ACP_AGENT_ALLOWLIST, type DiscoveredAcpAgent, type DiscoveredAcpAgentGroup, type DiscoveredAcpAgentInstance, type LocalAcpAgentProbe, type LocalAcpDiscoveryOptions, type LocalAcpProbeResult, acpRuntimeSupportsSessionLoad, acpSessionRuntimeStateFromCapabilities, acpSessionRuntimeStateFromUpdate, asRecord, buildAcpBackendId, buildStrategyTable, defaultAcpAgentAllowlist, defaultQuirks, discoverLocalAcpAgentInstances, discoverLocalAcpAgents, evaluateAcpDistributionPolicy, geminiStrategy, grokStrategy, isBannedAcpRegistryId, kimiStrategy, mergeAcpRuntimeState, modeLabelFor, normalizeAcpRuntimeCapabilities, normalizeRegistry, qwenStrategy, readAcpContentText, readBoolean, readContentText, readFirstLocationPath, readFirstString, readKind, readNonEmptyString, readNumber, readPromptText, readString, readToolCallId, readToolContentText, readToolOutput, readUpdateText, strategyByBackendId, strategyById, toolCallFromUpdate, wellKnownAgentBinDirs };
|
package/dist/index.js
CHANGED
|
@@ -1,54 +1,200 @@
|
|
|
1
|
-
// src/acp-
|
|
2
|
-
import {
|
|
1
|
+
// src/acp-connection.ts
|
|
2
|
+
import { spawn } from "child_process";
|
|
3
|
+
import { Readable, Writable } from "stream";
|
|
3
4
|
import {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
} from "@
|
|
7
|
-
|
|
8
|
-
|
|
5
|
+
ClientSideConnection,
|
|
6
|
+
ndJsonStream
|
|
7
|
+
} from "@zed-industries/agent-client-protocol";
|
|
8
|
+
import { noopLogger } from "@pwrdrvr/agent-core";
|
|
9
|
+
function isPlainObject(value) {
|
|
10
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
11
|
+
}
|
|
12
|
+
function sanitizeAcpNotificationLine(line) {
|
|
13
|
+
if (line.trim().length === 0) return line;
|
|
14
|
+
let message;
|
|
15
|
+
try {
|
|
16
|
+
message = JSON.parse(line);
|
|
17
|
+
} catch {
|
|
18
|
+
return line;
|
|
19
|
+
}
|
|
20
|
+
if (!isPlainObject(message) || message.method !== "session/update") return line;
|
|
21
|
+
const params = message.params;
|
|
22
|
+
if (!isPlainObject(params)) return line;
|
|
23
|
+
const update = params.update;
|
|
24
|
+
if (!isPlainObject(update)) return line;
|
|
25
|
+
let changed = false;
|
|
26
|
+
for (const key of ["rawInput", "rawOutput"]) {
|
|
27
|
+
if (!(key in update)) continue;
|
|
28
|
+
const value = update[key];
|
|
29
|
+
if (value === void 0 || isPlainObject(value)) continue;
|
|
30
|
+
if (value === null) {
|
|
31
|
+
delete update[key];
|
|
32
|
+
} else {
|
|
33
|
+
update[key] = { value };
|
|
34
|
+
}
|
|
35
|
+
changed = true;
|
|
36
|
+
}
|
|
37
|
+
return changed ? JSON.stringify(message) : line;
|
|
38
|
+
}
|
|
39
|
+
function sanitizeInboundStream(source) {
|
|
40
|
+
const decoder = new TextDecoder();
|
|
41
|
+
const encoder = new TextEncoder();
|
|
42
|
+
let buffer = "";
|
|
43
|
+
return source.pipeThrough(
|
|
44
|
+
new TransformStream({
|
|
45
|
+
transform(chunk, controller) {
|
|
46
|
+
buffer += decoder.decode(chunk, { stream: true });
|
|
47
|
+
let nl = buffer.indexOf("\n");
|
|
48
|
+
while (nl !== -1) {
|
|
49
|
+
const line = buffer.slice(0, nl);
|
|
50
|
+
buffer = buffer.slice(nl + 1);
|
|
51
|
+
controller.enqueue(encoder.encode(sanitizeAcpNotificationLine(line) + "\n"));
|
|
52
|
+
nl = buffer.indexOf("\n");
|
|
53
|
+
}
|
|
54
|
+
},
|
|
55
|
+
flush(controller) {
|
|
56
|
+
if (buffer.length > 0) {
|
|
57
|
+
controller.enqueue(encoder.encode(sanitizeAcpNotificationLine(buffer)));
|
|
58
|
+
buffer = "";
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
})
|
|
62
|
+
);
|
|
63
|
+
}
|
|
64
|
+
var AcpConnection = class {
|
|
65
|
+
constructor(options) {
|
|
66
|
+
this.options = options;
|
|
67
|
+
this.logger = options.logger ?? noopLogger;
|
|
68
|
+
}
|
|
69
|
+
options;
|
|
70
|
+
logger;
|
|
9
71
|
connection;
|
|
72
|
+
dispose;
|
|
73
|
+
connecting;
|
|
10
74
|
notificationListeners = /* @__PURE__ */ new Set();
|
|
11
75
|
requestHandler;
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
const
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
76
|
+
/** The `Client` handler the library invokes for agent→client traffic. */
|
|
77
|
+
buildClient() {
|
|
78
|
+
const emit = (method, params) => {
|
|
79
|
+
for (const listener of this.notificationListeners) listener(method, params);
|
|
80
|
+
};
|
|
81
|
+
return {
|
|
82
|
+
requestPermission: async (params) => {
|
|
83
|
+
if (!this.requestHandler) {
|
|
84
|
+
throw new Error("ACP request handler unavailable for session/request_permission");
|
|
85
|
+
}
|
|
86
|
+
return await this.requestHandler(
|
|
87
|
+
"session/request_permission",
|
|
88
|
+
params
|
|
89
|
+
);
|
|
90
|
+
},
|
|
91
|
+
sessionUpdate: async (params) => {
|
|
92
|
+
emit("session/update", params);
|
|
93
|
+
},
|
|
94
|
+
extNotification: async (method, params) => {
|
|
95
|
+
emit(method, params);
|
|
96
|
+
},
|
|
97
|
+
extMethod: async (method, params) => {
|
|
98
|
+
if (!this.requestHandler) {
|
|
99
|
+
throw new Error(`ACP request handler unavailable for ${method}`);
|
|
100
|
+
}
|
|
101
|
+
return await this.requestHandler(method, params) ?? {};
|
|
35
102
|
}
|
|
36
|
-
|
|
37
|
-
|
|
103
|
+
// No fs/terminal handlers: we don't advertise those client capabilities at
|
|
104
|
+
// `initialize`, so a conformant agent won't call them.
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
async ensureConnected() {
|
|
108
|
+
if (this.connection) return;
|
|
109
|
+
this.connecting ??= this.connect();
|
|
110
|
+
await this.connecting;
|
|
38
111
|
}
|
|
39
112
|
async connect() {
|
|
40
|
-
|
|
113
|
+
const create = this.options.createConnection ?? this.defaultCreateConnection();
|
|
114
|
+
const handle = create(this.buildClient());
|
|
115
|
+
this.connection = handle.connection;
|
|
116
|
+
this.dispose = handle.dispose;
|
|
117
|
+
}
|
|
118
|
+
defaultCreateConnection() {
|
|
119
|
+
const { command, args, env } = this.options;
|
|
120
|
+
const logger = this.logger;
|
|
121
|
+
return (client) => {
|
|
122
|
+
const child = spawn(command, args, {
|
|
123
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
124
|
+
...env !== void 0 ? { env } : {}
|
|
125
|
+
});
|
|
126
|
+
child.on("error", (error) => {
|
|
127
|
+
logger.error("acp agent process error", { command, message: error.message });
|
|
128
|
+
});
|
|
129
|
+
child.stderr?.on("data", (chunk) => {
|
|
130
|
+
const line = chunk.toString("utf8").trimEnd();
|
|
131
|
+
if (line.length > 0) logger.debug("acp agent stderr", { line });
|
|
132
|
+
});
|
|
133
|
+
const toAgentStdin = Writable.toWeb(child.stdin);
|
|
134
|
+
const fromAgentStdout = sanitizeInboundStream(
|
|
135
|
+
Readable.toWeb(child.stdout)
|
|
136
|
+
);
|
|
137
|
+
const stream = ndJsonStream(toAgentStdin, fromAgentStdout);
|
|
138
|
+
const connection = new ClientSideConnection(
|
|
139
|
+
(_agent) => client,
|
|
140
|
+
stream
|
|
141
|
+
);
|
|
142
|
+
return {
|
|
143
|
+
connection,
|
|
144
|
+
dispose: () => {
|
|
145
|
+
try {
|
|
146
|
+
child.stdin?.end();
|
|
147
|
+
} catch {
|
|
148
|
+
}
|
|
149
|
+
child.kill();
|
|
150
|
+
}
|
|
151
|
+
};
|
|
152
|
+
};
|
|
41
153
|
}
|
|
42
|
-
async request(method, params,
|
|
43
|
-
await this.
|
|
44
|
-
|
|
154
|
+
async request(method, params = {}, _timeoutMs) {
|
|
155
|
+
await this.ensureConnected();
|
|
156
|
+
const conn = this.connection;
|
|
157
|
+
if (!conn) throw new Error("acp connection unavailable");
|
|
158
|
+
switch (method) {
|
|
159
|
+
case "initialize":
|
|
160
|
+
return await conn.initialize(params);
|
|
161
|
+
case "session/new":
|
|
162
|
+
return await conn.newSession(params);
|
|
163
|
+
case "session/load":
|
|
164
|
+
return await conn.loadSession(params);
|
|
165
|
+
case "session/prompt":
|
|
166
|
+
return await conn.prompt(params);
|
|
167
|
+
case "session/set_mode":
|
|
168
|
+
return await conn.setSessionMode(params);
|
|
169
|
+
case "session/set_model":
|
|
170
|
+
return await conn.setSessionModel(params);
|
|
171
|
+
case "session/cancel":
|
|
172
|
+
await conn.cancel(params);
|
|
173
|
+
return {};
|
|
174
|
+
case "authenticate":
|
|
175
|
+
return await conn.authenticate(params);
|
|
176
|
+
default:
|
|
177
|
+
return await conn.extMethod(method, params);
|
|
178
|
+
}
|
|
45
179
|
}
|
|
46
|
-
async notify(method, params) {
|
|
47
|
-
await this.
|
|
48
|
-
|
|
180
|
+
async notify(method, params = {}) {
|
|
181
|
+
await this.ensureConnected();
|
|
182
|
+
const conn = this.connection;
|
|
183
|
+
if (!conn) throw new Error("acp connection unavailable");
|
|
184
|
+
if (method === "session/cancel") {
|
|
185
|
+
await conn.cancel(params);
|
|
186
|
+
return;
|
|
187
|
+
}
|
|
188
|
+
await conn.extNotification(method, params);
|
|
49
189
|
}
|
|
50
190
|
async close() {
|
|
51
|
-
|
|
191
|
+
try {
|
|
192
|
+
this.dispose?.();
|
|
193
|
+
} finally {
|
|
194
|
+
this.connection = void 0;
|
|
195
|
+
this.dispose = void 0;
|
|
196
|
+
this.connecting = void 0;
|
|
197
|
+
}
|
|
52
198
|
}
|
|
53
199
|
onNotification(listener) {
|
|
54
200
|
this.notificationListeners.add(listener);
|
|
@@ -65,9 +211,6 @@ var AcpStdioJsonRpcTransport = class {
|
|
|
65
211
|
};
|
|
66
212
|
}
|
|
67
213
|
};
|
|
68
|
-
function asRecord(value) {
|
|
69
|
-
return value && typeof value === "object" && !Array.isArray(value) ? value : void 0;
|
|
70
|
-
}
|
|
71
214
|
|
|
72
215
|
// src/acp-client.ts
|
|
73
216
|
import {
|
|
@@ -85,7 +228,7 @@ import {
|
|
|
85
228
|
} from "@pwrdrvr/agent-core";
|
|
86
229
|
|
|
87
230
|
// src/normalizer/content.ts
|
|
88
|
-
function
|
|
231
|
+
function asRecord(value) {
|
|
89
232
|
return value && typeof value === "object" && !Array.isArray(value) ? value : void 0;
|
|
90
233
|
}
|
|
91
234
|
function readString(record, key) {
|
|
@@ -122,7 +265,7 @@ function readAcpContentText(value) {
|
|
|
122
265
|
const parts = value.map((item) => readAcpContentText(item)).filter((item) => Boolean(item));
|
|
123
266
|
return parts.length > 0 ? parts.join("\n") : void 0;
|
|
124
267
|
}
|
|
125
|
-
const content =
|
|
268
|
+
const content = asRecord(value);
|
|
126
269
|
if (!content) {
|
|
127
270
|
return void 0;
|
|
128
271
|
}
|
|
@@ -143,7 +286,7 @@ function readFirstLocationPath(record) {
|
|
|
143
286
|
return void 0;
|
|
144
287
|
}
|
|
145
288
|
for (const location of locations) {
|
|
146
|
-
const path5 = readString(
|
|
289
|
+
const path5 = readString(asRecord(location), "path");
|
|
147
290
|
if (path5 && path5.trim()) {
|
|
148
291
|
return path5;
|
|
149
292
|
}
|
|
@@ -244,7 +387,7 @@ function toolCallFromUpdate(update, kind, sessionId) {
|
|
|
244
387
|
}
|
|
245
388
|
function readToolArgs(update) {
|
|
246
389
|
const raw = update.rawInput ?? update.raw_input ?? update.input ?? update.arguments ?? update.args;
|
|
247
|
-
return
|
|
390
|
+
return asRecord(raw) ?? (raw === void 0 ? void 0 : raw);
|
|
248
391
|
}
|
|
249
392
|
function readToolContentText(value) {
|
|
250
393
|
return readContentText({ content: value }, "content");
|
|
@@ -484,7 +627,7 @@ function readPlanSteps(record) {
|
|
|
484
627
|
if (typeof step === "string") {
|
|
485
628
|
return [{ step, status: "pending" }];
|
|
486
629
|
}
|
|
487
|
-
const stepRecord =
|
|
630
|
+
const stepRecord = asRecord(step);
|
|
488
631
|
if (!stepRecord) {
|
|
489
632
|
return [];
|
|
490
633
|
}
|
|
@@ -507,7 +650,7 @@ function readPromptText(content) {
|
|
|
507
650
|
|
|
508
651
|
// src/normalizer/runtime-capabilities.ts
|
|
509
652
|
function normalizeAcpRuntimeCapabilities(params) {
|
|
510
|
-
const record =
|
|
653
|
+
const record = asRecord(params.value);
|
|
511
654
|
if (!record) {
|
|
512
655
|
return params.initialize;
|
|
513
656
|
}
|
|
@@ -589,7 +732,7 @@ function acpSessionRuntimeStateFromUpdate(update, now) {
|
|
|
589
732
|
return currentModeId ? { currentModeId, updatedAt: now } : void 0;
|
|
590
733
|
}
|
|
591
734
|
if (kind === "config_option_update") {
|
|
592
|
-
const configOption =
|
|
735
|
+
const configOption = asRecord(update.configOption ?? update.config_option) ?? update;
|
|
593
736
|
const id = readString(configOption, "id") ?? readString(configOption, "configOptionId") ?? readString(configOption, "configId");
|
|
594
737
|
const value = readString(configOption, "currentValue") ?? readString(configOption, "value");
|
|
595
738
|
return id && value ? { configValues: { [id]: value }, updatedAt: now } : void 0;
|
|
@@ -619,7 +762,7 @@ function readConfigOptions(value) {
|
|
|
619
762
|
return [];
|
|
620
763
|
}
|
|
621
764
|
return value.flatMap((item) => {
|
|
622
|
-
const record =
|
|
765
|
+
const record = asRecord(item);
|
|
623
766
|
const id = readString(record, "id") ?? readString(record, "configOptionId") ?? readString(record, "configId");
|
|
624
767
|
if (!record || !id) {
|
|
625
768
|
return [];
|
|
@@ -648,7 +791,7 @@ function readConfigOptionValues(value) {
|
|
|
648
791
|
return [];
|
|
649
792
|
}
|
|
650
793
|
return value.flatMap((item) => {
|
|
651
|
-
const record =
|
|
794
|
+
const record = asRecord(item);
|
|
652
795
|
const optionValue = readString(record, "value") ?? readString(record, "id") ?? readString(record, "optionId");
|
|
653
796
|
if (!record || !optionValue) {
|
|
654
797
|
return [];
|
|
@@ -662,7 +805,7 @@ function readConfigOptionValues(value) {
|
|
|
662
805
|
});
|
|
663
806
|
}
|
|
664
807
|
function readModes(value) {
|
|
665
|
-
const record =
|
|
808
|
+
const record = asRecord(value);
|
|
666
809
|
const modes = Array.isArray(record?.availableModes) ? record.availableModes.flatMap(readMode) : [];
|
|
667
810
|
if (modes.length === 0) {
|
|
668
811
|
return void 0;
|
|
@@ -673,7 +816,7 @@ function readModes(value) {
|
|
|
673
816
|
return result;
|
|
674
817
|
}
|
|
675
818
|
function readMode(value) {
|
|
676
|
-
const record =
|
|
819
|
+
const record = asRecord(value);
|
|
677
820
|
const id = readString(record, "id") ?? readString(record, "modeId");
|
|
678
821
|
if (!record || !id) {
|
|
679
822
|
return [];
|
|
@@ -687,7 +830,7 @@ function readMode(value) {
|
|
|
687
830
|
return [mode];
|
|
688
831
|
}
|
|
689
832
|
function readModels(value) {
|
|
690
|
-
const record =
|
|
833
|
+
const record = asRecord(value);
|
|
691
834
|
const models = Array.isArray(record?.availableModels) ? record.availableModels.flatMap(readModel) : [];
|
|
692
835
|
if (models.length === 0) {
|
|
693
836
|
return void 0;
|
|
@@ -698,7 +841,7 @@ function readModels(value) {
|
|
|
698
841
|
return result;
|
|
699
842
|
}
|
|
700
843
|
function readModel(value) {
|
|
701
|
-
const record =
|
|
844
|
+
const record = asRecord(value);
|
|
702
845
|
const id = readString(record, "modelId") ?? readString(record, "id");
|
|
703
846
|
if (!record || !id) {
|
|
704
847
|
return [];
|
|
@@ -711,16 +854,16 @@ function readModel(value) {
|
|
|
711
854
|
return [model];
|
|
712
855
|
}
|
|
713
856
|
function readAgentCapabilities(value, sessionCapabilitiesValue) {
|
|
714
|
-
const record =
|
|
715
|
-
const sessionCapabilities =
|
|
716
|
-
const sessionMeta =
|
|
717
|
-
const kimiMeta =
|
|
857
|
+
const record = asRecord(value);
|
|
858
|
+
const sessionCapabilities = asRecord(sessionCapabilitiesValue);
|
|
859
|
+
const sessionMeta = asRecord(sessionCapabilities?._meta);
|
|
860
|
+
const kimiMeta = asRecord(sessionMeta?.kimi);
|
|
718
861
|
if (!record && !sessionCapabilities) {
|
|
719
862
|
return void 0;
|
|
720
863
|
}
|
|
721
|
-
const loadSession = readBoolean(record, "loadSession") ?? readBoolean(record, "load_session") ?? readBoolean(
|
|
722
|
-
const close = readBoolean(
|
|
723
|
-
const cancel = readBoolean(
|
|
864
|
+
const loadSession = readBoolean(record, "loadSession") ?? readBoolean(record, "load_session") ?? readBoolean(asRecord(record?.session), "load");
|
|
865
|
+
const close = readBoolean(asRecord(record?.session), "close");
|
|
866
|
+
const cancel = readBoolean(asRecord(record?.session), "cancel");
|
|
724
867
|
const sessionHistoryReplay = readBoolean(kimiMeta, "sessionHistoryReplay") ?? readBoolean(kimiMeta, "session_history_replay");
|
|
725
868
|
const capabilities = {
|
|
726
869
|
raw: record ?? sessionCapabilities
|
|
@@ -738,7 +881,7 @@ function readAgentCapabilities(value, sessionCapabilitiesValue) {
|
|
|
738
881
|
return capabilities;
|
|
739
882
|
}
|
|
740
883
|
function readAgentInfo(value) {
|
|
741
|
-
const record =
|
|
884
|
+
const record = asRecord(value);
|
|
742
885
|
if (!record) {
|
|
743
886
|
return void 0;
|
|
744
887
|
}
|
|
@@ -960,7 +1103,7 @@ var AcpAgentClient = class {
|
|
|
960
1103
|
cwd,
|
|
961
1104
|
mcpServers
|
|
962
1105
|
});
|
|
963
|
-
const record =
|
|
1106
|
+
const record = asRecord2(result);
|
|
964
1107
|
const protocolSessionId = readString2(record, "sessionId") ?? readString2(record, "session_id");
|
|
965
1108
|
if (!protocolSessionId) {
|
|
966
1109
|
throw new Error("ACP session/new did not return a session id");
|
|
@@ -1201,13 +1344,13 @@ var AcpAgentClient = class {
|
|
|
1201
1344
|
if (method !== "session/update" && !vendorMethods.includes(method)) {
|
|
1202
1345
|
return;
|
|
1203
1346
|
}
|
|
1204
|
-
const record =
|
|
1347
|
+
const record = asRecord2(params);
|
|
1205
1348
|
if (!record) return;
|
|
1206
1349
|
this.applySessionUpdate(record);
|
|
1207
1350
|
}
|
|
1208
1351
|
applySessionUpdate(params) {
|
|
1209
1352
|
const protocolSessionId = readString2(params, "sessionId") ?? readString2(params, "session_id");
|
|
1210
|
-
const update =
|
|
1353
|
+
const update = asRecord2(params.update);
|
|
1211
1354
|
if (!protocolSessionId || !update) {
|
|
1212
1355
|
return;
|
|
1213
1356
|
}
|
|
@@ -1400,7 +1543,7 @@ var AcpAgentClient = class {
|
|
|
1400
1543
|
}
|
|
1401
1544
|
};
|
|
1402
1545
|
function buildApprovalRequest(args) {
|
|
1403
|
-
const toolCall =
|
|
1546
|
+
const toolCall = asRecord2(args.params.toolCall) ?? {};
|
|
1404
1547
|
const title = typeof toolCall.title === "string" && toolCall.title.trim() ? toolCall.title.trim() : "ACP tool call";
|
|
1405
1548
|
const toolCallId = readString2(toolCall, "toolCallId") ?? readString2(toolCall, "tool_call_id");
|
|
1406
1549
|
const requestId = args.id == null ? toolCallId ?? `acp:${args.now()}` : String(args.id);
|
|
@@ -1436,7 +1579,7 @@ function readPermissionOptions(value) {
|
|
|
1436
1579
|
return [];
|
|
1437
1580
|
}
|
|
1438
1581
|
return value.flatMap((option) => {
|
|
1439
|
-
const record =
|
|
1582
|
+
const record = asRecord2(option);
|
|
1440
1583
|
const optionId = readString2(record, "optionId");
|
|
1441
1584
|
if (!record || !optionId) {
|
|
1442
1585
|
return [];
|
|
@@ -1511,12 +1654,12 @@ function readString2(record, key) {
|
|
|
1511
1654
|
const value = record?.[key];
|
|
1512
1655
|
return typeof value === "string" ? value : void 0;
|
|
1513
1656
|
}
|
|
1514
|
-
function
|
|
1657
|
+
function asRecord2(value) {
|
|
1515
1658
|
return value && typeof value === "object" && !Array.isArray(value) ? value : void 0;
|
|
1516
1659
|
}
|
|
1517
1660
|
function readAcpPromptUsage(result) {
|
|
1518
|
-
const meta =
|
|
1519
|
-
const tokenCount =
|
|
1661
|
+
const meta = asRecord2(asRecord2(result)?._meta);
|
|
1662
|
+
const tokenCount = asRecord2(asRecord2(meta?.quota)?.token_count);
|
|
1520
1663
|
if (!tokenCount) return void 0;
|
|
1521
1664
|
const num = (value) => typeof value === "number" && Number.isFinite(value) ? value : void 0;
|
|
1522
1665
|
const input = num(tokenCount.input_tokens);
|
|
@@ -2284,7 +2427,7 @@ function evaluateAcpDistributionPolicy(distribution, allowlist) {
|
|
|
2284
2427
|
};
|
|
2285
2428
|
}
|
|
2286
2429
|
function normalizeRegistry(raw) {
|
|
2287
|
-
const record =
|
|
2430
|
+
const record = asRecord3(raw);
|
|
2288
2431
|
const rawAgents = Array.isArray(record?.agents) ? record.agents : [];
|
|
2289
2432
|
return rawAgents.flatMap((item) => {
|
|
2290
2433
|
const agent = normalizeAgent(item);
|
|
@@ -2292,7 +2435,7 @@ function normalizeRegistry(raw) {
|
|
|
2292
2435
|
});
|
|
2293
2436
|
}
|
|
2294
2437
|
function normalizeAgent(raw) {
|
|
2295
|
-
const record =
|
|
2438
|
+
const record = asRecord3(raw);
|
|
2296
2439
|
if (!record || typeof record.id !== "string" || typeof record.name !== "string") {
|
|
2297
2440
|
return void 0;
|
|
2298
2441
|
}
|
|
@@ -2325,7 +2468,7 @@ function normalizeAgent(raw) {
|
|
|
2325
2468
|
return agent;
|
|
2326
2469
|
}
|
|
2327
2470
|
function normalizeDistributions(raw) {
|
|
2328
|
-
const record =
|
|
2471
|
+
const record = asRecord3(raw);
|
|
2329
2472
|
if (!record) {
|
|
2330
2473
|
return [];
|
|
2331
2474
|
}
|
|
@@ -2334,7 +2477,7 @@ function normalizeDistributions(raw) {
|
|
|
2334
2477
|
if (npx) distributions.push(npx);
|
|
2335
2478
|
const uvx = normalizePackageDistribution("uvx", record.uvx);
|
|
2336
2479
|
if (uvx) distributions.push(uvx);
|
|
2337
|
-
const binaryRecord =
|
|
2480
|
+
const binaryRecord = asRecord3(record.binary);
|
|
2338
2481
|
if (binaryRecord) {
|
|
2339
2482
|
for (const [platform, value] of Object.entries(binaryRecord)) {
|
|
2340
2483
|
const binary = normalizeBinaryDistribution(platform, value);
|
|
@@ -2344,7 +2487,7 @@ function normalizeDistributions(raw) {
|
|
|
2344
2487
|
return distributions;
|
|
2345
2488
|
}
|
|
2346
2489
|
function normalizePackageDistribution(kind, raw) {
|
|
2347
|
-
const record =
|
|
2490
|
+
const record = asRecord3(raw);
|
|
2348
2491
|
if (!record || typeof record.package !== "string") {
|
|
2349
2492
|
return void 0;
|
|
2350
2493
|
}
|
|
@@ -2356,7 +2499,7 @@ function normalizePackageDistribution(kind, raw) {
|
|
|
2356
2499
|
};
|
|
2357
2500
|
}
|
|
2358
2501
|
function normalizeBinaryDistribution(platform, raw) {
|
|
2359
|
-
const record =
|
|
2502
|
+
const record = asRecord3(raw);
|
|
2360
2503
|
if (!record || typeof record.archive !== "string" || typeof record.cmd !== "string") {
|
|
2361
2504
|
return void 0;
|
|
2362
2505
|
}
|
|
@@ -2378,7 +2521,7 @@ function normalizeAuth(raw) {
|
|
|
2378
2521
|
if (!raw) {
|
|
2379
2522
|
return { required: false, methods: [] };
|
|
2380
2523
|
}
|
|
2381
|
-
const record =
|
|
2524
|
+
const record = asRecord3(raw);
|
|
2382
2525
|
if (!record) {
|
|
2383
2526
|
return { required: true, methods: ["unknown"], raw };
|
|
2384
2527
|
}
|
|
@@ -2391,7 +2534,7 @@ function normalizeAuth(raw) {
|
|
|
2391
2534
|
raw
|
|
2392
2535
|
};
|
|
2393
2536
|
}
|
|
2394
|
-
function
|
|
2537
|
+
function asRecord3(value) {
|
|
2395
2538
|
return value && typeof value === "object" && !Array.isArray(value) ? value : void 0;
|
|
2396
2539
|
}
|
|
2397
2540
|
function stringValue(value) {
|
|
@@ -2401,7 +2544,7 @@ function stringArray(value) {
|
|
|
2401
2544
|
return Array.isArray(value) ? value.filter((item) => typeof item === "string") : [];
|
|
2402
2545
|
}
|
|
2403
2546
|
function stringRecord(value) {
|
|
2404
|
-
const record =
|
|
2547
|
+
const record = asRecord3(value);
|
|
2405
2548
|
if (!record) {
|
|
2406
2549
|
return {};
|
|
2407
2550
|
}
|
|
@@ -2416,17 +2559,17 @@ export {
|
|
|
2416
2559
|
AcpAgentAllowlist,
|
|
2417
2560
|
AcpAgentClient,
|
|
2418
2561
|
AcpAgentClientPool,
|
|
2562
|
+
AcpConnection,
|
|
2419
2563
|
AcpOneShotClient,
|
|
2420
2564
|
AcpRegistryService,
|
|
2421
2565
|
AcpSessionNormalizer,
|
|
2422
|
-
AcpStdioJsonRpcTransport,
|
|
2423
2566
|
BANNED_ACP_REGISTRY_IDS,
|
|
2424
2567
|
BUILT_IN_ACP_STRATEGIES,
|
|
2425
2568
|
DEFAULT_ACP_AGENT_ALLOWLIST,
|
|
2426
2569
|
acpRuntimeSupportsSessionLoad,
|
|
2427
2570
|
acpSessionRuntimeStateFromCapabilities,
|
|
2428
2571
|
acpSessionRuntimeStateFromUpdate,
|
|
2429
|
-
|
|
2572
|
+
asRecord,
|
|
2430
2573
|
buildAcpBackendId,
|
|
2431
2574
|
buildStrategyTable,
|
|
2432
2575
|
defaultAcpAgentAllowlist,
|