@pwrdrvr/agent-acp 0.1.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/LICENSE +21 -0
- package/dist/index.d.ts +568 -0
- package/dist/index.js +1973 -0
- package/dist/index.js.map +1 -0
- package/package.json +50 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 PwrDrvr LLC
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,568 @@
|
|
|
1
|
+
import { Logger, AgentBackend, NormalizedThreadEvent, Unsubscribe, AgentBackendToolCallHandler, AgentBackendApprovalHandler, AgentStartThreadOptions, AgentBackendStartThreadResult, AgentStartTurnOptions, NormalizedToolCall } from '@pwrdrvr/agent-core';
|
|
2
|
+
import { JsonRpcId, JsonRpcObserver, JsonRpcTransport } from '@pwrdrvr/agent-transport';
|
|
3
|
+
|
|
4
|
+
/** The bidirectional transport shape the ACP client drives. */
|
|
5
|
+
interface AcpJsonRpcTransport {
|
|
6
|
+
request(method: string, params?: Record<string, unknown>, timeoutMs?: number): Promise<unknown>;
|
|
7
|
+
notify?(method: string, params?: Record<string, unknown>): Promise<void>;
|
|
8
|
+
close?(): Promise<void>;
|
|
9
|
+
onNotification(listener: (method: string, params: Record<string, unknown>) => void): () => void;
|
|
10
|
+
onRequest?(listener: (method: string, params: Record<string, unknown>, id?: JsonRpcId) => Promise<unknown> | unknown): () => void;
|
|
11
|
+
}
|
|
12
|
+
type AcpStdioJsonRpcTransportOptions = {
|
|
13
|
+
command: string;
|
|
14
|
+
args: string[];
|
|
15
|
+
env?: NodeJS.ProcessEnv;
|
|
16
|
+
requestTimeoutMs?: number;
|
|
17
|
+
observer?: JsonRpcObserver;
|
|
18
|
+
logger?: Logger;
|
|
19
|
+
/** Override the underlying JSON-RPC transport (tests inject a fake). */
|
|
20
|
+
transport?: JsonRpcTransport;
|
|
21
|
+
};
|
|
22
|
+
declare class AcpStdioJsonRpcTransport implements AcpJsonRpcTransport {
|
|
23
|
+
private readonly connection;
|
|
24
|
+
private readonly notificationListeners;
|
|
25
|
+
private requestHandler;
|
|
26
|
+
constructor(options: AcpStdioJsonRpcTransportOptions);
|
|
27
|
+
connect(): Promise<void>;
|
|
28
|
+
request(method: string, params?: Record<string, unknown>, timeoutMs?: number): Promise<unknown>;
|
|
29
|
+
notify(method: string, params?: Record<string, unknown>): Promise<void>;
|
|
30
|
+
close(): Promise<void>;
|
|
31
|
+
onNotification(listener: (method: string, params: Record<string, unknown>) => void): () => void;
|
|
32
|
+
onRequest(listener: (method: string, params: Record<string, unknown>, id?: JsonRpcId) => Promise<unknown> | unknown): () => void;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
type LocalAcpProbeResult = {
|
|
36
|
+
stdout?: string | Buffer;
|
|
37
|
+
stderr?: string | Buffer;
|
|
38
|
+
};
|
|
39
|
+
type LocalAcpAgentProbe = (command: string, args: string[]) => Promise<LocalAcpProbeResult>;
|
|
40
|
+
/** How a strategy decides it is installed + ACP-capable on this machine. */
|
|
41
|
+
type AcpDiscoveryProbe = {
|
|
42
|
+
/** Args that print a version (probed first; failure = not installed). */
|
|
43
|
+
versionArgs: string[];
|
|
44
|
+
/** Args that print help/usage text the `helpMatches` regex confirms ACP support against. */
|
|
45
|
+
helpArgs: string[];
|
|
46
|
+
/** Regex the help/usage output must match for the agent to count as ACP-capable. */
|
|
47
|
+
helpMatches: RegExp;
|
|
48
|
+
/** Bare command name tried first. */
|
|
49
|
+
command: string;
|
|
50
|
+
/** Additional candidate command paths (Homebrew prefixes, `~/.<agent>/bin`, …). */
|
|
51
|
+
fallbackCommands?: string[];
|
|
52
|
+
};
|
|
53
|
+
/** Launch invocation: how to spawn the CLI in ACP stdio server mode. */
|
|
54
|
+
type AcpSpawnSpec = {
|
|
55
|
+
/** Command to run (resolved against the discovered candidate at spawn time). */
|
|
56
|
+
command: string;
|
|
57
|
+
/** Args that put the CLI into ACP stdio server mode (e.g. `["--acp"]`). */
|
|
58
|
+
args: string[];
|
|
59
|
+
/** Extra env to set when launching (e.g. Gemini workspace-trust). */
|
|
60
|
+
env?: Record<string, string>;
|
|
61
|
+
/** Extra args appended only when missing (e.g. Gemini `--skip-trust`). */
|
|
62
|
+
ensureArgs?: string[];
|
|
63
|
+
};
|
|
64
|
+
/**
|
|
65
|
+
* Normalization quirks the normalizer reads. NO agent-id literal ever appears
|
|
66
|
+
* in the normalizer — it reads these fields off the strategy it was constructed
|
|
67
|
+
* with. A synthetic strategy with different quirk values flows through the
|
|
68
|
+
* normalizer with zero normalizer changes (asserted in tests).
|
|
69
|
+
*/
|
|
70
|
+
type AcpAgentQuirks = {
|
|
71
|
+
/**
|
|
72
|
+
* Whether agent "thought"/reasoning chunks surface as assistant messages.
|
|
73
|
+
* Qwen sets this false (its thoughts are noisy scaffolding); others true.
|
|
74
|
+
*/
|
|
75
|
+
surfaceThoughts: boolean;
|
|
76
|
+
/**
|
|
77
|
+
* Where the auto-generated thread title comes from:
|
|
78
|
+
* • "topic-update" — a `tool_call` titled `Update topic to: "…"` (Gemini/Kimi/Qwen);
|
|
79
|
+
* • "session-summary" — a vendor `session_summary_generated` update (Grok);
|
|
80
|
+
* • "both" — recognize either.
|
|
81
|
+
*/
|
|
82
|
+
titleFrom: "topic-update" | "session-summary" | "both";
|
|
83
|
+
/** Vendor notification methods routed through the same session/update path. */
|
|
84
|
+
vendorNotificationMethods?: string[];
|
|
85
|
+
};
|
|
86
|
+
type AcpAgentStrategy = {
|
|
87
|
+
/** Strategy id, also the registry id (`gemini`, `grok`, `kimi`, `qwen`, …). */
|
|
88
|
+
id: string;
|
|
89
|
+
/** Neutral backend id (`acp:<id>`) used as the thread/session correlation key. */
|
|
90
|
+
backendId: string;
|
|
91
|
+
displayName: string;
|
|
92
|
+
authors: string[];
|
|
93
|
+
license?: string;
|
|
94
|
+
repositoryUrl?: string;
|
|
95
|
+
discoveryProbe: AcpDiscoveryProbe;
|
|
96
|
+
spawn: AcpSpawnSpec;
|
|
97
|
+
quirks: AcpAgentQuirks;
|
|
98
|
+
};
|
|
99
|
+
/** Build the neutral backend id for a registry id. */
|
|
100
|
+
declare function buildAcpBackendId(registryId: string): string;
|
|
101
|
+
/** Quirks for an unknown/synthetic strategy default to the common case. */
|
|
102
|
+
declare function defaultQuirks(overrides?: Partial<AcpAgentQuirks>): AcpAgentQuirks;
|
|
103
|
+
|
|
104
|
+
type AcpRuntimeConfigOptionValue = {
|
|
105
|
+
value: string;
|
|
106
|
+
label?: string;
|
|
107
|
+
description?: string;
|
|
108
|
+
};
|
|
109
|
+
type AcpRuntimeConfigOption = {
|
|
110
|
+
id: string;
|
|
111
|
+
label: string;
|
|
112
|
+
description?: string;
|
|
113
|
+
type: "select";
|
|
114
|
+
category?: string;
|
|
115
|
+
currentValue?: string;
|
|
116
|
+
values: AcpRuntimeConfigOptionValue[];
|
|
117
|
+
};
|
|
118
|
+
type AcpRuntimeMode = {
|
|
119
|
+
id: string;
|
|
120
|
+
label: string;
|
|
121
|
+
description?: string;
|
|
122
|
+
};
|
|
123
|
+
type AcpRuntimeModel = {
|
|
124
|
+
id: string;
|
|
125
|
+
label?: string;
|
|
126
|
+
description?: string;
|
|
127
|
+
};
|
|
128
|
+
type AcpRuntimeModes = {
|
|
129
|
+
availableModes: AcpRuntimeMode[];
|
|
130
|
+
currentModeId?: string;
|
|
131
|
+
};
|
|
132
|
+
type AcpRuntimeModels = {
|
|
133
|
+
availableModels: AcpRuntimeModel[];
|
|
134
|
+
currentModelId?: string;
|
|
135
|
+
};
|
|
136
|
+
type AcpRuntimeAgentInfo = {
|
|
137
|
+
name?: string;
|
|
138
|
+
title?: string;
|
|
139
|
+
version?: string;
|
|
140
|
+
};
|
|
141
|
+
type AcpRuntimeAgentCapabilities = {
|
|
142
|
+
loadSession?: boolean;
|
|
143
|
+
sessionHistoryReplay?: boolean;
|
|
144
|
+
session?: {
|
|
145
|
+
close?: boolean;
|
|
146
|
+
cancel?: boolean;
|
|
147
|
+
};
|
|
148
|
+
raw?: unknown;
|
|
149
|
+
};
|
|
150
|
+
type AcpRuntimeCapabilitiesSource = "initialize" | "session-new" | "session-load";
|
|
151
|
+
type AcpRuntimeCapabilities = {
|
|
152
|
+
source: AcpRuntimeCapabilitiesSource;
|
|
153
|
+
discoveredAt: number;
|
|
154
|
+
checkedAt: number;
|
|
155
|
+
protocolVersion?: number;
|
|
156
|
+
agentInfo?: AcpRuntimeAgentInfo;
|
|
157
|
+
agentCapabilities?: AcpRuntimeAgentCapabilities;
|
|
158
|
+
configOptions?: AcpRuntimeConfigOption[];
|
|
159
|
+
modes?: AcpRuntimeModes;
|
|
160
|
+
models?: AcpRuntimeModels;
|
|
161
|
+
};
|
|
162
|
+
type AcpSessionRuntimeState = {
|
|
163
|
+
updatedAt?: number;
|
|
164
|
+
currentModeId?: string;
|
|
165
|
+
currentModelId?: string;
|
|
166
|
+
configValues?: Record<string, string>;
|
|
167
|
+
};
|
|
168
|
+
declare function normalizeAcpRuntimeCapabilities(params: {
|
|
169
|
+
value: unknown;
|
|
170
|
+
now: number;
|
|
171
|
+
source: AcpRuntimeCapabilitiesSource;
|
|
172
|
+
initialize?: AcpRuntimeCapabilities;
|
|
173
|
+
}): AcpRuntimeCapabilities | undefined;
|
|
174
|
+
declare function acpRuntimeSupportsSessionLoad(capabilities: AcpRuntimeCapabilities | undefined): boolean;
|
|
175
|
+
declare function acpSessionRuntimeStateFromCapabilities(capabilities: AcpRuntimeCapabilities | undefined, now: number): AcpSessionRuntimeState | undefined;
|
|
176
|
+
/** Runtime-state change carried inside a session/update (mode/model/config). */
|
|
177
|
+
declare function acpSessionRuntimeStateFromUpdate(update: Record<string, unknown>, now: number): AcpSessionRuntimeState | undefined;
|
|
178
|
+
declare function mergeAcpRuntimeState(existing: AcpSessionRuntimeState | undefined, update: AcpSessionRuntimeState): AcpSessionRuntimeState;
|
|
179
|
+
/** Resolve the human-facing label for a mode id from the capabilities snapshot. */
|
|
180
|
+
declare function modeLabelFor(capabilities: AcpRuntimeCapabilities | undefined, modeId: string): string | undefined;
|
|
181
|
+
|
|
182
|
+
type AcpPromptContentBlock = {
|
|
183
|
+
type: "text";
|
|
184
|
+
text: string;
|
|
185
|
+
} | {
|
|
186
|
+
type: "image";
|
|
187
|
+
mimeType: string;
|
|
188
|
+
data: string;
|
|
189
|
+
};
|
|
190
|
+
type AcpMcpServerConfig = {
|
|
191
|
+
name: string;
|
|
192
|
+
command: string;
|
|
193
|
+
args?: string[];
|
|
194
|
+
env?: Record<string, string>;
|
|
195
|
+
};
|
|
196
|
+
type AcpRuntimeOptionSource = "mode" | "model" | "configOption";
|
|
197
|
+
type AcpAgentClientOptions = {
|
|
198
|
+
/** The transport (real stdio or a fake). */
|
|
199
|
+
transport: AcpJsonRpcTransport;
|
|
200
|
+
/** The agent strategy (carries quirks + display name). */
|
|
201
|
+
strategy: AcpAgentStrategy;
|
|
202
|
+
/** Identity sent at `initialize`. Defaults to "agent-kit". */
|
|
203
|
+
clientName?: string;
|
|
204
|
+
clientTitle?: string;
|
|
205
|
+
clientVersion?: string;
|
|
206
|
+
/** Default cwd for `session/new` when `startThread` omits one. */
|
|
207
|
+
cwd?: string;
|
|
208
|
+
/** MCP servers to attach at `session/new` / `session/load`. */
|
|
209
|
+
mcpServers?: AcpMcpServerConfig[];
|
|
210
|
+
now?: () => number;
|
|
211
|
+
logger?: Logger;
|
|
212
|
+
};
|
|
213
|
+
/** ACP-NATIVE thread/start options. **No longer the public `startThread`
|
|
214
|
+
* surface** — `AcpAgentClient` implements the non-generic `AgentBackend` and its
|
|
215
|
+
* public `startThread` takes neutral `AgentStartThreadOptions`. Retained as the
|
|
216
|
+
* internal mapping target and exposed via `startThreadNative` for hosts wanting
|
|
217
|
+
* ACP-specific control (e.g. per-thread `mcpServers`). */
|
|
218
|
+
type AcpStartThreadOptions = {
|
|
219
|
+
/** Working directory for the agent session. */
|
|
220
|
+
cwd?: string;
|
|
221
|
+
mcpServers?: AcpMcpServerConfig[];
|
|
222
|
+
};
|
|
223
|
+
/** ACP-NATIVE turn/start options. Internal mapping target; the public `startTurn`
|
|
224
|
+
* takes neutral `AgentStartTurnOptions`. */
|
|
225
|
+
type AcpStartTurnOptions = {
|
|
226
|
+
threadId: string;
|
|
227
|
+
/** Plain prompt text. */
|
|
228
|
+
prompt?: string;
|
|
229
|
+
/** Pre-built ACP content blocks (text/image); overrides `prompt` when set. */
|
|
230
|
+
promptContent?: AcpPromptContentBlock[];
|
|
231
|
+
};
|
|
232
|
+
/** Fired when the normalizer extracts a thread title from the stream. */
|
|
233
|
+
type AcpTitleHandler = (event: {
|
|
234
|
+
threadId: string;
|
|
235
|
+
title: string;
|
|
236
|
+
}) => void;
|
|
237
|
+
/** Fired when runtime capabilities (models/modes/config-options) are observed. */
|
|
238
|
+
type AcpRuntimeCapabilitiesHandler = (event: {
|
|
239
|
+
threadId?: string;
|
|
240
|
+
runtimeCapabilities: AcpRuntimeCapabilities;
|
|
241
|
+
runtimeState?: AcpSessionRuntimeState;
|
|
242
|
+
}) => void;
|
|
243
|
+
declare class AcpAgentClient implements AgentBackend {
|
|
244
|
+
private readonly transport;
|
|
245
|
+
private readonly strategy;
|
|
246
|
+
private readonly now;
|
|
247
|
+
private readonly logger;
|
|
248
|
+
private readonly eventListeners;
|
|
249
|
+
private toolCallHandler;
|
|
250
|
+
private approvalHandler;
|
|
251
|
+
private titleHandler;
|
|
252
|
+
private runtimeCapabilitiesHandler;
|
|
253
|
+
private readonly sessions;
|
|
254
|
+
private readonly threadIdByProtocolId;
|
|
255
|
+
private unsubscribeNotification;
|
|
256
|
+
private unsubscribeRequest;
|
|
257
|
+
private initialized;
|
|
258
|
+
private runtimeCapabilities?;
|
|
259
|
+
private threadSequence;
|
|
260
|
+
constructor(options: AcpAgentClientOptions);
|
|
261
|
+
private readonly clientName;
|
|
262
|
+
private readonly clientTitle;
|
|
263
|
+
private readonly clientVersion;
|
|
264
|
+
private readonly defaultCwd;
|
|
265
|
+
private readonly defaultMcpServers;
|
|
266
|
+
onEvent(cb: (event: NormalizedThreadEvent) => void): Unsubscribe;
|
|
267
|
+
onToolCall(handler: AgentBackendToolCallHandler): Unsubscribe;
|
|
268
|
+
onApprovalRequest(handler: AgentBackendApprovalHandler): Unsubscribe;
|
|
269
|
+
/** Subscribe to title extraction (topic-update / session-summary). */
|
|
270
|
+
onTitle(handler: AcpTitleHandler): Unsubscribe;
|
|
271
|
+
/** Subscribe to runtime-capabilities (models/modes/config-options) changes. */
|
|
272
|
+
onRuntimeCapabilities(handler: AcpRuntimeCapabilitiesHandler): Unsubscribe;
|
|
273
|
+
/**
|
|
274
|
+
* Public `AgentBackend.startThread`: accepts NEUTRAL `AgentStartThreadOptions`
|
|
275
|
+
* and maps them onto an ACP `session/new`. ACP supports:
|
|
276
|
+
* • `cwd` → `session/new.cwd`.
|
|
277
|
+
* • `model` → applied via `session/set_model` after the session opens, when
|
|
278
|
+
* the agent advertises model selection (best-effort; debug-logged if not).
|
|
279
|
+
* • `instructions` is NOT injected here — ACP `session/new` has no base-
|
|
280
|
+
* instructions slot, matching the adapter's existing behavior. A host that
|
|
281
|
+
* wants system framing sends it as leading turn text.
|
|
282
|
+
* Codex-only fields (`approvalPolicy`, `sandbox`, `config`, `environments`,
|
|
283
|
+
* `tools`, `serviceName`, `modelProvider`, `serviceTier`, `workspaceRoots`) are
|
|
284
|
+
* IGNORED — logged at debug so it's visible the backend doesn't honor them.
|
|
285
|
+
*/
|
|
286
|
+
startThread(options?: AgentStartThreadOptions): Promise<AgentBackendStartThreadResult>;
|
|
287
|
+
/** ACP-native `session/new`. The neutral `startThread` delegates here after
|
|
288
|
+
* mapping cwd + dropping Codex-only fields. Exposed for hosts that need
|
|
289
|
+
* ACP-specific control (per-thread `mcpServers`). */
|
|
290
|
+
startThreadNative(options?: AcpStartThreadOptions): Promise<AgentBackendStartThreadResult>;
|
|
291
|
+
/**
|
|
292
|
+
* Public `AgentBackend.startTurn`: accepts NEUTRAL `AgentStartTurnOptions` and
|
|
293
|
+
* maps them onto ACP prompt content blocks — a leading `text` block from
|
|
294
|
+
* `input.text`, then one `image` block per `input.imagePaths` entry (read from
|
|
295
|
+
* disk, base64-encoded, mimeType inferred from extension). `reasoning` maps to
|
|
296
|
+
* an ACP mode/config when the session advertises a matching option, else it is
|
|
297
|
+
* IGNORED (debug-logged).
|
|
298
|
+
*/
|
|
299
|
+
startTurn(options: AgentStartTurnOptions): Promise<{
|
|
300
|
+
turnId: string;
|
|
301
|
+
}>;
|
|
302
|
+
/** ACP-native `session/prompt`. Takes a plain prompt or pre-built content
|
|
303
|
+
* blocks. The neutral `startTurn` delegates here after building blocks. */
|
|
304
|
+
startTurnNative(options: AcpStartTurnOptions): Promise<{
|
|
305
|
+
turnId: string;
|
|
306
|
+
}>;
|
|
307
|
+
interruptTurn(threadId: string): Promise<void>;
|
|
308
|
+
setMode(threadId: string, modeId: string): Promise<void>;
|
|
309
|
+
setModel(threadId: string, modelId: string): Promise<void>;
|
|
310
|
+
setConfigOption(threadId: string, optionId: string, value: string): Promise<void>;
|
|
311
|
+
close(): Promise<void>;
|
|
312
|
+
private emit;
|
|
313
|
+
private initialize;
|
|
314
|
+
private handleNotification;
|
|
315
|
+
private applySessionUpdate;
|
|
316
|
+
private handleAcpRequest;
|
|
317
|
+
private handlePermissionRequest;
|
|
318
|
+
private setRuntimeOption;
|
|
319
|
+
private setRuntimeOptionOnTransport;
|
|
320
|
+
/** Map a neutral `reasoning` token onto an ACP runtime option. We try to match
|
|
321
|
+
* it to an available MODE (by id or label, case-insensitively) and switch via
|
|
322
|
+
* `session/set_mode`. ACP has no first-class "reasoning effort" concept, so if
|
|
323
|
+
* no mode matches we leave it alone — the caller's `.catch` debug-logs. */
|
|
324
|
+
private applyReasoning;
|
|
325
|
+
/** Read an image file and build an ACP `image` content block (base64 + inferred
|
|
326
|
+
* mimeType). Throws on read failure; the caller catches + skips. */
|
|
327
|
+
private imageBlockFromPath;
|
|
328
|
+
private captureRuntimeCapabilities;
|
|
329
|
+
private notifyRuntimeCapabilities;
|
|
330
|
+
private emitThreadSettings;
|
|
331
|
+
private requireSession;
|
|
332
|
+
/** Whether the agent advertises session/load support (for hosts that resume). */
|
|
333
|
+
supportsSessionLoad(): boolean;
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
type AcpNormalizerOptions = {
|
|
337
|
+
/** The agent's normalization quirks (surface thoughts, where title comes from). */
|
|
338
|
+
quirks: AcpAgentQuirks;
|
|
339
|
+
};
|
|
340
|
+
type AcpNormalizeResult = {
|
|
341
|
+
events: NormalizedThreadEvent[];
|
|
342
|
+
/** A thread title extracted from a topic-update / session-summary, if any. */
|
|
343
|
+
title?: string;
|
|
344
|
+
};
|
|
345
|
+
type AcpApplyContext = {
|
|
346
|
+
threadId: string;
|
|
347
|
+
turnId: string;
|
|
348
|
+
};
|
|
349
|
+
declare class AcpSessionNormalizer {
|
|
350
|
+
private readonly quirks;
|
|
351
|
+
private activeAssistantItemId;
|
|
352
|
+
private assistantText;
|
|
353
|
+
private assistantSequence;
|
|
354
|
+
private readonly toolCalls;
|
|
355
|
+
constructor(options: AcpNormalizerOptions);
|
|
356
|
+
/** Reset coalescing state at a turn boundary (new prompt / turn finished). */
|
|
357
|
+
resetTurn(): void;
|
|
358
|
+
/** Finalize the in-flight assistant bubble into a terminal `agent_message`, if any. */
|
|
359
|
+
finalizeAssistantMessage(ctx: AcpApplyContext): NormalizedThreadEvent[];
|
|
360
|
+
/** Normalize one ACP session/update into neutral events (+ optional title). */
|
|
361
|
+
apply(update: Record<string, unknown>, ctx: AcpApplyContext): AcpNormalizeResult;
|
|
362
|
+
private applyAgentMessageChunk;
|
|
363
|
+
private applyThoughtChunk;
|
|
364
|
+
private applyUserMessageChunk;
|
|
365
|
+
private applyPlan;
|
|
366
|
+
private applyToolCall;
|
|
367
|
+
private assistantItemIdForChunk;
|
|
368
|
+
/** Strategy-driven title extraction. NO agent-id literal — reads quirks.titleFrom. */
|
|
369
|
+
private extractTitle;
|
|
370
|
+
}
|
|
371
|
+
/** Read the message parts (text/image) of a prompt, camel/snake tolerant. */
|
|
372
|
+
declare function readPromptText(content: unknown): string | undefined;
|
|
373
|
+
|
|
374
|
+
/** Read the tool-call correlation id across every spelling agents use. */
|
|
375
|
+
declare function readToolCallId(update: Record<string, unknown>, kind: string, sessionId: string): string;
|
|
376
|
+
/**
|
|
377
|
+
* Normalize one ACP tool-ish update (tool_call / tool_call_update / file /
|
|
378
|
+
* terminal) into a NormalizedToolCall. The result is fed to the normalizer's
|
|
379
|
+
* upsert, which merges deltas with the same id via agent-core's `mergeToolCall`.
|
|
380
|
+
*/
|
|
381
|
+
declare function toolCallFromUpdate(update: Record<string, unknown>, kind: string, sessionId: string): NormalizedToolCall;
|
|
382
|
+
/** Tool output text from a content array, for permission prompts. */
|
|
383
|
+
declare function readToolContentText(value: unknown): string | undefined;
|
|
384
|
+
|
|
385
|
+
declare function asRecord(value: unknown): Record<string, unknown> | undefined;
|
|
386
|
+
declare function readString(record: Record<string, unknown> | undefined, key: string): string | undefined;
|
|
387
|
+
declare function readNonEmptyString(record: Record<string, unknown> | undefined, key: string): string | undefined;
|
|
388
|
+
declare function readNumber(record: Record<string, unknown> | undefined, key: string): number | undefined;
|
|
389
|
+
declare function readBoolean(record: Record<string, unknown> | undefined, key: string): boolean | undefined;
|
|
390
|
+
/**
|
|
391
|
+
* Read the first defined string among the given keys, in order. Used for
|
|
392
|
+
* camel/snake parity (`toolCallId` vs `tool_call_id`).
|
|
393
|
+
*/
|
|
394
|
+
declare function readFirstString(record: Record<string, unknown> | undefined, ...keys: string[]): string | undefined;
|
|
395
|
+
/** The session-update kind, tolerant of all four key spellings. */
|
|
396
|
+
declare function readKind(update: Record<string, unknown>): string;
|
|
397
|
+
/**
|
|
398
|
+
* Recursively unwrap an ACP content value to plain text. Handles a bare string,
|
|
399
|
+
* an array of content blocks (joined with newlines), and nested
|
|
400
|
+
* `{ type:"text", text }` / `{ content }` / `{ text }` / `{ output }` /
|
|
401
|
+
* `{ result }` shapes.
|
|
402
|
+
*/
|
|
403
|
+
declare function readAcpContentText(value: unknown): string | undefined;
|
|
404
|
+
declare function readContentText(record: Record<string, unknown>, key: string): string | undefined;
|
|
405
|
+
/** Tool output, checked across all the spellings agents use. */
|
|
406
|
+
declare function readToolOutput(record: Record<string, unknown>): string | undefined;
|
|
407
|
+
/** First location path from an ACP `locations: [{ path }]` array. */
|
|
408
|
+
declare function readFirstLocationPath(record: Record<string, unknown>): string | undefined;
|
|
409
|
+
/** The assistant/user text carried by a chunk update (camel/snake tolerant). */
|
|
410
|
+
declare function readUpdateText(update: Record<string, unknown>): string | undefined;
|
|
411
|
+
|
|
412
|
+
declare const geminiStrategy: AcpAgentStrategy;
|
|
413
|
+
|
|
414
|
+
declare const grokStrategy: AcpAgentStrategy;
|
|
415
|
+
|
|
416
|
+
declare const kimiStrategy: AcpAgentStrategy;
|
|
417
|
+
|
|
418
|
+
declare const qwenStrategy: AcpAgentStrategy;
|
|
419
|
+
|
|
420
|
+
declare const BUILT_IN_ACP_STRATEGIES: readonly AcpAgentStrategy[];
|
|
421
|
+
/** Index a list of strategies by id (built-ins by default). */
|
|
422
|
+
declare function buildStrategyTable(strategies?: readonly AcpAgentStrategy[]): Map<string, AcpAgentStrategy>;
|
|
423
|
+
/** Look up a strategy by its registry id, falling back to the built-in table. */
|
|
424
|
+
declare function strategyById(id: string, table?: Map<string, AcpAgentStrategy>): AcpAgentStrategy | undefined;
|
|
425
|
+
/** Look up a strategy by its neutral backend id (`acp:<id>`). */
|
|
426
|
+
declare function strategyByBackendId(backendId: string, strategies?: readonly AcpAgentStrategy[]): AcpAgentStrategy | undefined;
|
|
427
|
+
|
|
428
|
+
type DiscoveredAcpAgent = {
|
|
429
|
+
strategyId: string;
|
|
430
|
+
backendId: string;
|
|
431
|
+
name: string;
|
|
432
|
+
version?: string;
|
|
433
|
+
/** Resolved command that passed the probe (may be a fallback path). */
|
|
434
|
+
command: string;
|
|
435
|
+
/** Spawn args that put it into ACP stdio mode. */
|
|
436
|
+
args: string[];
|
|
437
|
+
/** Extra env to set at launch. */
|
|
438
|
+
env: Record<string, string>;
|
|
439
|
+
discoveredAt: number;
|
|
440
|
+
};
|
|
441
|
+
type LocalAcpDiscoveryOptions = {
|
|
442
|
+
probe?: LocalAcpAgentProbe;
|
|
443
|
+
now?: () => number;
|
|
444
|
+
/** Strategy table to probe (built-ins by default). */
|
|
445
|
+
strategies?: readonly AcpAgentStrategy[];
|
|
446
|
+
/** Per-strategy command override (tried before the strategy's own candidates). */
|
|
447
|
+
overrides?: Record<string, string>;
|
|
448
|
+
};
|
|
449
|
+
declare function discoverLocalAcpAgents(options?: LocalAcpDiscoveryOptions): Promise<DiscoveredAcpAgent[]>;
|
|
450
|
+
|
|
451
|
+
declare const ACP_REGISTRY_URL = "https://cdn.agentclientprotocol.com/registry/v1/latest/registry.json";
|
|
452
|
+
type AcpDistributionKind = "npx" | "uvx" | "binary" | "local";
|
|
453
|
+
type AcpRegistryDistributionEnv = Record<string, string>;
|
|
454
|
+
type AcpPackageDistribution = {
|
|
455
|
+
kind: "npx" | "uvx";
|
|
456
|
+
packageName: string;
|
|
457
|
+
args: string[];
|
|
458
|
+
env: AcpRegistryDistributionEnv;
|
|
459
|
+
};
|
|
460
|
+
type AcpBinaryPlatformDistribution = {
|
|
461
|
+
kind: "binary";
|
|
462
|
+
platform: string;
|
|
463
|
+
archiveUrl: string;
|
|
464
|
+
command: string;
|
|
465
|
+
args: string[];
|
|
466
|
+
env: AcpRegistryDistributionEnv;
|
|
467
|
+
checksum?: string;
|
|
468
|
+
signatureUrl?: string;
|
|
469
|
+
};
|
|
470
|
+
type AcpRegistryDistribution = AcpPackageDistribution | AcpBinaryPlatformDistribution;
|
|
471
|
+
type AcpRegistryAuthMethod = "agent-managed" | "terminal" | "unknown";
|
|
472
|
+
type AcpRegistryAuthDescriptor = {
|
|
473
|
+
required: boolean;
|
|
474
|
+
methods: AcpRegistryAuthMethod[];
|
|
475
|
+
raw?: unknown;
|
|
476
|
+
};
|
|
477
|
+
type AcpRegistryAgent = {
|
|
478
|
+
id: string;
|
|
479
|
+
backendId: string;
|
|
480
|
+
name: string;
|
|
481
|
+
version?: string;
|
|
482
|
+
description?: string;
|
|
483
|
+
authors: string[];
|
|
484
|
+
license?: string;
|
|
485
|
+
repositoryUrl?: string;
|
|
486
|
+
websiteUrl?: string;
|
|
487
|
+
iconUrl?: string;
|
|
488
|
+
distributions: AcpRegistryDistribution[];
|
|
489
|
+
distributionKinds: AcpDistributionKind[];
|
|
490
|
+
auth: AcpRegistryAuthDescriptor;
|
|
491
|
+
raw: unknown;
|
|
492
|
+
};
|
|
493
|
+
type AcpVerificationStatus = "verified" | "unverified-allowed" | "unverified-blocked" | "not-applicable";
|
|
494
|
+
type AcpAllowlistDecision = {
|
|
495
|
+
allowed: true;
|
|
496
|
+
ruleId: string;
|
|
497
|
+
unverifiedBinaryAllowed: boolean;
|
|
498
|
+
} | {
|
|
499
|
+
allowed: false;
|
|
500
|
+
reason: string;
|
|
501
|
+
};
|
|
502
|
+
type AcpRegistryAgentWithPolicy = AcpRegistryAgent & {
|
|
503
|
+
allowlist: AcpAllowlistDecision;
|
|
504
|
+
installable: boolean;
|
|
505
|
+
unavailableReason?: string;
|
|
506
|
+
verificationStatus: AcpVerificationStatus;
|
|
507
|
+
};
|
|
508
|
+
type AcpRegistrySnapshot = {
|
|
509
|
+
fetchedAt: number;
|
|
510
|
+
agents: AcpRegistryAgent[];
|
|
511
|
+
raw: unknown;
|
|
512
|
+
};
|
|
513
|
+
|
|
514
|
+
type AcpAgentAllowlistRule = {
|
|
515
|
+
id: string;
|
|
516
|
+
registryId: string;
|
|
517
|
+
versions?: string[];
|
|
518
|
+
distributionKinds?: AcpDistributionKind[];
|
|
519
|
+
allowedPackageNames?: string[];
|
|
520
|
+
allowedArchiveHosts?: string[];
|
|
521
|
+
allowUnverifiedBinary?: boolean;
|
|
522
|
+
allowGplFamilyLicense?: boolean;
|
|
523
|
+
};
|
|
524
|
+
declare const BANNED_ACP_REGISTRY_IDS: Set<string>;
|
|
525
|
+
declare const DEFAULT_ACP_AGENT_ALLOWLIST: AcpAgentAllowlistRule[];
|
|
526
|
+
declare class AcpAgentAllowlist {
|
|
527
|
+
private readonly rules;
|
|
528
|
+
constructor(rules: AcpAgentAllowlistRule[]);
|
|
529
|
+
evaluate(agent: AcpRegistryAgent): AcpAllowlistDecision;
|
|
530
|
+
evaluateDistribution(agent: AcpRegistryAgent, distribution: AcpRegistryDistribution): AcpAllowlistDecision;
|
|
531
|
+
}
|
|
532
|
+
declare const defaultAcpAgentAllowlist: AcpAgentAllowlist;
|
|
533
|
+
declare function isBannedAcpRegistryId(registryId: string): boolean;
|
|
534
|
+
|
|
535
|
+
type AcpRegistryFetch = (input: string, init?: {
|
|
536
|
+
headers?: Record<string, string>;
|
|
537
|
+
}) => Promise<{
|
|
538
|
+
ok: boolean;
|
|
539
|
+
status: number;
|
|
540
|
+
statusText: string;
|
|
541
|
+
json(): Promise<unknown>;
|
|
542
|
+
}>;
|
|
543
|
+
type AcpRegistryServiceOptions = {
|
|
544
|
+
allowlist?: AcpAgentAllowlist;
|
|
545
|
+
fetch?: AcpRegistryFetch;
|
|
546
|
+
now?: () => number;
|
|
547
|
+
registryUrl?: string;
|
|
548
|
+
};
|
|
549
|
+
type AcpDistributionPolicy = {
|
|
550
|
+
allowlist: AcpAllowlistDecision;
|
|
551
|
+
installable: boolean;
|
|
552
|
+
verificationStatus: AcpVerificationStatus;
|
|
553
|
+
unavailableReason?: string;
|
|
554
|
+
};
|
|
555
|
+
declare class AcpRegistryService {
|
|
556
|
+
private readonly allowlist;
|
|
557
|
+
private readonly fetcher;
|
|
558
|
+
private readonly now;
|
|
559
|
+
private readonly registryUrl;
|
|
560
|
+
constructor(options?: AcpRegistryServiceOptions);
|
|
561
|
+
fetchRegistry(): Promise<AcpRegistrySnapshot>;
|
|
562
|
+
applyAllowlist(snapshot: AcpRegistrySnapshot): AcpRegistryAgentWithPolicy[];
|
|
563
|
+
evaluateDistribution(agent: AcpRegistryAgent, distribution: AcpRegistryDistribution): AcpDistributionPolicy;
|
|
564
|
+
}
|
|
565
|
+
declare function evaluateAcpDistributionPolicy(distribution: AcpRegistryDistribution, allowlist: AcpAllowlistDecision): AcpDistributionPolicy;
|
|
566
|
+
declare function normalizeRegistry(raw: unknown): AcpRegistryAgent[];
|
|
567
|
+
|
|
568
|
+
export { ACP_REGISTRY_URL, AcpAgentAllowlist, type AcpAgentAllowlistRule, AcpAgentClient, type AcpAgentClientOptions, type AcpAgentQuirks, type AcpAgentStrategy, type AcpAllowlistDecision, type AcpApplyContext, type AcpBinaryPlatformDistribution, type AcpDiscoveryProbe, type AcpDistributionKind, type AcpDistributionPolicy, type AcpJsonRpcTransport, type AcpMcpServerConfig, type AcpNormalizeResult, type AcpNormalizerOptions, type AcpPackageDistribution, 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, AcpStdioJsonRpcTransport, type AcpStdioJsonRpcTransportOptions, type AcpTitleHandler, type AcpVerificationStatus, BANNED_ACP_REGISTRY_IDS, BUILT_IN_ACP_STRATEGIES, DEFAULT_ACP_AGENT_ALLOWLIST, type DiscoveredAcpAgent, type LocalAcpAgentProbe, type LocalAcpDiscoveryOptions, type LocalAcpProbeResult, acpRuntimeSupportsSessionLoad, acpSessionRuntimeStateFromCapabilities, acpSessionRuntimeStateFromUpdate, asRecord, buildAcpBackendId, buildStrategyTable, defaultAcpAgentAllowlist, defaultQuirks, 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 };
|