@pwrdrvr/agent-acp 0.8.0 → 0.9.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/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, JsonRpcObserver, JsonRpcTransport } from '@pwrdrvr/agent-transport';
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
- type AcpStdioJsonRpcTransportOptions = {
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
- /** Override the underlying JSON-RPC transport (tests inject a fake). */
20
- transport?: JsonRpcTransport;
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 AcpStdioJsonRpcTransport implements AcpJsonRpcTransport {
23
- private readonly connection;
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: AcpStdioJsonRpcTransportOptions);
27
- connect(): Promise<void>;
28
- request(method: string, params?: Record<string, unknown>, timeoutMs?: number): Promise<unknown>;
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, AcpStdioJsonRpcTransport, type AcpStdioJsonRpcTransportOptions, 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 };
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,143 @@
1
- // src/acp-stdio-transport.ts
2
- import { noopLogger } from "@pwrdrvr/agent-core";
1
+ // src/acp-connection.ts
2
+ import { spawn } from "child_process";
3
+ import { Readable, Writable } from "stream";
3
4
  import {
4
- JsonRpcConnection,
5
- StdioJsonRpcTransport
6
- } from "@pwrdrvr/agent-transport";
7
- var DEFAULT_REQUEST_TIMEOUT_MS = 10 * 6e4;
8
- var AcpStdioJsonRpcTransport = class {
5
+ ClientSideConnection,
6
+ ndJsonStream
7
+ } from "@zed-industries/agent-client-protocol";
8
+ import { noopLogger } from "@pwrdrvr/agent-core";
9
+ var AcpConnection = class {
10
+ constructor(options) {
11
+ this.options = options;
12
+ this.logger = options.logger ?? noopLogger;
13
+ }
14
+ options;
15
+ logger;
9
16
  connection;
17
+ dispose;
18
+ connecting;
10
19
  notificationListeners = /* @__PURE__ */ new Set();
11
20
  requestHandler;
12
- constructor(options) {
13
- const logger = options.logger ?? noopLogger;
14
- const transport = options.transport ?? new StdioJsonRpcTransport({
15
- command: options.command,
16
- args: options.args,
17
- ...options.env !== void 0 ? { env: options.env } : {},
18
- logger
19
- });
20
- this.connection = new JsonRpcConnection(
21
- transport,
22
- options.requestTimeoutMs ?? DEFAULT_REQUEST_TIMEOUT_MS,
23
- options.observer,
24
- { logger, logContext: { owner: "acp-stdio-transport" } }
25
- );
26
- this.connection.setNotificationHandler((method, params) => {
27
- const normalized = asRecord(params) ?? {};
28
- for (const listener of this.notificationListeners) {
29
- listener(method, normalized);
30
- }
31
- });
32
- this.connection.setRequestHandler(async (method, params, id) => {
33
- if (!this.requestHandler) {
34
- throw new Error(`ACP request handler unavailable for ${method}`);
21
+ /** The `Client` handler the library invokes for agent→client traffic. */
22
+ buildClient() {
23
+ const emit = (method, params) => {
24
+ for (const listener of this.notificationListeners) listener(method, params);
25
+ };
26
+ return {
27
+ requestPermission: async (params) => {
28
+ if (!this.requestHandler) {
29
+ throw new Error("ACP request handler unavailable for session/request_permission");
30
+ }
31
+ return await this.requestHandler(
32
+ "session/request_permission",
33
+ params
34
+ );
35
+ },
36
+ sessionUpdate: async (params) => {
37
+ emit("session/update", params);
38
+ },
39
+ extNotification: async (method, params) => {
40
+ emit(method, params);
41
+ },
42
+ extMethod: async (method, params) => {
43
+ if (!this.requestHandler) {
44
+ throw new Error(`ACP request handler unavailable for ${method}`);
45
+ }
46
+ return await this.requestHandler(method, params) ?? {};
35
47
  }
36
- return await this.requestHandler(method, asRecord(params) ?? {}, id);
37
- });
48
+ // No fs/terminal handlers: we don't advertise those client capabilities at
49
+ // `initialize`, so a conformant agent won't call them.
50
+ };
51
+ }
52
+ async ensureConnected() {
53
+ if (this.connection) return;
54
+ this.connecting ??= this.connect();
55
+ await this.connecting;
38
56
  }
39
57
  async connect() {
40
- await this.connection.connect();
58
+ const create = this.options.createConnection ?? this.defaultCreateConnection();
59
+ const handle = create(this.buildClient());
60
+ this.connection = handle.connection;
61
+ this.dispose = handle.dispose;
62
+ }
63
+ defaultCreateConnection() {
64
+ const { command, args, env } = this.options;
65
+ const logger = this.logger;
66
+ return (client) => {
67
+ const child = spawn(command, args, {
68
+ stdio: ["pipe", "pipe", "pipe"],
69
+ ...env !== void 0 ? { env } : {}
70
+ });
71
+ child.on("error", (error) => {
72
+ logger.error("acp agent process error", { command, message: error.message });
73
+ });
74
+ child.stderr?.on("data", (chunk) => {
75
+ const line = chunk.toString("utf8").trimEnd();
76
+ if (line.length > 0) logger.debug("acp agent stderr", { line });
77
+ });
78
+ const toAgentStdin = Writable.toWeb(child.stdin);
79
+ const fromAgentStdout = Readable.toWeb(child.stdout);
80
+ const stream = ndJsonStream(toAgentStdin, fromAgentStdout);
81
+ const connection = new ClientSideConnection(
82
+ (_agent) => client,
83
+ stream
84
+ );
85
+ return {
86
+ connection,
87
+ dispose: () => {
88
+ try {
89
+ child.stdin?.end();
90
+ } catch {
91
+ }
92
+ child.kill();
93
+ }
94
+ };
95
+ };
41
96
  }
42
- async request(method, params, timeoutMs) {
43
- await this.connection.connect();
44
- return await this.connection.request(method, params, timeoutMs);
97
+ async request(method, params = {}, _timeoutMs) {
98
+ await this.ensureConnected();
99
+ const conn = this.connection;
100
+ if (!conn) throw new Error("acp connection unavailable");
101
+ switch (method) {
102
+ case "initialize":
103
+ return await conn.initialize(params);
104
+ case "session/new":
105
+ return await conn.newSession(params);
106
+ case "session/load":
107
+ return await conn.loadSession(params);
108
+ case "session/prompt":
109
+ return await conn.prompt(params);
110
+ case "session/set_mode":
111
+ return await conn.setSessionMode(params);
112
+ case "session/set_model":
113
+ return await conn.setSessionModel(params);
114
+ case "session/cancel":
115
+ await conn.cancel(params);
116
+ return {};
117
+ case "authenticate":
118
+ return await conn.authenticate(params);
119
+ default:
120
+ return await conn.extMethod(method, params);
121
+ }
45
122
  }
46
- async notify(method, params) {
47
- await this.connection.connect();
48
- await this.connection.notify(method, params);
123
+ async notify(method, params = {}) {
124
+ await this.ensureConnected();
125
+ const conn = this.connection;
126
+ if (!conn) throw new Error("acp connection unavailable");
127
+ if (method === "session/cancel") {
128
+ await conn.cancel(params);
129
+ return;
130
+ }
131
+ await conn.extNotification(method, params);
49
132
  }
50
133
  async close() {
51
- await this.connection.close();
134
+ try {
135
+ this.dispose?.();
136
+ } finally {
137
+ this.connection = void 0;
138
+ this.dispose = void 0;
139
+ this.connecting = void 0;
140
+ }
52
141
  }
53
142
  onNotification(listener) {
54
143
  this.notificationListeners.add(listener);
@@ -65,9 +154,6 @@ var AcpStdioJsonRpcTransport = class {
65
154
  };
66
155
  }
67
156
  };
68
- function asRecord(value) {
69
- return value && typeof value === "object" && !Array.isArray(value) ? value : void 0;
70
- }
71
157
 
72
158
  // src/acp-client.ts
73
159
  import {
@@ -85,7 +171,7 @@ import {
85
171
  } from "@pwrdrvr/agent-core";
86
172
 
87
173
  // src/normalizer/content.ts
88
- function asRecord2(value) {
174
+ function asRecord(value) {
89
175
  return value && typeof value === "object" && !Array.isArray(value) ? value : void 0;
90
176
  }
91
177
  function readString(record, key) {
@@ -122,7 +208,7 @@ function readAcpContentText(value) {
122
208
  const parts = value.map((item) => readAcpContentText(item)).filter((item) => Boolean(item));
123
209
  return parts.length > 0 ? parts.join("\n") : void 0;
124
210
  }
125
- const content = asRecord2(value);
211
+ const content = asRecord(value);
126
212
  if (!content) {
127
213
  return void 0;
128
214
  }
@@ -143,7 +229,7 @@ function readFirstLocationPath(record) {
143
229
  return void 0;
144
230
  }
145
231
  for (const location of locations) {
146
- const path5 = readString(asRecord2(location), "path");
232
+ const path5 = readString(asRecord(location), "path");
147
233
  if (path5 && path5.trim()) {
148
234
  return path5;
149
235
  }
@@ -244,7 +330,7 @@ function toolCallFromUpdate(update, kind, sessionId) {
244
330
  }
245
331
  function readToolArgs(update) {
246
332
  const raw = update.rawInput ?? update.raw_input ?? update.input ?? update.arguments ?? update.args;
247
- return asRecord2(raw) ?? (raw === void 0 ? void 0 : raw);
333
+ return asRecord(raw) ?? (raw === void 0 ? void 0 : raw);
248
334
  }
249
335
  function readToolContentText(value) {
250
336
  return readContentText({ content: value }, "content");
@@ -484,7 +570,7 @@ function readPlanSteps(record) {
484
570
  if (typeof step === "string") {
485
571
  return [{ step, status: "pending" }];
486
572
  }
487
- const stepRecord = asRecord2(step);
573
+ const stepRecord = asRecord(step);
488
574
  if (!stepRecord) {
489
575
  return [];
490
576
  }
@@ -507,7 +593,7 @@ function readPromptText(content) {
507
593
 
508
594
  // src/normalizer/runtime-capabilities.ts
509
595
  function normalizeAcpRuntimeCapabilities(params) {
510
- const record = asRecord2(params.value);
596
+ const record = asRecord(params.value);
511
597
  if (!record) {
512
598
  return params.initialize;
513
599
  }
@@ -589,7 +675,7 @@ function acpSessionRuntimeStateFromUpdate(update, now) {
589
675
  return currentModeId ? { currentModeId, updatedAt: now } : void 0;
590
676
  }
591
677
  if (kind === "config_option_update") {
592
- const configOption = asRecord2(update.configOption ?? update.config_option) ?? update;
678
+ const configOption = asRecord(update.configOption ?? update.config_option) ?? update;
593
679
  const id = readString(configOption, "id") ?? readString(configOption, "configOptionId") ?? readString(configOption, "configId");
594
680
  const value = readString(configOption, "currentValue") ?? readString(configOption, "value");
595
681
  return id && value ? { configValues: { [id]: value }, updatedAt: now } : void 0;
@@ -619,7 +705,7 @@ function readConfigOptions(value) {
619
705
  return [];
620
706
  }
621
707
  return value.flatMap((item) => {
622
- const record = asRecord2(item);
708
+ const record = asRecord(item);
623
709
  const id = readString(record, "id") ?? readString(record, "configOptionId") ?? readString(record, "configId");
624
710
  if (!record || !id) {
625
711
  return [];
@@ -648,7 +734,7 @@ function readConfigOptionValues(value) {
648
734
  return [];
649
735
  }
650
736
  return value.flatMap((item) => {
651
- const record = asRecord2(item);
737
+ const record = asRecord(item);
652
738
  const optionValue = readString(record, "value") ?? readString(record, "id") ?? readString(record, "optionId");
653
739
  if (!record || !optionValue) {
654
740
  return [];
@@ -662,7 +748,7 @@ function readConfigOptionValues(value) {
662
748
  });
663
749
  }
664
750
  function readModes(value) {
665
- const record = asRecord2(value);
751
+ const record = asRecord(value);
666
752
  const modes = Array.isArray(record?.availableModes) ? record.availableModes.flatMap(readMode) : [];
667
753
  if (modes.length === 0) {
668
754
  return void 0;
@@ -673,7 +759,7 @@ function readModes(value) {
673
759
  return result;
674
760
  }
675
761
  function readMode(value) {
676
- const record = asRecord2(value);
762
+ const record = asRecord(value);
677
763
  const id = readString(record, "id") ?? readString(record, "modeId");
678
764
  if (!record || !id) {
679
765
  return [];
@@ -687,7 +773,7 @@ function readMode(value) {
687
773
  return [mode];
688
774
  }
689
775
  function readModels(value) {
690
- const record = asRecord2(value);
776
+ const record = asRecord(value);
691
777
  const models = Array.isArray(record?.availableModels) ? record.availableModels.flatMap(readModel) : [];
692
778
  if (models.length === 0) {
693
779
  return void 0;
@@ -698,7 +784,7 @@ function readModels(value) {
698
784
  return result;
699
785
  }
700
786
  function readModel(value) {
701
- const record = asRecord2(value);
787
+ const record = asRecord(value);
702
788
  const id = readString(record, "modelId") ?? readString(record, "id");
703
789
  if (!record || !id) {
704
790
  return [];
@@ -711,16 +797,16 @@ function readModel(value) {
711
797
  return [model];
712
798
  }
713
799
  function readAgentCapabilities(value, sessionCapabilitiesValue) {
714
- const record = asRecord2(value);
715
- const sessionCapabilities = asRecord2(sessionCapabilitiesValue);
716
- const sessionMeta = asRecord2(sessionCapabilities?._meta);
717
- const kimiMeta = asRecord2(sessionMeta?.kimi);
800
+ const record = asRecord(value);
801
+ const sessionCapabilities = asRecord(sessionCapabilitiesValue);
802
+ const sessionMeta = asRecord(sessionCapabilities?._meta);
803
+ const kimiMeta = asRecord(sessionMeta?.kimi);
718
804
  if (!record && !sessionCapabilities) {
719
805
  return void 0;
720
806
  }
721
- const loadSession = readBoolean(record, "loadSession") ?? readBoolean(record, "load_session") ?? readBoolean(asRecord2(record?.session), "load");
722
- const close = readBoolean(asRecord2(record?.session), "close");
723
- const cancel = readBoolean(asRecord2(record?.session), "cancel");
807
+ const loadSession = readBoolean(record, "loadSession") ?? readBoolean(record, "load_session") ?? readBoolean(asRecord(record?.session), "load");
808
+ const close = readBoolean(asRecord(record?.session), "close");
809
+ const cancel = readBoolean(asRecord(record?.session), "cancel");
724
810
  const sessionHistoryReplay = readBoolean(kimiMeta, "sessionHistoryReplay") ?? readBoolean(kimiMeta, "session_history_replay");
725
811
  const capabilities = {
726
812
  raw: record ?? sessionCapabilities
@@ -738,7 +824,7 @@ function readAgentCapabilities(value, sessionCapabilitiesValue) {
738
824
  return capabilities;
739
825
  }
740
826
  function readAgentInfo(value) {
741
- const record = asRecord2(value);
827
+ const record = asRecord(value);
742
828
  if (!record) {
743
829
  return void 0;
744
830
  }
@@ -960,7 +1046,7 @@ var AcpAgentClient = class {
960
1046
  cwd,
961
1047
  mcpServers
962
1048
  });
963
- const record = asRecord3(result);
1049
+ const record = asRecord2(result);
964
1050
  const protocolSessionId = readString2(record, "sessionId") ?? readString2(record, "session_id");
965
1051
  if (!protocolSessionId) {
966
1052
  throw new Error("ACP session/new did not return a session id");
@@ -1201,13 +1287,13 @@ var AcpAgentClient = class {
1201
1287
  if (method !== "session/update" && !vendorMethods.includes(method)) {
1202
1288
  return;
1203
1289
  }
1204
- const record = asRecord3(params);
1290
+ const record = asRecord2(params);
1205
1291
  if (!record) return;
1206
1292
  this.applySessionUpdate(record);
1207
1293
  }
1208
1294
  applySessionUpdate(params) {
1209
1295
  const protocolSessionId = readString2(params, "sessionId") ?? readString2(params, "session_id");
1210
- const update = asRecord3(params.update);
1296
+ const update = asRecord2(params.update);
1211
1297
  if (!protocolSessionId || !update) {
1212
1298
  return;
1213
1299
  }
@@ -1400,7 +1486,7 @@ var AcpAgentClient = class {
1400
1486
  }
1401
1487
  };
1402
1488
  function buildApprovalRequest(args) {
1403
- const toolCall = asRecord3(args.params.toolCall) ?? {};
1489
+ const toolCall = asRecord2(args.params.toolCall) ?? {};
1404
1490
  const title = typeof toolCall.title === "string" && toolCall.title.trim() ? toolCall.title.trim() : "ACP tool call";
1405
1491
  const toolCallId = readString2(toolCall, "toolCallId") ?? readString2(toolCall, "tool_call_id");
1406
1492
  const requestId = args.id == null ? toolCallId ?? `acp:${args.now()}` : String(args.id);
@@ -1436,7 +1522,7 @@ function readPermissionOptions(value) {
1436
1522
  return [];
1437
1523
  }
1438
1524
  return value.flatMap((option) => {
1439
- const record = asRecord3(option);
1525
+ const record = asRecord2(option);
1440
1526
  const optionId = readString2(record, "optionId");
1441
1527
  if (!record || !optionId) {
1442
1528
  return [];
@@ -1511,12 +1597,12 @@ function readString2(record, key) {
1511
1597
  const value = record?.[key];
1512
1598
  return typeof value === "string" ? value : void 0;
1513
1599
  }
1514
- function asRecord3(value) {
1600
+ function asRecord2(value) {
1515
1601
  return value && typeof value === "object" && !Array.isArray(value) ? value : void 0;
1516
1602
  }
1517
1603
  function readAcpPromptUsage(result) {
1518
- const meta = asRecord3(asRecord3(result)?._meta);
1519
- const tokenCount = asRecord3(asRecord3(meta?.quota)?.token_count);
1604
+ const meta = asRecord2(asRecord2(result)?._meta);
1605
+ const tokenCount = asRecord2(asRecord2(meta?.quota)?.token_count);
1520
1606
  if (!tokenCount) return void 0;
1521
1607
  const num = (value) => typeof value === "number" && Number.isFinite(value) ? value : void 0;
1522
1608
  const input = num(tokenCount.input_tokens);
@@ -2284,7 +2370,7 @@ function evaluateAcpDistributionPolicy(distribution, allowlist) {
2284
2370
  };
2285
2371
  }
2286
2372
  function normalizeRegistry(raw) {
2287
- const record = asRecord4(raw);
2373
+ const record = asRecord3(raw);
2288
2374
  const rawAgents = Array.isArray(record?.agents) ? record.agents : [];
2289
2375
  return rawAgents.flatMap((item) => {
2290
2376
  const agent = normalizeAgent(item);
@@ -2292,7 +2378,7 @@ function normalizeRegistry(raw) {
2292
2378
  });
2293
2379
  }
2294
2380
  function normalizeAgent(raw) {
2295
- const record = asRecord4(raw);
2381
+ const record = asRecord3(raw);
2296
2382
  if (!record || typeof record.id !== "string" || typeof record.name !== "string") {
2297
2383
  return void 0;
2298
2384
  }
@@ -2325,7 +2411,7 @@ function normalizeAgent(raw) {
2325
2411
  return agent;
2326
2412
  }
2327
2413
  function normalizeDistributions(raw) {
2328
- const record = asRecord4(raw);
2414
+ const record = asRecord3(raw);
2329
2415
  if (!record) {
2330
2416
  return [];
2331
2417
  }
@@ -2334,7 +2420,7 @@ function normalizeDistributions(raw) {
2334
2420
  if (npx) distributions.push(npx);
2335
2421
  const uvx = normalizePackageDistribution("uvx", record.uvx);
2336
2422
  if (uvx) distributions.push(uvx);
2337
- const binaryRecord = asRecord4(record.binary);
2423
+ const binaryRecord = asRecord3(record.binary);
2338
2424
  if (binaryRecord) {
2339
2425
  for (const [platform, value] of Object.entries(binaryRecord)) {
2340
2426
  const binary = normalizeBinaryDistribution(platform, value);
@@ -2344,7 +2430,7 @@ function normalizeDistributions(raw) {
2344
2430
  return distributions;
2345
2431
  }
2346
2432
  function normalizePackageDistribution(kind, raw) {
2347
- const record = asRecord4(raw);
2433
+ const record = asRecord3(raw);
2348
2434
  if (!record || typeof record.package !== "string") {
2349
2435
  return void 0;
2350
2436
  }
@@ -2356,7 +2442,7 @@ function normalizePackageDistribution(kind, raw) {
2356
2442
  };
2357
2443
  }
2358
2444
  function normalizeBinaryDistribution(platform, raw) {
2359
- const record = asRecord4(raw);
2445
+ const record = asRecord3(raw);
2360
2446
  if (!record || typeof record.archive !== "string" || typeof record.cmd !== "string") {
2361
2447
  return void 0;
2362
2448
  }
@@ -2378,7 +2464,7 @@ function normalizeAuth(raw) {
2378
2464
  if (!raw) {
2379
2465
  return { required: false, methods: [] };
2380
2466
  }
2381
- const record = asRecord4(raw);
2467
+ const record = asRecord3(raw);
2382
2468
  if (!record) {
2383
2469
  return { required: true, methods: ["unknown"], raw };
2384
2470
  }
@@ -2391,7 +2477,7 @@ function normalizeAuth(raw) {
2391
2477
  raw
2392
2478
  };
2393
2479
  }
2394
- function asRecord4(value) {
2480
+ function asRecord3(value) {
2395
2481
  return value && typeof value === "object" && !Array.isArray(value) ? value : void 0;
2396
2482
  }
2397
2483
  function stringValue(value) {
@@ -2401,7 +2487,7 @@ function stringArray(value) {
2401
2487
  return Array.isArray(value) ? value.filter((item) => typeof item === "string") : [];
2402
2488
  }
2403
2489
  function stringRecord(value) {
2404
- const record = asRecord4(value);
2490
+ const record = asRecord3(value);
2405
2491
  if (!record) {
2406
2492
  return {};
2407
2493
  }
@@ -2416,17 +2502,17 @@ export {
2416
2502
  AcpAgentAllowlist,
2417
2503
  AcpAgentClient,
2418
2504
  AcpAgentClientPool,
2505
+ AcpConnection,
2419
2506
  AcpOneShotClient,
2420
2507
  AcpRegistryService,
2421
2508
  AcpSessionNormalizer,
2422
- AcpStdioJsonRpcTransport,
2423
2509
  BANNED_ACP_REGISTRY_IDS,
2424
2510
  BUILT_IN_ACP_STRATEGIES,
2425
2511
  DEFAULT_ACP_AGENT_ALLOWLIST,
2426
2512
  acpRuntimeSupportsSessionLoad,
2427
2513
  acpSessionRuntimeStateFromCapabilities,
2428
2514
  acpSessionRuntimeStateFromUpdate,
2429
- asRecord2 as asRecord,
2515
+ asRecord,
2430
2516
  buildAcpBackendId,
2431
2517
  buildStrategyTable,
2432
2518
  defaultAcpAgentAllowlist,