acpx 0.6.0 → 0.7.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.
Files changed (37) hide show
  1. package/README.md +1 -0
  2. package/dist/{cli-rGyZlX2p.js → cli-T-Z-9x6a.js} +4 -4
  3. package/dist/{cli-rGyZlX2p.js.map → cli-T-Z-9x6a.js.map} +1 -1
  4. package/dist/cli.js +64 -68
  5. package/dist/cli.js.map +1 -1
  6. package/dist/{client-2fTFutRH.d.ts → client-COPilhO_.d.ts} +4 -2
  7. package/dist/client-COPilhO_.d.ts.map +1 -0
  8. package/dist/{flags-DG-3Vfgg.js → flags-Dj-IXgo9.js} +5 -5
  9. package/dist/flags-Dj-IXgo9.js.map +1 -0
  10. package/dist/{flows-gbxyIf6o.js → flows-CF8w1rPI.js} +113 -10
  11. package/dist/flows-CF8w1rPI.js.map +1 -0
  12. package/dist/flows.d.ts +16 -1
  13. package/dist/flows.d.ts.map +1 -1
  14. package/dist/flows.js +2 -2
  15. package/dist/{ipc-CkAW8Qvc.js → ipc-ABXlXzGP.js} +53 -15
  16. package/dist/ipc-ABXlXzGP.js.map +1 -0
  17. package/dist/{perf-metrics-DvT_gvUh.js → perf-metrics-C2pXfxvR.js} +2 -2
  18. package/dist/perf-metrics-C2pXfxvR.js.map +1 -0
  19. package/dist/{prompt-turn-BOoZaDEq.js → prompt-turn-CVPMWdj1.js} +72 -49
  20. package/dist/prompt-turn-CVPMWdj1.js.map +1 -0
  21. package/dist/{render-CyodRDtK.js → render-N5YwotCy.js} +3 -3
  22. package/dist/{render-CyodRDtK.js.map → render-N5YwotCy.js.map} +1 -1
  23. package/dist/runtime.d.ts +5 -3
  24. package/dist/runtime.d.ts.map +1 -1
  25. package/dist/runtime.js +20 -12
  26. package/dist/runtime.js.map +1 -1
  27. package/dist/{session-DcIse8N0.js → session-CDaQe6BH.js} +77 -78
  28. package/dist/session-CDaQe6BH.js.map +1 -0
  29. package/package.json +11 -11
  30. package/skills/acpx/SKILL.md +3 -2
  31. package/dist/client-2fTFutRH.d.ts.map +0 -1
  32. package/dist/flags-DG-3Vfgg.js.map +0 -1
  33. package/dist/flows-gbxyIf6o.js.map +0 -1
  34. package/dist/ipc-CkAW8Qvc.js.map +0 -1
  35. package/dist/perf-metrics-DvT_gvUh.js.map +0 -1
  36. package/dist/prompt-turn-BOoZaDEq.js.map +0 -1
  37. package/dist/session-DcIse8N0.js.map +0 -1
@@ -1,4 +1,4 @@
1
- import { B as PermissionPromptUnavailableError, C as isAcpResourceNotFoundError, F as AuthPolicyError, G as SessionModelReplayError, I as ClaudeAcpSessionCreateTimeoutError, J as SessionResumeRequiredError, K as SessionNotFoundError, L as CopilotAcpUnsupportedError, M as AgentDisconnectedError, N as AgentSpawnError, P as AgentStartupError, R as GeminiAcpStartupTimeoutError, S as extractAcpError, U as SessionConfigOptionReplayError, W as SessionModeReplayError, g as textPrompt, i as measurePerf, j as SESSION_RECORD_SCHEMA, l as extractRuntimeSessionId, q as SessionResolutionError, r as incrementPerfCounter, u as normalizeRuntimeSessionId, v as formatErrorMessage, y as isAcpQueryClosedBeforeResponseError, z as PermissionDeniedError } from "./perf-metrics-DvT_gvUh.js";
1
+ import { B as PermissionDeniedError, C as isAcpResourceNotFoundError, F as AgentStartupError, G as SessionModeReplayError, I as AuthPolicyError, J as SessionResolutionError, K as SessionModelReplayError, L as ClaudeAcpSessionCreateTimeoutError, M as SESSION_RECORD_SCHEMA, N as AgentDisconnectedError, P as AgentSpawnError, R as CopilotAcpUnsupportedError, S as extractAcpError, V as PermissionPromptUnavailableError, W as SessionConfigOptionReplayError, Y as SessionResumeRequiredError, g as textPrompt, i as measurePerf, l as extractRuntimeSessionId, q as SessionNotFoundError, r as incrementPerfCounter, u as normalizeRuntimeSessionId, v as formatErrorMessage, y as isAcpQueryClosedBeforeResponseError, z as GeminiAcpStartupTimeoutError } from "./perf-metrics-C2pXfxvR.js";
2
2
  import { r as isSessionUpdateNotification } from "./jsonrpc-DSxh2w5R.js";
3
3
  import fs, { statSync } from "node:fs";
4
4
  import { fileURLToPath } from "node:url";
@@ -1290,9 +1290,10 @@ function isWsl(options) {
1290
1290
  if ((options.platform ?? process.platform) !== "linux") return false;
1291
1291
  return (options.existsSync ?? fs.existsSync)("/proc/sys/fs/binfmt_misc/WSLInterop");
1292
1292
  }
1293
+ const WINDOWS_EXECUTABLE_EXTENSION_RE = /\.(?:exe|cmd|bat)$/u;
1293
1294
  function isWindowsExecutableCommand(command) {
1294
- const normalized = command.replace(/\\/g, "/").toLowerCase();
1295
- return normalized.endsWith(".exe") || normalized.startsWith("/mnt/c/");
1295
+ const normalized = command.toLowerCase();
1296
+ return WINDOWS_EXECUTABLE_EXTENSION_RE.test(normalized);
1296
1297
  }
1297
1298
  async function runWslpath(cwd) {
1298
1299
  const { stdout } = await execFileAsync("wslpath", ["-w", cwd], { encoding: "utf8" });
@@ -1399,46 +1400,8 @@ function compareVersionParts(left, right) {
1399
1400
  return 0;
1400
1401
  }
1401
1402
  async function detectGeminiVersion(command) {
1402
- return await new Promise((resolve) => {
1403
- const child = spawn(command, ["--version"], buildSpawnCommandOptions(command, {
1404
- stdio: [
1405
- "ignore",
1406
- "pipe",
1407
- "pipe"
1408
- ],
1409
- windowsHide: true
1410
- }));
1411
- let stdout = "";
1412
- let stderr = "";
1413
- let settled = false;
1414
- const finish = (value) => {
1415
- if (settled) return;
1416
- settled = true;
1417
- clearTimeout(timer);
1418
- child.removeAllListeners();
1419
- child.stdout?.removeAllListeners();
1420
- child.stderr?.removeAllListeners();
1421
- resolve(value);
1422
- };
1423
- const timer = setTimeout(() => {
1424
- child.kill("SIGKILL");
1425
- finish(void 0);
1426
- }, GEMINI_VERSION_TIMEOUT_MS);
1427
- child.stdout?.setEncoding("utf8");
1428
- child.stderr?.setEncoding("utf8");
1429
- child.stdout?.on("data", (chunk) => {
1430
- stdout += chunk;
1431
- });
1432
- child.stderr?.on("data", (chunk) => {
1433
- stderr += chunk;
1434
- });
1435
- child.once("error", () => {
1436
- finish(void 0);
1437
- });
1438
- child.once("close", () => {
1439
- finish(parseGeminiVersion(`${stdout}\n${stderr}`.split(/\r?\n/).map((line) => line.trim()).find((line) => /\d+\.\d+\.\d+/.test(line))));
1440
- });
1441
- });
1403
+ const versionLine = (await readCommandOutput(command, ["--version"], GEMINI_VERSION_TIMEOUT_MS))?.split(/\r?\n/).map((line) => line.trim()).find((line) => /\d+\.\d+\.\d+/.test(line));
1404
+ return parseGeminiVersion(versionLine);
1442
1405
  }
1443
1406
  async function resolveGeminiCommandArgs(command, args) {
1444
1407
  if (basenameToken(command) !== "gemini" || !args.includes("--acp")) return [...args];
@@ -1528,6 +1491,13 @@ function buildClaudeCodeOptionsMeta(options) {
1528
1491
  if (Object.keys(meta).length === 0) return;
1529
1492
  return meta;
1530
1493
  }
1494
+ function resolveClaudeCodeExecutable(platform = process.platform, env = process.env) {
1495
+ if (platform !== "win32") return;
1496
+ if (readWindowsEnvValue(env, "CLAUDE_CODE_EXECUTABLE")) return;
1497
+ const resolved = resolveWindowsCommand("claude", env);
1498
+ if (!resolved) return;
1499
+ return path.resolve(resolved);
1500
+ }
1531
1501
  //#endregion
1532
1502
  //#region src/acp/auth-env.ts
1533
1503
  const AUTH_ENV_PREFIX = "ACPX_AUTH_";
@@ -2102,7 +2072,15 @@ var AcpClient = class {
2102
2072
  else this.log(`spawning agent: ${spawnCommand} ${args.join(" ")}`);
2103
2073
  const geminiAcp = isGeminiAcpCommand(spawnCommand, args);
2104
2074
  if (isCopilotAcpCommand(spawnCommand, args)) await ensureCopilotAcpSupport(spawnCommand);
2105
- const spawnedChild = spawn(spawnCommand, args, buildSpawnCommandOptions(spawnCommand, buildAgentSpawnOptions(this.options.cwd, this.options.authCredentials)));
2075
+ const agentSpawnOptions = buildAgentSpawnOptions(this.options.cwd, this.options.authCredentials);
2076
+ if (isClaudeAcpCommand(spawnCommand, args)) {
2077
+ const claudeExe = resolveClaudeCodeExecutable(process.platform, agentSpawnOptions.env);
2078
+ if (claudeExe) {
2079
+ agentSpawnOptions.env.CLAUDE_CODE_EXECUTABLE = claudeExe;
2080
+ this.log(`resolved system Claude Code executable: ${claudeExe}`);
2081
+ }
2082
+ }
2083
+ const spawnedChild = spawn(spawnCommand, args, buildSpawnCommandOptions(spawnCommand, agentSpawnOptions));
2106
2084
  try {
2107
2085
  await waitForSpawn$1(spawnedChild);
2108
2086
  } catch (error) {
@@ -2254,6 +2232,7 @@ var AcpClient = class {
2254
2232
  return {
2255
2233
  sessionId: result.sessionId,
2256
2234
  agentSessionId: extractRuntimeSessionId(result._meta),
2235
+ configOptions: result.configOptions ?? void 0,
2257
2236
  models: result.models ?? void 0
2258
2237
  };
2259
2238
  }
@@ -2283,6 +2262,7 @@ var AcpClient = class {
2283
2262
  this.loadedSessionId = sessionId;
2284
2263
  return {
2285
2264
  agentSessionId: extractRuntimeSessionId(response?._meta),
2265
+ configOptions: response?.configOptions ?? void 0,
2286
2266
  models: response?.models ?? void 0
2287
2267
  };
2288
2268
  }
@@ -2365,7 +2345,7 @@ var AcpClient = class {
2365
2345
  }
2366
2346
  async closeSession(sessionId) {
2367
2347
  const connection = this.getConnection();
2368
- await this.runConnectionRequest(() => connection.unstable_closeNes({ sessionId }));
2348
+ await this.runConnectionRequest(() => connection.closeSession({ sessionId }));
2369
2349
  if (this.loadedSessionId === sessionId) this.loadedSessionId = void 0;
2370
2350
  }
2371
2351
  async requestCancelActivePrompt() {
@@ -3099,6 +3079,15 @@ function trimConversationForRuntime(conversation) {
3099
3079
  if (requestUsageEntries.length > MAX_RUNTIME_REQUEST_TOKEN_USAGE) conversation.request_token_usage = Object.fromEntries(requestUsageEntries.slice(-MAX_RUNTIME_REQUEST_TOKEN_USAGE));
3100
3080
  }
3101
3081
  //#endregion
3082
+ //#region src/session/config-options.ts
3083
+ function applyConfigOptionsToRecord(record, result) {
3084
+ const configOptions = result?.configOptions;
3085
+ if (!configOptions) return;
3086
+ const acpxState = cloneSessionAcpxState(record.acpx) ?? {};
3087
+ acpxState.config_options = structuredClone(configOptions);
3088
+ record.acpx = acpxState;
3089
+ }
3090
+ //#endregion
3102
3091
  //#region src/session/mode-preference.ts
3103
3092
  function ensureAcpxState(state) {
3104
3093
  return state ?? {};
@@ -3170,6 +3159,30 @@ function syncAdvertisedModelState(record, models) {
3170
3159
  record.acpx = acpx;
3171
3160
  }
3172
3161
  //#endregion
3162
+ //#region src/acp/model-support.ts
3163
+ var RequestedModelUnsupportedError = class extends Error {
3164
+ constructor(message) {
3165
+ super(message);
3166
+ this.name = "RequestedModelUnsupportedError";
3167
+ }
3168
+ };
3169
+ function supportsLegacyClaudeCodeModelMetadata(agentCommand) {
3170
+ if (!agentCommand) return false;
3171
+ const { command, args } = splitCommandLine(agentCommand);
3172
+ return isClaudeAcpCommand(command, args);
3173
+ }
3174
+ function formatAvailableModelIds(models) {
3175
+ const ids = models?.availableModels.map((model) => model.modelId.trim()).filter((modelId) => modelId.length > 0) ?? [];
3176
+ return ids.length > 0 ? ids.join(", ") : "none advertised";
3177
+ }
3178
+ function assertRequestedModelSupported(params) {
3179
+ if (!params.models) {
3180
+ if (supportsLegacyClaudeCodeModelMetadata(params.agentCommand)) return;
3181
+ throw new RequestedModelUnsupportedError(`Cannot ${params.context === "replay" ? "replay saved model" : "apply --model"} "${params.requestedModel}": the ACP agent did not advertise model support. Generic model selection requires ACP models plus session/set_model support, or an adapter-specific startup model flag.`);
3182
+ }
3183
+ if (!new Set(params.models.availableModels.map((model) => model.modelId)).has(params.requestedModel)) throw new RequestedModelUnsupportedError(`Cannot ${params.context === "replay" ? "replay saved model" : "apply --model"} "${params.requestedModel}": the ACP agent did not advertise that model. Available models: ${formatAvailableModelIds(params.models)}.`);
3184
+ }
3185
+ //#endregion
3173
3186
  //#region src/runtime/engine/lifecycle.ts
3174
3187
  function applyLifecycleSnapshotToRecord(record, snapshot) {
3175
3188
  if (!snapshot) return;
@@ -3244,9 +3257,15 @@ async function replayDesiredMode(params) {
3244
3257
  }
3245
3258
  }
3246
3259
  async function replayDesiredModel(params) {
3247
- if (!params.desiredModelId || !params.models) return;
3248
- if (params.models.currentModelId === params.desiredModelId) return;
3260
+ if (!params.desiredModelId) return;
3249
3261
  try {
3262
+ assertRequestedModelSupported({
3263
+ requestedModel: params.desiredModelId,
3264
+ models: params.models,
3265
+ agentCommand: params.record.agentCommand,
3266
+ context: "replay"
3267
+ });
3268
+ if (!params.models || params.models.currentModelId === params.desiredModelId) return;
3250
3269
  await withTimeout(params.client.setSessionModel(params.sessionId, params.desiredModelId), params.timeoutMs);
3251
3270
  if (params.verbose) process.stderr.write(`[acpx] replayed desired model ${params.desiredModelId} on fresh ACP session ${params.sessionId} (previous ${params.previousSessionId})\n`);
3252
3271
  } catch (error) {
@@ -3304,6 +3323,7 @@ async function connectAndLoadSession(options) {
3304
3323
  else if (client.supportsLoadSession()) try {
3305
3324
  const loadResult = await withTimeout(client.loadSessionWithOptions(record.acpSessionId, record.cwd, { suppressReplayUpdates: true }), options.timeoutMs);
3306
3325
  reconcileAgentSessionId(record, loadResult.agentSessionId);
3326
+ applyConfigOptionsToRecord(record, loadResult);
3307
3327
  sessionModels = loadResult.models;
3308
3328
  resumed = true;
3309
3329
  } catch (error) {
@@ -3318,6 +3338,7 @@ async function connectAndLoadSession(options) {
3318
3338
  sessionId = createdSession.sessionId;
3319
3339
  createdFreshSession = true;
3320
3340
  pendingAgentSessionId = createdSession.agentSessionId;
3341
+ applyConfigOptionsToRecord(record, createdSession);
3321
3342
  sessionModels = createdSession.models;
3322
3343
  }
3323
3344
  else {
@@ -3329,6 +3350,7 @@ async function connectAndLoadSession(options) {
3329
3350
  sessionId = createdSession.sessionId;
3330
3351
  createdFreshSession = true;
3331
3352
  pendingAgentSessionId = createdSession.agentSessionId;
3353
+ applyConfigOptionsToRecord(record, createdSession);
3332
3354
  sessionModels = createdSession.models;
3333
3355
  }
3334
3356
  if (createdFreshSession) {
@@ -3346,6 +3368,7 @@ async function connectAndLoadSession(options) {
3346
3368
  sessionId,
3347
3369
  desiredModelId,
3348
3370
  previousSessionId: originalSessionId,
3371
+ record,
3349
3372
  models: sessionModels,
3350
3373
  timeoutMs: options.timeoutMs,
3351
3374
  verbose: options.verbose
@@ -3539,6 +3562,6 @@ async function runPromptTurn(params) {
3539
3562
  }
3540
3563
  }
3541
3564
  //#endregion
3542
- export { listSessionsForAgent as A, sessionEventLockPath as B, DEFAULT_HISTORY_LIMIT as C, findSessionByDirectoryWalk as D, findSession as E, parseSessionRecord as F, TimeoutError as G, assertPersistedKeyPolicy as H, DEFAULT_EVENT_SEGMENT_MAX_BYTES as I, DEFAULT_AGENT_NAME as J, withInterrupt as K, defaultSessionEventLog as L, pruneSessions as M, resolveSessionRecord as N, isoNow$2 as O, writeSessionRecord as P, sessionBaseDir$1 as R, permissionModeSatisfies as S, findGitRepositoryRoot as T, serializeSessionRecordForDisk as U, sessionEventSegmentPath as V, InterruptedError as W, normalizeAgentName$1 as X, listBuiltInAgents as Y, resolveAgentCommand as Z, recordClientOperation as _, connectAndLoadSession as a, trimConversationForRuntime as b, reconcileAgentSessionId as c, setDesiredModeId as d, setDesiredModelId as f, createSessionConversation as g, cloneSessionConversation as h, sessionOptionsFromRecord as i, normalizeName as j, listSessions as k, setCurrentModelId as l, cloneSessionAcpxState as m, withConnectedSession as n, applyConversation as o, syncAdvertisedModelState as p, withTimeout as q, mergeSessionOptions as r, applyLifecycleSnapshotToRecord as s, runPromptTurn as t, setDesiredConfigOption as u, recordPromptSubmission as v, absolutePath as w, AcpClient as x, recordSessionUpdate as y, sessionEventActivePath as z };
3565
+ export { resolveAgentCommand as $, isoNow$2 as A, sessionBaseDir$1 as B, AcpClient as C, findGitRepositoryRoot as D, absolutePath as E, resolveSessionRecord as F, serializeSessionRecordForDisk as G, sessionEventLockPath as H, writeSessionRecord as I, withInterrupt as J, InterruptedError as K, parseSessionRecord as L, listSessionsForAgent as M, normalizeName as N, findSession as O, pruneSessions as P, normalizeAgentName$1 as Q, DEFAULT_EVENT_SEGMENT_MAX_BYTES as R, trimConversationForRuntime as S, DEFAULT_HISTORY_LIMIT as T, sessionEventSegmentPath as U, sessionEventActivePath as V, assertPersistedKeyPolicy as W, DEFAULT_AGENT_NAME as X, withTimeout as Y, listBuiltInAgents as Z, cloneSessionConversation as _, connectAndLoadSession as a, recordPromptSubmission as b, reconcileAgentSessionId as c, setDesiredConfigOption as d, setDesiredModeId as f, cloneSessionAcpxState as g, applyConfigOptionsToRecord as h, sessionOptionsFromRecord as i, listSessions as j, findSessionByDirectoryWalk as k, assertRequestedModelSupported as l, syncAdvertisedModelState as m, withConnectedSession as n, applyConversation as o, setDesiredModelId as p, TimeoutError as q, mergeSessionOptions as r, applyLifecycleSnapshotToRecord as s, runPromptTurn as t, setCurrentModelId as u, createSessionConversation as v, permissionModeSatisfies as w, recordSessionUpdate as x, recordClientOperation as y, defaultSessionEventLog as z };
3543
3566
 
3544
- //# sourceMappingURL=prompt-turn-BOoZaDEq.js.map
3567
+ //# sourceMappingURL=prompt-turn-CVPMWdj1.js.map