@moxt-ai/mobius 0.0.318 → 0.0.320

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.
Files changed (76) hide show
  1. package/dist/acp/adapter/agent-initialization.d.ts.map +1 -1
  2. package/dist/acp/adapter/agent-initialization.js +7 -12
  3. package/dist/acp/adapter/agent-initialization.js.map +1 -1
  4. package/dist/acp/adapter/claude/agent-connection.d.ts +6 -0
  5. package/dist/acp/adapter/claude/agent-connection.d.ts.map +1 -0
  6. package/dist/acp/adapter/claude/agent-connection.js +15 -0
  7. package/dist/acp/adapter/claude/agent-connection.js.map +1 -0
  8. package/dist/acp/adapter/codex/agent-connection.d.ts +6 -0
  9. package/dist/acp/adapter/codex/agent-connection.d.ts.map +1 -0
  10. package/dist/acp/adapter/codex/agent-connection.js +15 -0
  11. package/dist/acp/adapter/codex/agent-connection.js.map +1 -0
  12. package/dist/acp/adapter/pi/agent-connection.d.ts +6 -0
  13. package/dist/acp/adapter/pi/agent-connection.d.ts.map +1 -0
  14. package/dist/acp/adapter/pi/agent-connection.js +15 -0
  15. package/dist/acp/adapter/pi/agent-connection.js.map +1 -0
  16. package/dist/acp/adapter/session-events.d.ts +1 -1
  17. package/dist/acp/adapter/session-events.d.ts.map +1 -1
  18. package/dist/acp/adapter/session-events.js +12 -11
  19. package/dist/acp/adapter/session-events.js.map +1 -1
  20. package/dist/acp/agent/agent-definition.d.ts +9 -21
  21. package/dist/acp/agent/agent-definition.d.ts.map +1 -1
  22. package/dist/acp/agent/agent-definition.js +11 -31
  23. package/dist/acp/agent/agent-definition.js.map +1 -1
  24. package/dist/acp/connection/agent-connection.d.ts +18 -10
  25. package/dist/acp/connection/agent-connection.d.ts.map +1 -1
  26. package/dist/acp/connection/agent-connection.js +1 -231
  27. package/dist/acp/connection/agent-connection.js.map +1 -1
  28. package/dist/acp/connection/agent-operation.d.ts +4 -0
  29. package/dist/acp/connection/agent-operation.d.ts.map +1 -0
  30. package/dist/acp/connection/agent-operation.js +57 -0
  31. package/dist/acp/connection/agent-operation.js.map +1 -0
  32. package/dist/acp/connection/endpoint-agent-connection.d.ts +28 -0
  33. package/dist/acp/connection/endpoint-agent-connection.d.ts.map +1 -0
  34. package/dist/acp/connection/endpoint-agent-connection.js +31 -0
  35. package/dist/acp/connection/endpoint-agent-connection.js.map +1 -0
  36. package/dist/agent/discovery/acp-readiness-probe.d.ts +1 -0
  37. package/dist/agent/discovery/acp-readiness-probe.d.ts.map +1 -1
  38. package/dist/agent/discovery/acp-readiness-probe.js +29 -188
  39. package/dist/agent/discovery/acp-readiness-probe.js.map +1 -1
  40. package/dist/agent/discovery/discover-agent.d.ts.map +1 -1
  41. package/dist/agent/discovery/discover-agent.js +4 -6
  42. package/dist/agent/discovery/discover-agent.js.map +1 -1
  43. package/dist/agent/discovery/executable-discovery.d.ts +1 -1
  44. package/dist/agent/discovery/executable-discovery.d.ts.map +1 -1
  45. package/dist/agent/discovery/executable-discovery.js +1 -6
  46. package/dist/agent/discovery/executable-discovery.js.map +1 -1
  47. package/dist/agent/specification/agent-specification.d.ts +3 -9
  48. package/dist/agent/specification/agent-specification.d.ts.map +1 -1
  49. package/dist/agent/specification/agent-specification.js +1 -12
  50. package/dist/agent/specification/agent-specification.js.map +1 -1
  51. package/dist/agent/specification/vendors/claude-code-agent.d.ts +2 -2
  52. package/dist/agent/specification/vendors/claude-code-agent.d.ts.map +1 -1
  53. package/dist/agent/specification/vendors/claude-code-agent.js +2 -2
  54. package/dist/agent/specification/vendors/claude-code-agent.js.map +1 -1
  55. package/dist/agent/specification/vendors/codex-agent.d.ts +2 -2
  56. package/dist/agent/specification/vendors/codex-agent.d.ts.map +1 -1
  57. package/dist/agent/specification/vendors/codex-agent.js +2 -2
  58. package/dist/agent/specification/vendors/codex-agent.js.map +1 -1
  59. package/dist/agent/specification/vendors/pi-agent.d.ts +2 -2
  60. package/dist/agent/specification/vendors/pi-agent.d.ts.map +1 -1
  61. package/dist/agent/specification/vendors/pi-agent.js +2 -2
  62. package/dist/agent/specification/vendors/pi-agent.js.map +1 -1
  63. package/dist/cli/handler/agents/logic/agent-diagnostics.d.ts.map +1 -1
  64. package/dist/cli/handler/agents/logic/agent-diagnostics.js +1 -4
  65. package/dist/cli/handler/agents/logic/agent-diagnostics.js.map +1 -1
  66. package/dist/cli.js +579 -860
  67. package/dist/cli.js.map +4 -4
  68. package/dist/runtime/catalog/resolve-catalog-agent.js +6 -3
  69. package/dist/runtime/catalog/resolve-catalog-agent.js.map +1 -1
  70. package/dist/runtime.d.ts +3 -2
  71. package/dist/runtime.d.ts.map +1 -1
  72. package/dist/runtime.js +303 -609
  73. package/dist/runtime.js.map +4 -4
  74. package/dist/session/settings/discover-agent-settings.js +1 -1
  75. package/dist/session/settings/discover-agent-settings.js.map +1 -1
  76. package/package.json +2 -2
package/dist/runtime.js CHANGED
@@ -1017,92 +1017,46 @@ function restrictAcpSessionCapabilities(capabilities, response) {
1017
1017
  }
1018
1018
 
1019
1019
  // src/acp/agent/agent-definition.ts
1020
- var AgentDefinition = class {
1020
+ var AcpAgentDefinition = class _AcpAgentDefinition {
1021
1021
  agentIdentity;
1022
1022
  agentVersion;
1023
+ adapterVersion;
1023
1024
  capabilities;
1024
1025
  command;
1025
1026
  environment;
1026
1027
  id;
1027
1028
  label;
1028
- constructor(id, label, _command, environment, agentVersion, agentIdentity, capabilities) {
1029
+ runtimeExecutables;
1030
+ #connectionFactory;
1031
+ constructor(id, label, command, createConnection, environment = {}, agentVersion = "", agentIdentity = readExecutableIdentity(command), capabilities = unsupportedSessionCapabilities(), adapterVersion = agentVersion, runtimeExecutables = [agentIdentity]) {
1029
1032
  this.agentIdentity = agentIdentity;
1030
1033
  this.agentVersion = agentVersion;
1034
+ this.adapterVersion = adapterVersion;
1031
1035
  this.capabilities = Object.freeze({ ...capabilities });
1032
1036
  this.command = agentIdentity.realPath;
1033
1037
  this.environment = Object.freeze({ ...environment });
1034
1038
  this.id = id;
1035
1039
  this.label = label;
1040
+ this.runtimeExecutables = Object.freeze([.../* @__PURE__ */ new Set([agentIdentity, ...runtimeExecutables])]);
1041
+ this.#connectionFactory = createConnection;
1036
1042
  }
1037
- };
1038
- var LocalAgentDefinition = class _LocalAgentDefinition extends AgentDefinition {
1039
- kind = "acp-adapter-process";
1040
- adapterIdentity;
1041
- adapterPath;
1042
- adapterVersion;
1043
- arguments;
1044
- constructor(id, label, command, arguments_, environment = {}, adapterVersion = "", agentVersion = "", adapterIdentity = readExecutableIdentity(command), agentIdentity = adapterIdentity, capabilities = unsupportedSessionCapabilities()) {
1045
- super(id, label, command, environment, agentVersion, agentIdentity, capabilities);
1046
- this.adapterIdentity = adapterIdentity;
1047
- this.adapterPath = adapterIdentity.realPath;
1048
- this.adapterVersion = adapterVersion;
1049
- this.arguments = Object.freeze([...arguments_]);
1050
- }
1051
- withEnvironment = (environment) => new _LocalAgentDefinition(
1043
+ createConnection = (options) => this.#connectionFactory({ ...options, command: this.command, environment: this.environment });
1044
+ withEnvironment = (environment) => new _AcpAgentDefinition(
1052
1045
  this.id,
1053
1046
  this.label,
1054
1047
  this.command,
1055
- this.arguments,
1048
+ this.#connectionFactory,
1056
1049
  environment,
1057
- this.adapterVersion,
1058
1050
  this.agentVersion,
1059
- this.adapterIdentity,
1060
1051
  this.agentIdentity,
1061
- this.capabilities
1062
- );
1063
- };
1064
- var InProcessAcpAgentDefinition = class _InProcessAcpAgentDefinition extends AgentDefinition {
1065
- kind = "in-process-acp";
1066
- createEndpoint;
1067
- constructor(id, label, command, createEndpoint, environment = {}, agentVersion = "", agentIdentity = readExecutableIdentity(command), capabilities = unsupportedSessionCapabilities()) {
1068
- super(id, label, command, environment, agentVersion, agentIdentity, capabilities);
1069
- this.createEndpoint = createEndpoint;
1070
- }
1071
- withEnvironment = (environment) => new _InProcessAcpAgentDefinition(
1072
- this.id,
1073
- this.label,
1074
- this.command,
1075
- this.createEndpoint,
1076
- environment,
1077
- this.agentVersion,
1078
- this.agentIdentity,
1079
- this.capabilities
1052
+ this.capabilities,
1053
+ this.adapterVersion,
1054
+ this.runtimeExecutables
1080
1055
  );
1081
1056
  };
1082
1057
 
1083
- // src/acp/adapter/adapter-registry.ts
1084
- var AdapterRegistry = class {
1085
- #resolve;
1086
- #dependencies;
1087
- #adapters = /* @__PURE__ */ new Map();
1088
- constructor(resolve19, dependencies) {
1089
- this.#resolve = resolve19;
1090
- this.#dependencies = dependencies;
1091
- }
1092
- resolve = (agent) => {
1093
- const existing = this.#adapters.get(agent.id);
1094
- if (existing !== void 0) {
1095
- return existing;
1096
- }
1097
- const adapter = this.#resolve(agent, this.#dependencies);
1098
- this.#adapters.set(agent.id, adapter);
1099
- return adapter;
1100
- };
1101
- close = async () => {
1102
- await Promise.all([...this.#adapters.values()].map((adapter) => adapter.close()));
1103
- this.#adapters.clear();
1104
- };
1105
- };
1058
+ // src/acp/connection/agent-operation.ts
1059
+ import { RequestError } from "@agentclientprotocol/sdk";
1106
1060
 
1107
1061
  // src/infra/operation-error.ts
1108
1062
  var OperationError = class extends Error {
@@ -1141,6 +1095,145 @@ var AcpConfigurationValueUnavailableError = class extends AcpExecutionError {
1141
1095
  }
1142
1096
  };
1143
1097
 
1098
+ // src/acp/agent/in-process-endpoint.ts
1099
+ function acpEndpointTerminationError(termination) {
1100
+ switch (termination.kind) {
1101
+ case "failed":
1102
+ return termination.error;
1103
+ case "closed":
1104
+ return new AcpExecutionError("The ACP endpoint is closed", {}, "acp_endpoint_closed");
1105
+ default: {
1106
+ const unreachable3 = termination;
1107
+ return unreachable3;
1108
+ }
1109
+ }
1110
+ }
1111
+
1112
+ // src/acp/connection/agent-operation.ts
1113
+ function requestErrorMessage(error62) {
1114
+ const fallback = truncate(error62.message, 500);
1115
+ if (error62.message !== "Internal error" || !isRecord(error62.data)) {
1116
+ return fallback;
1117
+ }
1118
+ const agentError = error62.data["error"];
1119
+ if (isRecord(agentError)) {
1120
+ const message = agentError["message"];
1121
+ if (typeof message === "string" && message.length > 0) {
1122
+ return truncate(message, 500);
1123
+ }
1124
+ }
1125
+ const details = error62.data["details"];
1126
+ return typeof details === "string" && details.length > 0 ? truncate(details, 500) : fallback;
1127
+ }
1128
+ async function raceAgentOperation(operation, termination, exitMessage, signal) {
1129
+ let removeAbortListener = () => {
1130
+ };
1131
+ const aborted2 = new Promise((_resolve, reject2) => {
1132
+ const rejectAbort = () => {
1133
+ reject2(signal.reason ?? new Error("ACP request was cancelled"));
1134
+ };
1135
+ signal.addEventListener("abort", rejectAbort, { once: true });
1136
+ removeAbortListener = () => signal.removeEventListener("abort", rejectAbort);
1137
+ if (signal.aborted) {
1138
+ rejectAbort();
1139
+ }
1140
+ });
1141
+ try {
1142
+ return await Promise.race([
1143
+ aborted2,
1144
+ operation,
1145
+ termination.then((result) => {
1146
+ const cause = acpEndpointTerminationError(result);
1147
+ throw new AcpExecutionError(exitMessage, { cause }, cause.code);
1148
+ })
1149
+ ]);
1150
+ } catch (error62) {
1151
+ signal.throwIfAborted();
1152
+ if (error62 instanceof RequestError && error62.code === -32e3) {
1153
+ throw new AcpExecutionError(
1154
+ "Agent authentication is required",
1155
+ { cause: error62 },
1156
+ "authentication_required"
1157
+ );
1158
+ }
1159
+ if (error62 instanceof RequestError) {
1160
+ throw new AcpExecutionError(requestErrorMessage(error62), { cause: error62 }, "acp_agent_error");
1161
+ }
1162
+ throw error62;
1163
+ } finally {
1164
+ removeAbortListener();
1165
+ }
1166
+ }
1167
+
1168
+ // src/acp/connection/create-client.ts
1169
+ import {
1170
+ client,
1171
+ methods
1172
+ } from "@agentclientprotocol/sdk";
1173
+ var createAcpClient = (handler) => client({ name: "mobius" }).onRequest(
1174
+ methods.client.session.requestPermission,
1175
+ async (context) => await handler.onPermission(context.params, context.signal)
1176
+ ).onRequest(
1177
+ methods.client.elicitation.create,
1178
+ async (context) => await handler.onElicitation(context.params, context.signal)
1179
+ ).onNotification(methods.client.session.update, async (context) => {
1180
+ await handler.onUpdate(context.params);
1181
+ }).onNotification(methods.client.elicitation.complete, async (context) => {
1182
+ await handler.onElicitationComplete(context.params);
1183
+ });
1184
+
1185
+ // src/acp/connection/endpoint-agent-connection.ts
1186
+ var EndpointAgentConnection = class {
1187
+ #endpoint;
1188
+ connection;
1189
+ termination;
1190
+ #closePromise = null;
1191
+ constructor(endpoint, client2) {
1192
+ this.#endpoint = endpoint;
1193
+ this.termination = endpoint.terminated;
1194
+ this.connection = createAcpClient(client2).connect(endpoint.app());
1195
+ }
1196
+ initialize = async (signal) => {
1197
+ await this.#endpoint.initialize(signal);
1198
+ };
1199
+ agentSettingsModelEffort = () => this.#endpoint.agentSettingsModelEffort?.() ?? null;
1200
+ closeProcess = () => {
1201
+ this.#closePromise ??= (async () => {
1202
+ try {
1203
+ await this.#endpoint.close();
1204
+ } finally {
1205
+ this.connection.close();
1206
+ }
1207
+ })();
1208
+ return this.#closePromise;
1209
+ };
1210
+ race = (operation, exitMessage, signal) => raceAgentOperation(operation, this.termination, exitMessage, signal);
1211
+ };
1212
+
1213
+ // src/acp/adapter/adapter-registry.ts
1214
+ var AdapterRegistry = class {
1215
+ #resolve;
1216
+ #dependencies;
1217
+ #adapters = /* @__PURE__ */ new Map();
1218
+ constructor(resolve19, dependencies) {
1219
+ this.#resolve = resolve19;
1220
+ this.#dependencies = dependencies;
1221
+ }
1222
+ resolve = (agent) => {
1223
+ const existing = this.#adapters.get(agent.id);
1224
+ if (existing !== void 0) {
1225
+ return existing;
1226
+ }
1227
+ const adapter = this.#resolve(agent, this.#dependencies);
1228
+ this.#adapters.set(agent.id, adapter);
1229
+ return adapter;
1230
+ };
1231
+ close = async () => {
1232
+ await Promise.all([...this.#adapters.values()].map((adapter) => adapter.close()));
1233
+ this.#adapters.clear();
1234
+ };
1235
+ };
1236
+
1144
1237
  // src/util/run-cleanup.ts
1145
1238
  async function runCleanup(...actions) {
1146
1239
  const [first, ...remaining] = actions;
@@ -22842,7 +22935,7 @@ var nativeSessionPageSchema = external_exports.object({
22842
22935
  }).readonly();
22843
22936
 
22844
22937
  // src/acp/protocol/session-config-protocol.ts
22845
- import { methods } from "@agentclientprotocol/sdk";
22938
+ import { methods as methods2 } from "@agentclientprotocol/sdk";
22846
22939
  var MAXIMUM_CONFIG_OPTIONS = 100;
22847
22940
  var SessionConfigProtocolError = class extends Error {
22848
22941
  code = "invalid_session_configuration_response";
@@ -23012,7 +23105,7 @@ var StandardSessionConfigProtocol = class {
23012
23105
  }
23013
23106
  if (existing.type === "select" && existing.category === "mode") {
23014
23107
  await transport.request(
23015
- methods.agent.session.setMode,
23108
+ methods2.agent.session.setMode,
23016
23109
  { modeId: change.value, sessionId: nativeSessionId },
23017
23110
  "ACP agent exited while setting the session mode",
23018
23111
  change.signal
@@ -23030,7 +23123,7 @@ var StandardSessionConfigProtocol = class {
23030
23123
  value: change.value
23031
23124
  };
23032
23125
  const response = await transport.request(
23033
- methods.agent.session.setConfigOption,
23126
+ methods2.agent.session.setConfigOption,
23034
23127
  params,
23035
23128
  "ACP agent exited while changing session configuration",
23036
23129
  change.signal
@@ -23051,266 +23144,6 @@ function sessionConfigProtocolForAgent(_agentId) {
23051
23144
  // src/acp/adapter/session-events.ts
23052
23145
  import { setImmediate as yieldToRuntime2 } from "node:timers/promises";
23053
23146
 
23054
- // src/acp/connection/agent-connection.ts
23055
- import { spawn as spawn2 } from "node:child_process";
23056
- import { ndJsonStream, RequestError } from "@agentclientprotocol/sdk";
23057
-
23058
- // src/acp/agent/in-process-endpoint.ts
23059
- function acpEndpointTerminationError(termination) {
23060
- switch (termination.kind) {
23061
- case "failed":
23062
- return termination.error;
23063
- case "closed":
23064
- return new AcpExecutionError("The ACP endpoint is closed", {}, "acp_endpoint_closed");
23065
- default: {
23066
- const unreachable3 = termination;
23067
- return unreachable3;
23068
- }
23069
- }
23070
- }
23071
-
23072
- // src/acp/connection/create-client.ts
23073
- import {
23074
- client,
23075
- methods as methods2
23076
- } from "@agentclientprotocol/sdk";
23077
- var createAcpClient = (handler) => client({ name: "mobius" }).onRequest(
23078
- methods2.client.session.requestPermission,
23079
- async (context) => await handler.onPermission(context.params, context.signal)
23080
- ).onRequest(
23081
- methods2.client.elicitation.create,
23082
- async (context) => await handler.onElicitation(context.params, context.signal)
23083
- ).onNotification(methods2.client.session.update, async (context) => {
23084
- await handler.onUpdate(context.params);
23085
- }).onNotification(methods2.client.elicitation.complete, async (context) => {
23086
- await handler.onElicitationComplete(context.params);
23087
- });
23088
-
23089
- // src/acp/connection/agent-connection.ts
23090
- function requestErrorMessage(error62) {
23091
- const fallback = truncate(error62.message, 500);
23092
- if (error62.message !== "Internal error" || !isRecord(error62.data)) {
23093
- return fallback;
23094
- }
23095
- const agentError = error62.data["error"];
23096
- if (isRecord(agentError)) {
23097
- const message = agentError["message"];
23098
- if (typeof message === "string" && message.length > 0) {
23099
- return truncate(message, 500);
23100
- }
23101
- }
23102
- const details = error62.data["details"];
23103
- return typeof details === "string" && details.length > 0 ? truncate(details, 500) : fallback;
23104
- }
23105
- function readableWebStream(input2) {
23106
- let streamOpen = true;
23107
- return new ReadableStream({
23108
- start(controller) {
23109
- input2.on("data", (chunk) => {
23110
- if (!streamOpen) {
23111
- return;
23112
- }
23113
- if (chunk instanceof Uint8Array) {
23114
- controller.enqueue(new Uint8Array(chunk));
23115
- return;
23116
- }
23117
- streamOpen = false;
23118
- controller.error(new Error("ACP process produced a non-binary chunk"));
23119
- });
23120
- input2.once("end", () => {
23121
- if (!streamOpen) {
23122
- return;
23123
- }
23124
- streamOpen = false;
23125
- controller.close();
23126
- });
23127
- input2.once("error", (error62) => {
23128
- if (!streamOpen) {
23129
- return;
23130
- }
23131
- streamOpen = false;
23132
- controller.error(error62);
23133
- });
23134
- },
23135
- cancel() {
23136
- streamOpen = false;
23137
- }
23138
- });
23139
- }
23140
- function createWritableAcpStream(output2) {
23141
- let outputFailure;
23142
- const pendingWriteFailures = /* @__PURE__ */ new Set();
23143
- const fail = (error62) => {
23144
- outputFailure = error62;
23145
- for (const reject2 of pendingWriteFailures) {
23146
- reject2(error62);
23147
- }
23148
- pendingWriteFailures.clear();
23149
- };
23150
- output2.on("error", fail);
23151
- output2.once("close", () => {
23152
- if (outputFailure === void 0) {
23153
- fail(new Error("ACP process input closed"));
23154
- }
23155
- });
23156
- return new WritableStream({
23157
- write(chunk) {
23158
- if (outputFailure !== void 0) {
23159
- return Promise.reject(outputFailure);
23160
- }
23161
- return new Promise((resolve19, reject2) => {
23162
- pendingWriteFailures.add(reject2);
23163
- output2.write(chunk, (error62) => {
23164
- pendingWriteFailures.delete(reject2);
23165
- if (error62) {
23166
- outputFailure = error62;
23167
- reject2(error62);
23168
- return;
23169
- }
23170
- if (outputFailure !== void 0) {
23171
- reject2(outputFailure);
23172
- return;
23173
- }
23174
- resolve19();
23175
- });
23176
- });
23177
- }
23178
- });
23179
- }
23180
- var AgentConnection = class {
23181
- connection;
23182
- termination;
23183
- #process;
23184
- constructor(agent, cwd, client2, onBackgroundActivity = () => {
23185
- }) {
23186
- if (agent.kind === "in-process-acp") {
23187
- const inProcess = agent.createEndpoint({
23188
- command: agent.command,
23189
- cwd,
23190
- environment: agent.environment,
23191
- onSessionUpdate: client2.onUpdate,
23192
- onBackgroundActivity
23193
- });
23194
- this.#process = { kind: "in-process", endpoint: inProcess };
23195
- this.termination = inProcess.terminated;
23196
- this.connection = createAcpClient(client2).connect(inProcess.app());
23197
- return;
23198
- }
23199
- const launch = executableLaunch2(agent.adapterPath, agent.arguments);
23200
- const child = spawn2(launch.command, [...launch.arguments], {
23201
- cwd,
23202
- ...platformSpawnOptions,
23203
- env: { ...process.env, ...agent.environment },
23204
- shell: false,
23205
- stdio: ["pipe", "pipe", "pipe"]
23206
- });
23207
- this.#process = { kind: "child", child };
23208
- const stdin = child.stdin;
23209
- const stdout = child.stdout;
23210
- const stderr = child.stderr;
23211
- if (stdin === null || stdout === null || stderr === null) {
23212
- child.kill("SIGKILL");
23213
- throw new AcpExecutionError("ACP process streams are unavailable");
23214
- }
23215
- stderr.setEncoding("utf8");
23216
- stderr.on("data", (chunk) => {
23217
- process.stderr.write(`[${agent.id}-acp] ${chunk}`);
23218
- });
23219
- this.termination = new Promise((resolve19) => {
23220
- child.once("error", (cause) => {
23221
- resolve19({ kind: "failed", error: new AcpExecutionError("The ACP process could not run", { cause }) });
23222
- });
23223
- child.once("exit", (code, signal) => {
23224
- resolve19({
23225
- kind: "failed",
23226
- error: new AcpExecutionError("The ACP process stopped", { cause: { code, signal } })
23227
- });
23228
- });
23229
- });
23230
- const stream = ndJsonStream(createWritableAcpStream(stdin), readableWebStream(stdout));
23231
- let pendingUpdates = 0;
23232
- this.connection = createAcpClient({
23233
- onElicitation: client2.onElicitation,
23234
- onElicitationComplete: client2.onElicitationComplete,
23235
- onPermission: client2.onPermission,
23236
- // ACP notifications acknowledge transport writes, not their consumption.
23237
- // Stop reading the child while updates from the current chunk drain;
23238
- // the OS pipe then backpressures history replay instead of filling our queue.
23239
- onUpdate: async (notification) => {
23240
- pendingUpdates += 1;
23241
- stdout.pause();
23242
- try {
23243
- await client2.onUpdate(notification);
23244
- } finally {
23245
- pendingUpdates -= 1;
23246
- if (pendingUpdates === 0) {
23247
- stdout.resume();
23248
- }
23249
- }
23250
- }
23251
- }).connect(stream);
23252
- }
23253
- get inProcessAgent() {
23254
- return this.#process.kind === "in-process" ? this.#process.endpoint : null;
23255
- }
23256
- closeProcess = async () => {
23257
- try {
23258
- if (this.#process.kind === "in-process") {
23259
- await this.#process.endpoint.close();
23260
- return;
23261
- }
23262
- await stopProcessTree(this.#process.child);
23263
- } finally {
23264
- this.connection.close();
23265
- }
23266
- };
23267
- race = async (operation, exitMessage, signal) => {
23268
- let removeAbortListener = () => {
23269
- };
23270
- const aborted2 = new Promise((_resolve, reject2) => {
23271
- const rejectAbort = () => {
23272
- reject2(signal.reason ?? new Error("ACP request was cancelled"));
23273
- };
23274
- signal.addEventListener("abort", rejectAbort, { once: true });
23275
- removeAbortListener = () => {
23276
- signal.removeEventListener("abort", rejectAbort);
23277
- };
23278
- if (signal.aborted) {
23279
- rejectAbort();
23280
- }
23281
- });
23282
- try {
23283
- try {
23284
- return await Promise.race([
23285
- // The caller has already started operation. Even when cancellation
23286
- // won before entry, observe its later rejection during endpoint cleanup.
23287
- aborted2,
23288
- operation,
23289
- this.termination.then((termination) => {
23290
- const cause = acpEndpointTerminationError(termination);
23291
- throw new AcpExecutionError(exitMessage, { cause }, cause.code);
23292
- })
23293
- ]);
23294
- } catch (error62) {
23295
- signal.throwIfAborted();
23296
- if (error62 instanceof RequestError && error62.code === -32e3) {
23297
- throw new AcpExecutionError(
23298
- "Agent authentication is required",
23299
- { cause: error62 },
23300
- "authentication_required"
23301
- );
23302
- }
23303
- if (error62 instanceof RequestError) {
23304
- throw new AcpExecutionError(requestErrorMessage(error62), { cause: error62 }, "acp_agent_error");
23305
- }
23306
- throw error62;
23307
- }
23308
- } finally {
23309
- removeAbortListener();
23310
- }
23311
- };
23312
- };
23313
-
23314
23147
  // src/acp/connection/agent-update-stream.ts
23315
23148
  import { setImmediate as yieldToRuntime } from "node:timers/promises";
23316
23149
  var MAX_PENDING_UPDATES = 100;
@@ -23539,21 +23372,23 @@ var AdapterSessionConnection = class {
23539
23372
  onElicitation: options.interactions.onElicitation,
23540
23373
  onElicitationComplete: options.interactions.onElicitationComplete
23541
23374
  };
23542
- this.#connection = new AgentConnection(options.agent, options.cwd, client2, (active) => {
23543
- if (this.#lifetime.signal.aborted) {
23544
- return;
23375
+ this.#connection = options.agent.createConnection({
23376
+ cwd: options.cwd,
23377
+ client: client2,
23378
+ onBackgroundActivity: (active) => {
23379
+ if (this.#lifetime.signal.aborted) {
23380
+ return;
23381
+ }
23382
+ this.#backgroundActivity = active;
23383
+ this.#onBackgroundActivity(active);
23545
23384
  }
23546
- this.#backgroundActivity = active;
23547
- this.#onBackgroundActivity(active);
23548
23385
  });
23549
23386
  }
23550
23387
  get connection() {
23551
23388
  return this.#connection.connection;
23552
23389
  }
23553
- get inProcessAgent() {
23554
- return this.#connection.inProcessAgent;
23555
- }
23556
- agentSettingsModelEffort = () => this.#connection.inProcessAgent?.agentSettingsModelEffort?.() ?? null;
23390
+ initialize = (signal) => this.#connection.initialize(signal);
23391
+ agentSettingsModelEffort = () => this.#connection.agentSettingsModelEffort();
23557
23392
  race = (operation, exitMessage, signal) => this.#connection.race(operation, exitMessage, signal);
23558
23393
  closeProcess = async () => {
23559
23394
  this.#lifetime.abort(new DOMException("The adapter event subscription closed", "AbortError"));
@@ -24611,10 +24446,7 @@ var RetryableAcpInitializationError = class extends AcpExecutionError {
24611
24446
  };
24612
24447
  async function validateAgentRuntime(agent, signal) {
24613
24448
  signal.throwIfAborted();
24614
- const unchanged = await Promise.all([
24615
- agent.kind === "acp-adapter-process" ? revalidateExecutable(agent.adapterIdentity) : Promise.resolve(true),
24616
- revalidateExecutable(agent.agentIdentity)
24617
- ]);
24449
+ const unchanged = await Promise.all(agent.runtimeExecutables.map((identity2) => revalidateExecutable(identity2)));
24618
24450
  signal.throwIfAborted();
24619
24451
  if (unchanged.some((result) => !result)) {
24620
24452
  throw new AcpExecutionError(
@@ -24625,16 +24457,10 @@ async function validateAgentRuntime(agent, signal) {
24625
24457
  }
24626
24458
  }
24627
24459
  async function initializeAgentConnection(connection, agentId, verifiedVersion, signal) {
24628
- if (connection.inProcessAgent !== null) {
24629
- await connection.race(
24630
- connection.inProcessAgent.initialize(signal),
24631
- "The Codex app-server exited during initialization",
24632
- signal
24633
- ).catch((cause) => {
24634
- signal.throwIfAborted();
24635
- throw new RetryableAcpInitializationError(cause);
24636
- });
24637
- }
24460
+ await connection.race(connection.initialize(signal), "The Agent runtime exited during initialization", signal).catch((cause) => {
24461
+ signal.throwIfAborted();
24462
+ throw new RetryableAcpInitializationError(cause);
24463
+ });
24638
24464
  const initialized = await connection.race(
24639
24465
  connection.connection.agent.request(
24640
24466
  methods4.agent.initialize,
@@ -24943,7 +24769,7 @@ var ClaudeAdapter = class {
24943
24769
  import { createHash as createHash3 } from "node:crypto";
24944
24770
 
24945
24771
  // src/acp/harness/codex/app-server-client.ts
24946
- import { spawn as spawn3 } from "node:child_process";
24772
+ import { spawn as spawn2 } from "node:child_process";
24947
24773
 
24948
24774
  // src/acp/harness/codex/app-server-protocol.ts
24949
24775
  import { isAbsolute as isAbsolute5 } from "node:path";
@@ -25263,7 +25089,7 @@ var CodexAppServerClient = class {
25263
25089
  constructor(options) {
25264
25090
  this.#handlers = options.handlers;
25265
25091
  const launch = executableLaunch2(options.command, ["app-server"]);
25266
- this.#child = spawn3(launch.command, [...launch.arguments], {
25092
+ this.#child = spawn2(launch.command, [...launch.arguments], {
25267
25093
  cwd: options.cwd,
25268
25094
  ...platformSpawnOptions,
25269
25095
  env: { ...process.env, ...options.environment },
@@ -25917,12 +25743,12 @@ function presentToolItem(item) {
25917
25743
  };
25918
25744
  }
25919
25745
  if (item.type === "collabAgentToolCall") {
25920
- const spawn8 = item.tool === "spawnAgent";
25746
+ const spawn6 = item.tool === "spawnAgent";
25921
25747
  return {
25922
25748
  content: [],
25923
25749
  kind: "other",
25924
25750
  locations: [],
25925
- rawInput: spawn8 ? {
25751
+ rawInput: spawn6 ? {
25926
25752
  model: item.model,
25927
25753
  prompt: item.prompt,
25928
25754
  reasoningEffort: item.reasoningEffort,
@@ -25930,10 +25756,10 @@ function presentToolItem(item) {
25930
25756
  } : { receiverThreadIds: item.receiverThreadIds, senderThreadId: item.senderThreadId },
25931
25757
  rawOutput: {
25932
25758
  agentsStates: item.agentsStates,
25933
- ...spawn8 ? { receiverThreadIds: item.receiverThreadIds } : {}
25759
+ ...spawn6 ? { receiverThreadIds: item.receiverThreadIds } : {}
25934
25760
  },
25935
25761
  status: collaborationStatus(item.status),
25936
- title: spawn8 ? "Dispatch subagent" : "Wait for subagent"
25762
+ title: spawn6 ? "Dispatch subagent" : "Wait for subagent"
25937
25763
  };
25938
25764
  }
25939
25765
  if (item.type === "subAgentActivity" && item.kind === "started") {
@@ -32455,7 +32281,7 @@ import { fetch as fetch3 } from "undici";
32455
32281
  // package.json
32456
32282
  var package_default = {
32457
32283
  name: "@moxt-ai/mobius",
32458
- version: "0.0.318",
32284
+ version: "0.0.320",
32459
32285
  description: "Mobius CLI for pairing and running local AI agent services.",
32460
32286
  type: "module",
32461
32287
  bin: {
@@ -32559,7 +32385,7 @@ var package_default = {
32559
32385
  };
32560
32386
 
32561
32387
  // src/acp/harness/claude/parent-lifeline.ts
32562
- import { spawn as spawn4 } from "node:child_process";
32388
+ import { spawn as spawn3 } from "node:child_process";
32563
32389
  import { Duplex } from "node:stream";
32564
32390
  var supervisor = `
32565
32391
  const { spawn, spawnSync } = require("node:child_process");
@@ -32588,7 +32414,7 @@ child.once("close", (code) => { exited = true; process.exitCode = code ?? 1; lif
32588
32414
  `;
32589
32415
  function spawnClaudeWithParentLifeline(options) {
32590
32416
  options.signal.throwIfAborted();
32591
- const child = spawn4(process.execPath, ["-e", supervisor, "--", options.command, ...options.args], {
32417
+ const child = spawn3(process.execPath, ["-e", supervisor, "--", options.command, ...options.args], {
32592
32418
  cwd: options.cwd,
32593
32419
  env: options.env,
32594
32420
  stdio: ["pipe", "pipe", "pipe", "pipe"],
@@ -32638,7 +32464,7 @@ import * as fs3 from "node:fs/promises";
32638
32464
  import * as os3 from "node:os";
32639
32465
  import * as path6 from "node:path";
32640
32466
  import { promisify as promisify2 } from "node:util";
32641
- import { agent as acpAgent, CreateElicitationResponse as CreateElicitationResponse2, methods as methods7, ndJsonStream as ndJsonStream2, RequestError as RequestError4 } from "@agentclientprotocol/sdk";
32467
+ import { agent as acpAgent, CreateElicitationResponse as CreateElicitationResponse2, methods as methods7, ndJsonStream, RequestError as RequestError4 } from "@agentclientprotocol/sdk";
32642
32468
 
32643
32469
  // ../../node_modules/.pnpm/@anthropic-ai+claude-agent-sdk@0.3.257_@anthropic-ai+sdk@0.122.0_zod@4.6.5__@modelconte_b0b90ed00d211c5955785f7de7f8dbf4/node_modules/@anthropic-ai/claude-agent-sdk/sdk.mjs
32644
32470
  import { createRequire as $ne } from "node:module";
@@ -73410,16 +73236,15 @@ var ClaudeAcpAgent = class {
73410
73236
  session.lastSessionState = message.state;
73411
73237
  if (message.state === "idle") {
73412
73238
  disarmResultWatchdog();
73239
+ const boundary = session.idleBoundary;
73240
+ const hadEarlierResult = boundary.kind === "accounted" && boundary.turn !== session.activeTurn;
73241
+ session.idleBoundary = { kind: "unaccounted" };
73413
73242
  if (session.cancelled && session.activeTurn && !session.activeTurn.settled) {
73414
73243
  settleActive(turnOutcome(session, "cancelled"));
73415
73244
  session.emittedAssistantText = false;
73416
73245
  } else if (isHeldOpen(session.activeTurn)) {
73417
- if (session.owedTrailingIdles > 0) {
73418
- session.owedTrailingIdles--;
73419
- }
73420
73246
  settleDeferredIfDrained();
73421
- } else if (session.owedTrailingIdles > 0) {
73422
- session.owedTrailingIdles--;
73247
+ } else if (hadEarlierResult) {
73423
73248
  } else if (isSteering(session.activeTurn)) {
73424
73249
  const steered = session.activeTurn;
73425
73250
  if (steered.steeredEchoes?.size === 0 && steered.steeredSettle !== void 0) {
@@ -73428,7 +73253,7 @@ var ClaudeAcpAgent = class {
73428
73253
  steered.steeredSettle = void 0;
73429
73254
  settleDeferredIfDrained();
73430
73255
  }
73431
- } else if (!session.cancelled && session.activeTurn && !session.activeTurn.settled) {
73256
+ } else if (boundary.kind === "unaccounted" && !session.cancelled && session.activeTurn && !session.activeTurn.settled) {
73432
73257
  this.logger.error(`Session ${params.sessionId}: SDK went idle without emitting a result for the active turn; failing the in-flight prompt (issue #825)`);
73433
73258
  failActive(RequestError4.internalError(errorKindData("no_result"), TURN_NO_RESULT_MESSAGE));
73434
73259
  }
@@ -73689,9 +73514,8 @@ ${message.api_refusal_explanation}` : "";
73689
73514
  }
73690
73515
  }
73691
73516
  const deliveredAssistantText = session.emittedAssistantText;
73692
- const owesTrailingIdle = isAutonomousResult || !isSteering(session.activeTurn);
73693
- if (owesTrailingIdle && (isAutonomousResult || !session.cancelled || !session.activeTurn)) {
73694
- session.owedTrailingIdles++;
73517
+ if (isAutonomousResult || !session.cancelled || !session.activeTurn) {
73518
+ session.idleBoundary = { kind: "accounted", turn: session.activeTurn ?? null };
73695
73519
  }
73696
73520
  if (!isAutonomousResult) {
73697
73521
  session.accumulatedUsage.inputTokens += message.usage.input_tokens;
@@ -73953,12 +73777,18 @@ ${message.api_refusal_explanation}` : "";
73953
73777
  if (session.activeTurn !== queued) {
73954
73778
  if (session.activeTurn) {
73955
73779
  if (session.cancelled) {
73956
- session.owedTrailingIdles++;
73780
+ session.idleBoundary = {
73781
+ kind: "accounted",
73782
+ turn: session.activeTurn ?? null
73783
+ };
73957
73784
  settleActive(turnOutcome(session, "cancelled"));
73958
73785
  } else if (isHeldOpen(session.activeTurn)) {
73959
73786
  settleActive(session.activeTurn.deferredSettle);
73960
73787
  } else if (isSteering(session.activeTurn) && session.activeTurn.steeredSettle !== void 0) {
73961
- session.owedTrailingIdles++;
73788
+ session.idleBoundary = {
73789
+ kind: "accounted",
73790
+ turn: session.activeTurn ?? null
73791
+ };
73962
73792
  settleActive(session.activeTurn.steeredSettle);
73963
73793
  } else {
73964
73794
  settleActive(turnOutcome(session, "end_turn"));
@@ -73969,8 +73799,8 @@ ${message.api_refusal_explanation}` : "";
73969
73799
  break;
73970
73800
  }
73971
73801
  if ("isReplay" in message && message.isReplay) {
73972
- if (isSteering(session.activeTurn)) {
73973
- session.activeTurn.steeredEchoes.delete(message.uuid);
73802
+ if (isSteering(session.activeTurn) && session.activeTurn.steeredEchoes.delete(message.uuid)) {
73803
+ session.activeTurn.steeredSettle = void 0;
73974
73804
  }
73975
73805
  break;
73976
73806
  }
@@ -74235,7 +74065,7 @@ ${message.api_refusal_explanation}` : "";
74235
74065
  session.activeTurn = null;
74236
74066
  session.emittedAssistantText = false;
74237
74067
  if (session.lastSessionState !== "idle") {
74238
- session.owedTrailingIdles++;
74068
+ session.idleBoundary = { kind: "accounted", turn: active };
74239
74069
  }
74240
74070
  active.resolve({
74241
74071
  stopReason: "cancelled",
@@ -74245,7 +74075,7 @@ ${message.api_refusal_explanation}` : "";
74245
74075
  }
74246
74076
  }
74247
74077
  if (isSteering(session.activeTurn) && session.activeTurn.steeredSettle !== void 0) {
74248
- session.owedTrailingIdles++;
74078
+ session.idleBoundary = { kind: "accounted", turn: session.activeTurn ?? null };
74249
74079
  }
74250
74080
  if (session.activeTurn && session.cancelController && !session.cancelController.signal.aborted && !session.forceCancelTimer) {
74251
74081
  const cancelController = session.cancelController;
@@ -75263,7 +75093,7 @@ ${message.api_refusal_explanation}` : "";
75263
75093
  emittedToolCalls: /* @__PURE__ */ new Set(),
75264
75094
  liveBackgroundTasks: /* @__PURE__ */ new Map(),
75265
75095
  emittedAssistantText: false,
75266
- owedTrailingIdles: 0,
75096
+ idleBoundary: { kind: "unaccounted" },
75267
75097
  messageIdToUuid: /* @__PURE__ */ new Map()
75268
75098
  };
75269
75099
  return {
@@ -76670,6 +76500,20 @@ var ClaudeAcpEndpoint = class {
76670
76500
  };
76671
76501
  };
76672
76502
 
76503
+ // src/acp/adapter/claude/agent-connection.ts
76504
+ var ClaudeAgentConnection = class extends EndpointAgentConnection {
76505
+ constructor(options) {
76506
+ const endpoint = new ClaudeAcpEndpoint({
76507
+ command: options.command,
76508
+ cwd: options.cwd,
76509
+ environment: options.environment,
76510
+ onSessionUpdate: options.client.onUpdate,
76511
+ onBackgroundActivity: (active) => options.onBackgroundActivity?.(active)
76512
+ });
76513
+ super(endpoint, options.client);
76514
+ }
76515
+ };
76516
+
76673
76517
  // src/agent/discovery/version-output.ts
76674
76518
  function normalizeVersionOutput(output2) {
76675
76519
  return output2.trim().split(/\r?\n/, 1)[0]?.trim().slice(0, 128) ?? "";
@@ -76693,17 +76537,6 @@ var LocalAgentSpecification = class {
76693
76537
  resolveInstalledAgentExecutables = (_context) => Promise.resolve([]);
76694
76538
  verifyAcp = (_connection, _initialized, _defaultWorkspace, _signal) => Promise.resolve();
76695
76539
  };
76696
- var DirectAcpAgentSpecification = class extends LocalAgentSpecification {
76697
- adapterOverrideVariable;
76698
- agentOverrideVariable;
76699
- launchArguments;
76700
- constructor(executableOverrideVariable, launchArguments) {
76701
- super();
76702
- this.adapterOverrideVariable = executableOverrideVariable;
76703
- this.agentOverrideVariable = executableOverrideVariable;
76704
- this.launchArguments = Object.freeze([...launchArguments]);
76705
- }
76706
- };
76707
76540
  var InProcessAcpAgentSpecification = class extends LocalAgentSpecification {
76708
76541
  launchArguments = Object.freeze([]);
76709
76542
  adapterOverrideVariable;
@@ -76719,7 +76552,7 @@ var InProcessAcpAgentSpecification = class extends LocalAgentSpecification {
76719
76552
  // src/agent/specification/vendors/claude-code-agent.ts
76720
76553
  var ClaudeCodeAgentSpecification = class extends InProcessAcpAgentSpecification {
76721
76554
  agentExecutable = "claude";
76722
- createEndpoint = (options) => new ClaudeAcpEndpoint(options);
76555
+ createConnection = (options) => new ClaudeAgentConnection(options);
76723
76556
  id = "claude";
76724
76557
  label = "Claude Code";
76725
76558
  minimumSupportedAgentVersion = "2.1.273";
@@ -77725,11 +77558,25 @@ var CodexAcpAgent = class {
77725
77558
  };
77726
77559
  };
77727
77560
 
77561
+ // src/acp/adapter/codex/agent-connection.ts
77562
+ var CodexAgentConnection = class extends EndpointAgentConnection {
77563
+ constructor(options) {
77564
+ const endpoint = new CodexAcpAgent({
77565
+ command: options.command,
77566
+ cwd: options.cwd,
77567
+ environment: options.environment,
77568
+ onSessionUpdate: options.client.onUpdate,
77569
+ onBackgroundActivity: (active) => options.onBackgroundActivity?.(active)
77570
+ });
77571
+ super(endpoint, options.client);
77572
+ }
77573
+ };
77574
+
77728
77575
  // src/agent/specification/vendors/codex-agent.ts
77729
77576
  var CodexAgentSpecification = class extends InProcessAcpAgentSpecification {
77730
77577
  versionProbeTimeoutMilliseconds = 1e4;
77731
77578
  agentExecutable = "codex";
77732
- createEndpoint = (options) => new CodexAcpAgent(options);
77579
+ createConnection = (options) => new CodexAgentConnection(options);
77733
77580
  id = "codex";
77734
77581
  label = "Codex";
77735
77582
  minimumSupportedAgentVersion = "0.153.0";
@@ -77757,7 +77604,7 @@ import { basename as basename5, dirname as dirname8, isAbsolute as isAbsolute13,
77757
77604
  import { RequestError as RequestError8 } from "@agentclientprotocol/sdk";
77758
77605
 
77759
77606
  // src/acp/harness/pi/upstream/dist/pi-rpc/process.js
77760
- import { spawn as spawn6 } from "node:child_process";
77607
+ import { spawn as spawn5 } from "node:child_process";
77761
77608
  import * as readline from "node:readline";
77762
77609
 
77763
77610
  // src/acp/harness/pi/upstream/dist/pi-rpc/command.js
@@ -77874,7 +77721,7 @@ var PiRpcProcess = class _PiRpcProcess {
77874
77721
  args.push("--fork", params.origin.sessionPath);
77875
77722
  break;
77876
77723
  }
77877
- const child = spawn6(cmd, args, {
77724
+ const child = spawn5(cmd, args, {
77878
77725
  cwd: params.cwd,
77879
77726
  stdio: "pipe",
77880
77727
  env: params.environment,
@@ -81590,6 +81437,20 @@ function piAgentOrThrow(agent) {
81590
81437
  return agent;
81591
81438
  }
81592
81439
 
81440
+ // src/acp/adapter/pi/agent-connection.ts
81441
+ var PiAgentConnection = class extends EndpointAgentConnection {
81442
+ constructor(options) {
81443
+ const endpoint = new PiAcpEndpoint({
81444
+ command: options.command,
81445
+ cwd: options.cwd,
81446
+ environment: options.environment,
81447
+ onSessionUpdate: options.client.onUpdate,
81448
+ onBackgroundActivity: (active) => options.onBackgroundActivity?.(active)
81449
+ });
81450
+ super(endpoint, options.client);
81451
+ }
81452
+ };
81453
+
81593
81454
  // src/agent/discovery/agent-probe-error.ts
81594
81455
  var AgentProbeError = class extends Error {
81595
81456
  code;
@@ -81605,7 +81466,7 @@ var ACP_PROBE_TIMEOUT_MILLISECONDS2 = 3e4;
81605
81466
  var PiAgentSpecification = class extends InProcessAcpAgentSpecification {
81606
81467
  acpProbeTimeoutMilliseconds = ACP_PROBE_TIMEOUT_MILLISECONDS2;
81607
81468
  agentExecutable = "pi";
81608
- createEndpoint = (options) => new PiAcpEndpoint(options);
81469
+ createConnection = (options) => new PiAgentConnection(options);
81609
81470
  // The Pi ACP fork inlines embedded prompt resources into the turn message, so Mobius
81610
81471
  // keeps the adapter's opt-in capability flag enabled for every launch it owns.
81611
81472
  createLaunchEnvironment = async (_agent, context) => {
@@ -81793,14 +81654,10 @@ var LocalAgentInventory = class {
81793
81654
  };
81794
81655
 
81795
81656
  // src/agent/discovery/acp-readiness-probe.ts
81796
- import { spawn as spawn7 } from "node:child_process";
81797
81657
  import {
81798
81658
  methods as methods12,
81799
- ndJsonStream as ndJsonStream3,
81800
- PROTOCOL_VERSION as PROTOCOL_VERSION3,
81801
- RequestError as RequestError9
81659
+ PROTOCOL_VERSION as PROTOCOL_VERSION3
81802
81660
  } from "@agentclientprotocol/sdk";
81803
- var ACP_OUTPUT_LIMIT_BYTES = 1024 * 1024;
81804
81661
  var VerifiedAcpReadiness = class {
81805
81662
  adapterVersion;
81806
81663
  capabilities;
@@ -81815,76 +81672,38 @@ var DiscoveryAcpHandler = class {
81815
81672
  onPermission = (_request, _signal) => Promise.reject(new Error("ACP probe does not grant permissions"));
81816
81673
  onUpdate = (_notification) => Promise.resolve();
81817
81674
  };
81818
- function readableAcpStream(input2) {
81819
- let byteLength = 0;
81820
- let open6 = true;
81821
- return new ReadableStream({
81822
- start(controller) {
81823
- input2.on("data", (chunk) => {
81824
- if (!open6) {
81825
- return;
81826
- }
81827
- if (!(chunk instanceof Uint8Array)) {
81828
- open6 = false;
81829
- controller.error(new Error("ACP adapter produced invalid output"));
81830
- return;
81831
- }
81832
- byteLength += chunk.byteLength;
81833
- if (byteLength > ACP_OUTPUT_LIMIT_BYTES) {
81834
- open6 = false;
81835
- controller.error(new Error("ACP adapter output limit exceeded"));
81836
- return;
81837
- }
81838
- controller.enqueue(new Uint8Array(chunk));
81839
- });
81840
- input2.once("end", () => {
81841
- if (open6) {
81842
- open6 = false;
81843
- controller.close();
81844
- }
81845
- });
81846
- input2.once("error", (error62) => {
81847
- if (open6) {
81848
- open6 = false;
81849
- controller.error(error62);
81850
- }
81851
- });
81852
- },
81853
- cancel() {
81854
- open6 = false;
81855
- }
81856
- });
81857
- }
81858
- function writableAcpStream(output2) {
81859
- return new WritableStream({
81860
- write(chunk) {
81861
- return new Promise((resolveWrite, rejectWrite) => {
81862
- output2.write(chunk, (error62) => {
81863
- if (error62) {
81864
- rejectWrite(error62);
81865
- return;
81866
- }
81867
- resolveWrite();
81868
- });
81869
- });
81675
+ function filterEnvironment(environment) {
81676
+ const filtered = {};
81677
+ for (const [name2, value] of Object.entries(environment)) {
81678
+ if (typeof value === "string") {
81679
+ filtered[name2] = value;
81870
81680
  }
81871
- });
81681
+ }
81682
+ return filtered;
81872
81683
  }
81873
- async function probeInProcessReadiness(specification, agent, environment, defaultWorkspace, controller) {
81874
- const handler = new DiscoveryAcpHandler();
81875
- const inProcess = agent.createEndpoint({
81876
- command: agent.command,
81877
- cwd: defaultWorkspace,
81878
- environment: { ...filterEnvironment(environment), ...agent.environment },
81879
- onSessionUpdate: handler.onUpdate
81880
- });
81684
+ async function probeAcpReadiness(specification, agent, environment, defaultWorkspace, signal) {
81685
+ signal.throwIfAborted();
81686
+ const controller = new AbortController();
81687
+ let timedOut = false;
81688
+ const timeout = setTimeout(() => {
81689
+ timedOut = true;
81690
+ controller.abort(new Error("ACP probe timed out"));
81691
+ }, specification.acpProbeTimeoutMilliseconds);
81692
+ const abort = () => controller.abort(signal.reason);
81693
+ signal.addEventListener("abort", abort, { once: true });
81694
+ if (signal.aborted) {
81695
+ abort();
81696
+ }
81881
81697
  try {
81882
- const connection = createAcpClient(handler).connect(inProcess.app());
81698
+ const runtime = agent.withEnvironment({ ...filterEnvironment(environment), ...agent.environment }).createConnection({
81699
+ cwd: defaultWorkspace,
81700
+ client: new DiscoveryAcpHandler()
81701
+ });
81883
81702
  try {
81884
- return await Promise.race([
81703
+ return await runtime.race(
81885
81704
  (async () => {
81886
- await inProcess.initialize(controller.signal);
81887
- const initialized = await connection.agent.request(
81705
+ await runtime.initialize(controller.signal);
81706
+ const initialized = await runtime.connection.agent.request(
81888
81707
  methods12.agent.initialize,
81889
81708
  {
81890
81709
  clientCapabilities: {},
@@ -81899,148 +81718,33 @@ async function probeInProcessReadiness(specification, agent, environment, defaul
81899
81718
  "ACP agent selected an unsupported protocol version"
81900
81719
  );
81901
81720
  }
81902
- await specification.verifyAcp(connection, initialized, defaultWorkspace, controller.signal);
81721
+ await specification.verifyAcp(runtime.connection, initialized, defaultWorkspace, controller.signal);
81903
81722
  return new VerifiedAcpReadiness(
81904
81723
  normalizeVersionOutput(initialized.agentInfo?.version ?? ""),
81905
81724
  normalizeAcpCapabilities(initialized)
81906
81725
  );
81907
81726
  })(),
81908
- inProcess.terminated.then((termination) => {
81909
- throw new AgentProbeError("acp_incompatible", "The ACP endpoint stopped during initialization", {
81910
- cause: acpEndpointTerminationError(termination)
81911
- });
81912
- })
81913
- ]);
81914
- } finally {
81915
- connection.close();
81916
- }
81917
- } finally {
81918
- await inProcess.close();
81919
- }
81920
- }
81921
- function filterEnvironment(environment) {
81922
- const filtered = {};
81923
- for (const [name2, value] of Object.entries(environment)) {
81924
- if (typeof value === "string") {
81925
- filtered[name2] = value;
81926
- }
81927
- }
81928
- return filtered;
81929
- }
81930
- async function probeAcpReadiness(specification, agent, environment, defaultWorkspace, signal) {
81931
- signal.throwIfAborted();
81932
- const controller = new AbortController();
81933
- let timedOut = false;
81934
- const timeout = setTimeout(() => {
81935
- timedOut = true;
81936
- controller.abort(new Error("ACP probe timed out"));
81937
- }, specification.acpProbeTimeoutMilliseconds);
81938
- const abort = () => controller.abort(signal.reason);
81939
- signal.addEventListener("abort", abort, { once: true });
81940
- if (signal.aborted) {
81941
- abort();
81942
- }
81943
- if (agent.kind === "in-process-acp") {
81944
- try {
81945
- return await probeInProcessReadiness(specification, agent, environment, defaultWorkspace, controller);
81946
- } catch (error62) {
81947
- if (signal.aborted) {
81948
- signal.throwIfAborted();
81949
- }
81950
- if (timedOut) {
81951
- throw new AgentProbeError("adapter_probe_timeout", "ACP agent probe timed out", { cause: error62 });
81952
- }
81953
- if (error62 instanceof AgentProbeError) {
81954
- throw error62;
81955
- }
81956
- if (error62 instanceof RequestError9 && error62.code === -32e3 && specification.authenticationCommand().length > 0) {
81957
- throw new AgentProbeError("authentication_required", "Agent authentication is required", {
81958
- cause: error62
81959
- });
81960
- }
81961
- throw new AgentProbeError("acp_incompatible", "ACP agent initialization failed", { cause: error62 });
81727
+ "The ACP endpoint stopped during initialization",
81728
+ controller.signal
81729
+ );
81962
81730
  } finally {
81963
- clearTimeout(timeout);
81964
- signal.removeEventListener("abort", abort);
81965
- }
81966
- }
81967
- const launch = executableLaunch2(agent.adapterPath, agent.arguments);
81968
- const child = spawn7(launch.command, [...launch.arguments], {
81969
- cwd: defaultWorkspace,
81970
- ...platformSpawnOptions,
81971
- env: { ...environment, ...agent.environment },
81972
- shell: false,
81973
- stdio: ["pipe", "pipe", "pipe"]
81974
- });
81975
- const processExit = new Promise((_resolve, reject2) => {
81976
- const rejectExit = () => reject2(new Error("ACP adapter exited during initialization"));
81977
- child.once("error", reject2);
81978
- child.once("exit", rejectExit);
81979
- if (child.exitCode !== null || child.signalCode !== null) {
81980
- rejectExit();
81981
- }
81982
- });
81983
- const stdin = child.stdin;
81984
- const stdout = child.stdout;
81985
- const stderr = child.stderr;
81986
- if (stdin === null || stdout === null || stderr === null) {
81987
- await stopProcessTree(child);
81988
- throw new AgentProbeError("acp_incompatible", "ACP adapter streams are unavailable");
81989
- }
81990
- let stderrBytes = 0;
81991
- const consumeStderr = (chunk) => {
81992
- stderrBytes += chunk.byteLength;
81993
- if (stderrBytes > ACP_OUTPUT_LIMIT_BYTES) {
81994
- controller.abort(new Error("ACP adapter output limit exceeded"));
81995
- }
81996
- };
81997
- stderr.on("data", consumeStderr);
81998
- const connection = createAcpClient(new DiscoveryAcpHandler()).connect(
81999
- ndJsonStream3(writableAcpStream(stdin), readableAcpStream(stdout))
82000
- );
82001
- try {
82002
- const initialized = await Promise.race([
82003
- connection.agent.request(
82004
- methods12.agent.initialize,
82005
- {
82006
- clientCapabilities: {},
82007
- clientInfo: { name: "mobius", version: "0.0.3" },
82008
- protocolVersion: PROTOCOL_VERSION3
82009
- },
82010
- { cancellationSignal: controller.signal }
82011
- ),
82012
- processExit
82013
- ]);
82014
- if (initialized.protocolVersion !== PROTOCOL_VERSION3) {
82015
- throw new AgentProbeError("acp_incompatible", "ACP adapter selected an unsupported protocol version");
81731
+ await runtime.closeProcess();
82016
81732
  }
82017
- await specification.verifyAcp(connection, initialized, defaultWorkspace, controller.signal);
82018
- return new VerifiedAcpReadiness(
82019
- normalizeVersionOutput(initialized.agentInfo?.version ?? ""),
82020
- normalizeAcpCapabilities(initialized)
82021
- );
82022
81733
  } catch (error62) {
82023
- if (signal.aborted) {
82024
- signal.throwIfAborted();
82025
- }
81734
+ signal.throwIfAborted();
82026
81735
  if (timedOut) {
82027
- throw new AgentProbeError("adapter_probe_timeout", "ACP adapter probe timed out", { cause: error62 });
81736
+ throw new AgentProbeError("adapter_probe_timeout", "ACP agent probe timed out", { cause: error62 });
82028
81737
  }
82029
81738
  if (error62 instanceof AgentProbeError) {
82030
81739
  throw error62;
82031
81740
  }
82032
- if (error62 instanceof RequestError9 && error62.code === -32e3 && specification.authenticationCommand().length > 0) {
81741
+ if (error62 instanceof AcpExecutionError && error62.code === "authentication_required" && specification.authenticationCommand().length > 0) {
82033
81742
  throw new AgentProbeError("authentication_required", "Agent authentication is required", { cause: error62 });
82034
81743
  }
82035
- throw new AgentProbeError("acp_incompatible", "ACP adapter initialization failed", { cause: error62 });
81744
+ throw new AgentProbeError("acp_incompatible", "ACP agent initialization failed", { cause: error62 });
82036
81745
  } finally {
82037
81746
  clearTimeout(timeout);
82038
81747
  signal.removeEventListener("abort", abort);
82039
- const capturedProcesses = await captureProcessTree(child);
82040
- connection.close();
82041
- stdin.end();
82042
- stderr.removeListener("data", consumeStderr);
82043
- await stopProcessTree(child, capturedProcesses);
82044
81748
  }
82045
81749
  }
82046
81750
 
@@ -82135,10 +81839,7 @@ async function resolveAgentExecutables(specification, context) {
82135
81839
  );
82136
81840
  }
82137
81841
  async function resolveAdapterExecutables(specification, context) {
82138
- if (specification instanceof DirectAcpAgentSpecification || specification instanceof InProcessAcpAgentSpecification) {
82139
- return await resolveAgentExecutables(specification, context);
82140
- }
82141
- throw new Error("Unsupported local Agent execution topology");
81842
+ return await resolveAgentExecutables(specification, context);
82142
81843
  }
82143
81844
  async function probeVersion(executable, arguments_, environment, defaultWorkspace, signal, timeoutMilliseconds, normalize4 = normalizeVersionOutput) {
82144
81845
  const result = await runBoundedProcess({
@@ -82252,7 +81953,7 @@ async function discoverAgent(specification, context) {
82252
81953
  return new MissingAdapter(specification);
82253
81954
  }
82254
81955
  for (const adapter of adapters) {
82255
- if (specification instanceof DirectAcpAgentSpecification && adapter.path !== agent.path) {
81956
+ if (adapter.path !== agent.path) {
82256
81957
  continue;
82257
81958
  }
82258
81959
  let adapterVersion = "";
@@ -82283,26 +81984,16 @@ async function discoverAgent(specification, context) {
82283
81984
  lastFailure = integrationProbeFailure(specification, error62);
82284
81985
  continue;
82285
81986
  }
82286
- const buildDefinition = (verifiedAdapterVersion, capabilities) => specification instanceof InProcessAcpAgentSpecification ? new InProcessAcpAgentDefinition(
81987
+ const buildDefinition = (verifiedAdapterVersion, capabilities) => new AcpAgentDefinition(
82287
81988
  specification.id,
82288
81989
  specification.label,
82289
81990
  agent.path,
82290
- specification.createEndpoint,
81991
+ specification.createConnection,
82291
81992
  launchEnvironment,
82292
81993
  agentVersion.length > 0 ? agentVersion : verifiedAdapterVersion,
82293
81994
  agent.identity,
82294
- capabilities
82295
- ) : new LocalAgentDefinition(
82296
- specification.id,
82297
- specification.label,
82298
- adapter.path,
82299
- specification.launchArguments,
82300
- launchEnvironment,
82301
- verifiedAdapterVersion,
82302
- agentVersion,
82303
- adapter.identity,
82304
- agent.identity,
82305
- capabilities
81995
+ capabilities,
81996
+ specification instanceof InProcessAcpAgentSpecification ? agentVersion : verifiedAdapterVersion
82306
81997
  );
82307
81998
  try {
82308
81999
  const readiness = await probeWithRetry(
@@ -82690,11 +82381,14 @@ function createCatalogAgentResolver(discover, readConfig, publish) {
82690
82381
  };
82691
82382
  }
82692
82383
  async function unchangedIdentity(agent, signal) {
82693
- if (!await revalidateExecutable(agent.agentIdentity)) {
82694
- return false;
82384
+ for (const identity2 of agent.runtimeExecutables) {
82385
+ signal.throwIfAborted();
82386
+ if (!await revalidateExecutable(identity2)) {
82387
+ return false;
82388
+ }
82695
82389
  }
82696
82390
  signal.throwIfAborted();
82697
- return agent.kind !== "acp-adapter-process" || await revalidateExecutable(agent.adapterIdentity);
82391
+ return true;
82698
82392
  }
82699
82393
 
82700
82394
  // src/runtime/connection/runtime-installation-store.ts
@@ -88982,7 +88676,7 @@ function settingsRevision(agent, reportedAgentVersion, settings, modelEffort) {
88982
88676
  };
88983
88677
  return createHash8("sha256").update(
88984
88678
  JSON.stringify({
88985
- adapterVersion: agent.kind === "acp-adapter-process" ? agent.adapterVersion : agent.agentVersion,
88679
+ adapterVersion: agent.adapterVersion,
88986
88680
  agentId: agent.id,
88987
88681
  agentVersion: agent.agentVersion,
88988
88682
  modelEffort: revisionModelEffort,
@@ -91738,8 +91432,8 @@ var MobiusRuntimeEngine = class {
91738
91432
  };
91739
91433
  };
91740
91434
  export {
91741
- InProcessAcpAgentDefinition,
91742
- LocalAgentDefinition,
91435
+ AcpAgentDefinition,
91436
+ EndpointAgentConnection,
91743
91437
  MobiusRuntimeConfigurationError,
91744
91438
  MobiusRuntimeEngine,
91745
91439
  OpaqueRuntimeReconnectTarget,