acpx 0.1.14 → 0.1.15

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 (2) hide show
  1. package/dist/cli.js +154 -37
  2. package/package.json +1 -1
package/dist/cli.js CHANGED
@@ -7,7 +7,7 @@ import { pathToFileURL } from "url";
7
7
  // src/cli-core.ts
8
8
  import { Command, CommanderError, InvalidArgumentError as InvalidArgumentError2 } from "commander";
9
9
  import fs7 from "fs/promises";
10
- import path10 from "path";
10
+ import path11 from "path";
11
11
  import { findSkillsRoot, maybeHandleSkillflag } from "skillflag";
12
12
 
13
13
  // src/agent-registry.ts
@@ -908,6 +908,9 @@ var TerminalManager = class {
908
908
  var REPLAY_IDLE_MS = 80;
909
909
  var REPLAY_DRAIN_TIMEOUT_MS = 5e3;
910
910
  var DRAIN_POLL_INTERVAL_MS = 20;
911
+ var AGENT_CLOSE_AFTER_STDIN_END_MS = 100;
912
+ var AGENT_CLOSE_TERM_GRACE_MS = 1500;
913
+ var AGENT_CLOSE_KILL_GRACE_MS = 1e3;
911
914
  function shouldSuppressSdkConsoleError(args) {
912
915
  if (args.length === 0) {
913
916
  return false;
@@ -943,6 +946,38 @@ function waitForSpawn2(child) {
943
946
  child.once("error", onError);
944
947
  });
945
948
  }
949
+ function isChildProcessRunning(child) {
950
+ return child.exitCode == null && child.signalCode == null;
951
+ }
952
+ function waitForChildExit(child, timeoutMs) {
953
+ if (!isChildProcessRunning(child)) {
954
+ return Promise.resolve(true);
955
+ }
956
+ return new Promise((resolve) => {
957
+ let settled = false;
958
+ const timer = setTimeout(
959
+ () => {
960
+ finish(false);
961
+ },
962
+ Math.max(0, timeoutMs)
963
+ );
964
+ const finish = (value) => {
965
+ if (settled) {
966
+ return;
967
+ }
968
+ settled = true;
969
+ child.off("close", onExitLike);
970
+ child.off("exit", onExitLike);
971
+ clearTimeout(timer);
972
+ resolve(value);
973
+ };
974
+ const onExitLike = () => {
975
+ finish(true);
976
+ };
977
+ child.once("close", onExitLike);
978
+ child.once("exit", onExitLike);
979
+ });
980
+ }
946
981
  function splitCommandLine(value) {
947
982
  const parts = [];
948
983
  let current = "";
@@ -1417,10 +1452,7 @@ var AcpClient = class {
1417
1452
  await this.terminalManager.shutdown();
1418
1453
  const agent = this.agent;
1419
1454
  if (agent) {
1420
- if (!agent.killed) {
1421
- agent.kill();
1422
- }
1423
- this.detachAgentHandles(agent);
1455
+ await this.terminateAgentProcess(agent);
1424
1456
  }
1425
1457
  this.sessionUpdateChain = Promise.resolve();
1426
1458
  this.observedSessionUpdates = 0;
@@ -1433,16 +1465,45 @@ var AcpClient = class {
1433
1465
  this.connection = void 0;
1434
1466
  this.agent = void 0;
1435
1467
  }
1436
- detachAgentHandles(agent) {
1468
+ async terminateAgentProcess(child) {
1469
+ if (!child.stdin.destroyed) {
1470
+ try {
1471
+ child.stdin.end();
1472
+ } catch {
1473
+ }
1474
+ }
1475
+ let exited = await waitForChildExit(child, AGENT_CLOSE_AFTER_STDIN_END_MS);
1476
+ if (!exited && isChildProcessRunning(child)) {
1477
+ try {
1478
+ child.kill("SIGTERM");
1479
+ } catch {
1480
+ }
1481
+ exited = await waitForChildExit(child, AGENT_CLOSE_TERM_GRACE_MS);
1482
+ }
1483
+ if (!exited && isChildProcessRunning(child)) {
1484
+ this.log(
1485
+ `agent did not exit after ${AGENT_CLOSE_TERM_GRACE_MS}ms; forcing SIGKILL`
1486
+ );
1487
+ try {
1488
+ child.kill("SIGKILL");
1489
+ } catch {
1490
+ }
1491
+ exited = await waitForChildExit(child, AGENT_CLOSE_KILL_GRACE_MS);
1492
+ }
1493
+ this.detachAgentHandles(child, !exited);
1494
+ }
1495
+ detachAgentHandles(agent, unref) {
1437
1496
  const stdin = agent.stdin;
1438
1497
  const stdout = agent.stdout;
1439
1498
  const stderr = agent.stderr;
1440
1499
  stdin?.destroy();
1441
1500
  stdout?.destroy();
1442
1501
  stderr?.destroy();
1443
- try {
1444
- agent.unref();
1445
- } catch {
1502
+ if (unref) {
1503
+ try {
1504
+ agent.unref();
1505
+ } catch {
1506
+ }
1446
1507
  }
1447
1508
  }
1448
1509
  getConnection() {
@@ -2418,48 +2479,48 @@ var OPAQUE_VALUE_PATHS = /* @__PURE__ */ new Set([
2418
2479
  function isRecord(value) {
2419
2480
  return !!value && typeof value === "object" && !Array.isArray(value);
2420
2481
  }
2421
- function joinPath(path11) {
2422
- return path11.join(".");
2482
+ function joinPath(path12) {
2483
+ return path12.join(".");
2423
2484
  }
2424
- function isAllowedKey(path11, key) {
2485
+ function isAllowedKey(path12, key) {
2425
2486
  if (ZED_TAG_KEYS.has(key)) {
2426
2487
  return true;
2427
2488
  }
2428
2489
  return false;
2429
2490
  }
2430
- function shouldSkipKeyRule(path11) {
2431
- return MAP_OBJECT_PATHS.has(joinPath(path11));
2491
+ function shouldSkipKeyRule(path12) {
2492
+ return MAP_OBJECT_PATHS.has(joinPath(path12));
2432
2493
  }
2433
- function shouldSkipDescend(path11) {
2434
- return OPAQUE_VALUE_PATHS.has(joinPath(path11)) || isToolResultOutputPath(path11);
2494
+ function shouldSkipDescend(path12) {
2495
+ return OPAQUE_VALUE_PATHS.has(joinPath(path12)) || isToolResultOutputPath(path12);
2435
2496
  }
2436
- function isToolResultOutputPath(path11) {
2437
- if (path11.length < 5 || path11[path11.length - 1] !== "output") {
2497
+ function isToolResultOutputPath(path12) {
2498
+ if (path12.length < 5 || path12[path12.length - 1] !== "output") {
2438
2499
  return false;
2439
2500
  }
2440
- const toolResultsIndex = path11.lastIndexOf("tool_results");
2441
- if (toolResultsIndex === -1 || toolResultsIndex + 2 !== path11.length - 1) {
2501
+ const toolResultsIndex = path12.lastIndexOf("tool_results");
2502
+ if (toolResultsIndex === -1 || toolResultsIndex + 2 !== path12.length - 1) {
2442
2503
  return false;
2443
2504
  }
2444
- const parentPath = path11.slice(0, toolResultsIndex + 1).join(".");
2505
+ const parentPath = path12.slice(0, toolResultsIndex + 1).join(".");
2445
2506
  return parentPath === "messages.Agent.tool_results";
2446
2507
  }
2447
- function collectViolations(value, path11, violations) {
2508
+ function collectViolations(value, path12, violations) {
2448
2509
  if (Array.isArray(value)) {
2449
2510
  for (const entry of value) {
2450
- collectViolations(entry, path11, violations);
2511
+ collectViolations(entry, path12, violations);
2451
2512
  }
2452
2513
  return;
2453
2514
  }
2454
2515
  if (!isRecord(value)) {
2455
2516
  return;
2456
2517
  }
2457
- const skipKeyRule = shouldSkipKeyRule(path11);
2518
+ const skipKeyRule = shouldSkipKeyRule(path12);
2458
2519
  for (const [key, child] of Object.entries(value)) {
2459
- if (!skipKeyRule && !SNAKE_CASE_KEY.test(key) && !isAllowedKey(path11, key)) {
2460
- violations.push(`${joinPath(path11)}.${key}`.replace(/^\./, ""));
2520
+ if (!skipKeyRule && !SNAKE_CASE_KEY.test(key) && !isAllowedKey(path12, key)) {
2521
+ violations.push(`${joinPath(path12)}.${key}`.replace(/^\./, ""));
2461
2522
  }
2462
- const childPath = [...path11, key];
2523
+ const childPath = [...path12, key];
2463
2524
  if (shouldSkipDescend(childPath)) {
2464
2525
  continue;
2465
2526
  }
@@ -6587,12 +6648,12 @@ function formatLocations(locations) {
6587
6648
  }
6588
6649
  const unique = /* @__PURE__ */ new Set();
6589
6650
  for (const location of locations) {
6590
- const path11 = location.path?.trim();
6591
- if (!path11) {
6651
+ const path12 = location.path?.trim();
6652
+ if (!path12) {
6592
6653
  continue;
6593
6654
  }
6594
6655
  const line = typeof location.line === "number" && Number.isFinite(location.line) ? `:${Math.max(1, Math.trunc(location.line))}` : "";
6595
- unique.add(`${path11}${line}`);
6656
+ unique.add(`${path12}${line}`);
6596
6657
  }
6597
6658
  const items = [...unique];
6598
6659
  if (items.length === 0) {
@@ -6605,15 +6666,15 @@ function formatLocations(locations) {
6605
6666
  }
6606
6667
  return `${visible.join(", ")}, +${hidden} more`;
6607
6668
  }
6608
- function summarizeDiff(path11, oldText, newText) {
6669
+ function summarizeDiff(path12, oldText, newText) {
6609
6670
  const oldLines = oldText ? oldText.split("\n").length : 0;
6610
6671
  const newLines = newText.split("\n").length;
6611
6672
  const delta = newLines - oldLines;
6612
6673
  if (delta === 0) {
6613
- return `diff ${path11} (line count unchanged)`;
6674
+ return `diff ${path12} (line count unchanged)`;
6614
6675
  }
6615
6676
  const signedDelta = `${delta > 0 ? "+" : ""}${delta}`;
6616
- return `diff ${path11} (${signedDelta} lines)`;
6677
+ return `diff ${path12} (${signedDelta} lines)`;
6617
6678
  }
6618
6679
  function textFromContentBlock(content) {
6619
6680
  switch (content.type) {
@@ -7069,6 +7130,62 @@ function createOutputFormatter(format, options = {}) {
7069
7130
  }
7070
7131
  }
7071
7132
 
7133
+ // src/version.ts
7134
+ import { readFileSync } from "fs";
7135
+ import path10 from "path";
7136
+ import { fileURLToPath } from "url";
7137
+ var UNKNOWN_VERSION = "0.0.0-unknown";
7138
+ var MODULE_DIR = path10.dirname(fileURLToPath(import.meta.url));
7139
+ var cachedVersion = null;
7140
+ function parseVersion(value) {
7141
+ if (typeof value !== "string") {
7142
+ return null;
7143
+ }
7144
+ const trimmed = value.trim();
7145
+ return trimmed.length > 0 ? trimmed : null;
7146
+ }
7147
+ function readPackageVersion(packageJsonPath) {
7148
+ try {
7149
+ const parsed = JSON.parse(readFileSync(packageJsonPath, "utf8"));
7150
+ return parseVersion(parsed.version);
7151
+ } catch {
7152
+ return null;
7153
+ }
7154
+ }
7155
+ function resolveVersionFromAncestors(startDir) {
7156
+ let current = startDir;
7157
+ while (true) {
7158
+ const packageVersion = readPackageVersion(path10.join(current, "package.json"));
7159
+ if (packageVersion) {
7160
+ return packageVersion;
7161
+ }
7162
+ const parent = path10.dirname(current);
7163
+ if (parent === current) {
7164
+ return null;
7165
+ }
7166
+ current = parent;
7167
+ }
7168
+ }
7169
+ function resolveAcpxVersion(params) {
7170
+ const env = params?.env ?? process.env;
7171
+ const envPackageName = parseVersion(env.npm_package_name);
7172
+ const envVersion = parseVersion(env.npm_package_version);
7173
+ if (envPackageName === "acpx" && envVersion) {
7174
+ return envVersion;
7175
+ }
7176
+ if (params?.packageJsonPath) {
7177
+ return readPackageVersion(params.packageJsonPath) ?? UNKNOWN_VERSION;
7178
+ }
7179
+ return resolveVersionFromAncestors(MODULE_DIR) ?? UNKNOWN_VERSION;
7180
+ }
7181
+ function getAcpxVersion() {
7182
+ if (cachedVersion) {
7183
+ return cachedVersion;
7184
+ }
7185
+ cachedVersion = resolveAcpxVersion();
7186
+ return cachedVersion;
7187
+ }
7188
+
7072
7189
  // src/queue-owner-env.ts
7073
7190
  function asRecord7(value) {
7074
7191
  if (!value || typeof value !== "object" || Array.isArray(value)) {
@@ -7151,7 +7268,7 @@ async function readPromptInputFromStdin() {
7151
7268
  }
7152
7269
  async function readPrompt(promptParts, filePath, cwd) {
7153
7270
  if (filePath) {
7154
- const source = filePath === "-" ? await readPromptInputFromStdin() : await fs7.readFile(path10.resolve(cwd, filePath), "utf8");
7271
+ const source = filePath === "-" ? await readPromptInputFromStdin() : await fs7.readFile(path11.resolve(cwd, filePath), "utf8");
7155
7272
  const pieces = [source.trim(), promptParts.join(" ").trim()].filter(
7156
7273
  (value) => value.length > 0
7157
7274
  );
@@ -7994,14 +8111,14 @@ function detectInitialCwd(argv) {
7994
8111
  if (token === "--cwd") {
7995
8112
  const next = argv[index + 1];
7996
8113
  if (next && next !== "--") {
7997
- return path10.resolve(next);
8114
+ return path11.resolve(next);
7998
8115
  }
7999
8116
  break;
8000
8117
  }
8001
8118
  if (token.startsWith("--cwd=")) {
8002
8119
  const value = token.slice("--cwd=".length).trim();
8003
8120
  if (value.length > 0) {
8004
- return path10.resolve(value);
8121
+ return path11.resolve(value);
8005
8122
  }
8006
8123
  break;
8007
8124
  }
@@ -8109,7 +8226,7 @@ async function main(argv = process.argv) {
8109
8226
  );
8110
8227
  const builtInAgents = listBuiltInAgents(config.agents);
8111
8228
  const program = new Command();
8112
- program.name("acpx").description("Headless CLI client for the Agent Client Protocol").enablePositionalOptions().showHelpAfterError();
8229
+ program.name("acpx").description("Headless CLI client for the Agent Client Protocol").version(getAcpxVersion()).enablePositionalOptions().showHelpAfterError();
8113
8230
  if (requestedJsonStrict) {
8114
8231
  program.configureOutput({
8115
8232
  writeOut: () => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "acpx",
3
- "version": "0.1.14",
3
+ "version": "0.1.15",
4
4
  "description": "Headless CLI client for the Agent Client Protocol (ACP) — talk to coding agents from the command line",
5
5
  "type": "module",
6
6
  "files": [