@ganglion/xacpx 0.17.0-beta.5 → 0.17.0-beta.7

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/README.md CHANGED
@@ -29,7 +29,7 @@ If you need to code or work remotely on a temporary basis, `xacpx` gives you a f
29
29
 
30
30
  ### Prerequisites
31
31
 
32
- - Node.js 22+ or Bun
32
+ - Node.js 22.12+ or Bun
33
33
  - A working agent CLI you intend to use, such as Codex / Claude Code / Gemini / OpenCode
34
34
  - A phone with WeChat, Feishu, or Yuanbao installed
35
35
 
@@ -182,7 +182,7 @@ xacpx-relay add token # prints the access token once
182
182
  xacpx-relay start # defaults: --host 0.0.0.0 --http-port 8787
183
183
 
184
184
  # On each instance host:
185
- xacpx plugin add @ganglion/xacpx-channel-relay # requires xacpx >= 0.11.0
185
+ xacpx plugin add @ganglion/xacpx-channel-relay # requires xacpx >= 0.17.0-beta.6
186
186
  xacpx channel add relay --url wss://relay.example.com --token <access-token> --name my-box
187
187
  xacpx restart
188
188
  ```
@@ -3687,7 +3687,43 @@ async function deleteAcpxSessionFiles(options) {
3687
3687
  var init_acpx_session_files = () => {};
3688
3688
 
3689
3689
  // src/transport/command-timeouts.ts
3690
- var DEFAULT_MANAGEMENT_COMMAND_TIMEOUT_MS = 30000, DEFAULT_SESSION_INIT_TIMEOUT_MS = 120000, BRIDGE_REQUEST_TIMEOUT_GRACE_MS = 15000;
3690
+ function formatTimeout(timeoutMs) {
3691
+ return timeoutMs >= 1000 ? `${timeoutMs / 1000}s` : `${timeoutMs}ms`;
3692
+ }
3693
+ function captureOutputTail(value) {
3694
+ const normalized = value?.trim();
3695
+ if (!normalized)
3696
+ return;
3697
+ return normalized.slice(-COMMAND_OUTPUT_TAIL_CHARS);
3698
+ }
3699
+ function isCommandTimeoutError(error) {
3700
+ return error instanceof CommandTimeoutError;
3701
+ }
3702
+ var DEFAULT_MANAGEMENT_COMMAND_TIMEOUT_MS = 30000, DEFAULT_SESSION_INIT_TIMEOUT_MS = 120000, BRIDGE_REQUEST_TIMEOUT_GRACE_MS = 15000, COMMAND_OUTPUT_TAIL_CHARS = 2000, CommandTimeoutError;
3703
+ var init_command_timeouts = __esm(() => {
3704
+ CommandTimeoutError = class CommandTimeoutError extends Error {
3705
+ timeoutMs;
3706
+ command;
3707
+ stage;
3708
+ stdoutTail;
3709
+ stderrTail;
3710
+ constructor(timeoutMs, command, detail = {}) {
3711
+ const stdoutTail = captureOutputTail(detail.stdout);
3712
+ const stderrTail = captureOutputTail(detail.stderr);
3713
+ const output = [
3714
+ stdoutTail ? `stdout tail: ${stdoutTail}` : "",
3715
+ stderrTail ? `stderr tail: ${stderrTail}` : ""
3716
+ ].filter(Boolean).join("; ");
3717
+ super(`acpx command timed out${detail.stage ? ` during ${detail.stage}` : ""} after ${formatTimeout(timeoutMs)}: ${command}` + (output ? `; ${output}` : ""));
3718
+ this.timeoutMs = timeoutMs;
3719
+ this.command = command;
3720
+ this.name = "CommandTimeoutError";
3721
+ this.stage = detail.stage;
3722
+ this.stdoutTail = stdoutTail;
3723
+ this.stderrTail = stderrTail;
3724
+ }
3725
+ };
3726
+ });
3691
3727
 
3692
3728
  // src/transport/permission-mode-flag.ts
3693
3729
  function permissionModeToFlag(permissionMode) {
@@ -3873,6 +3909,8 @@ init_acpx_queue_owner_launcher();
3873
3909
  init_agent_session_list();
3874
3910
  init_codex_subagent_filter();
3875
3911
  init_acpx_session_files();
3912
+ init_command_timeouts();
3913
+ init_command_timeouts();
3876
3914
  init_acpx_command_builder();
3877
3915
  class EnsureSessionFailedError extends Error {
3878
3916
  kind;
@@ -3885,15 +3923,6 @@ class EnsureSessionFailedError extends Error {
3885
3923
  }
3886
3924
  }
3887
3925
 
3888
- class CommandTimeoutError extends Error {
3889
- timeoutMs;
3890
- constructor(timeoutMs, command) {
3891
- super(`acpx command timed out after ${timeoutMs / 1000}s: ${command}`);
3892
- this.timeoutMs = timeoutMs;
3893
- this.name = "CommandTimeoutError";
3894
- }
3895
- }
3896
-
3897
3926
  class BridgeRuntime {
3898
3927
  command;
3899
3928
  run;
@@ -3976,12 +4005,14 @@ class BridgeRuntime {
3976
4005
  input.name
3977
4006
  ]));
3978
4007
  const result = await this.run(spawnSpec.command, spawnSpec.args, {
3979
- timeoutMs: this.managementCommandTimeoutMs()
4008
+ timeoutMs: this.managementCommandTimeoutMs(),
4009
+ stage: "has-session"
3980
4010
  });
3981
4011
  return { exists: result.code === 0 };
3982
4012
  }
3983
4013
  async tailSessionHistory(input) {
3984
4014
  const candidates = [
4015
+ ["sessions", "history", input.name, "--limit", String(input.lines)],
3985
4016
  ["sessions", "history", "quiet", "-s", input.name, String(input.lines)],
3986
4017
  ["sessions", "history", "quiet", input.name, String(input.lines)],
3987
4018
  ["sessions", "history", "-s", input.name, "--tail", String(input.lines)],
@@ -3993,7 +4024,8 @@ class BridgeRuntime {
3993
4024
  for (const tailArgs of candidates) {
3994
4025
  const spawnSpec = resolveSpawnCommand(this.command, this.buildSessionArgs(input, tailArgs));
3995
4026
  const result = await this.run(spawnSpec.command, spawnSpec.args, {
3996
- timeoutMs: Math.max(deadline - Date.now(), 1)
4027
+ timeoutMs: Math.max(deadline - Date.now(), 1),
4028
+ stage: "session-history"
3997
4029
  });
3998
4030
  if (result.code === 0) {
3999
4031
  return { text: result.stdout.trimEnd() };
@@ -4162,7 +4194,8 @@ class BridgeRuntime {
4162
4194
  input.name
4163
4195
  ]));
4164
4196
  const result = await this.run(spawnSpec.command, spawnSpec.args, {
4165
- timeoutMs: this.managementCommandTimeoutMs()
4197
+ timeoutMs: this.managementCommandTimeoutMs(),
4198
+ stage: "read-session-record"
4166
4199
  });
4167
4200
  if (result.code !== 0) {
4168
4201
  throw new Error(result.stderr || result.stdout || "sessions show failed");
@@ -4184,7 +4217,8 @@ class BridgeRuntime {
4184
4217
  input.modeId
4185
4218
  ]));
4186
4219
  const result = await this.run(spawnSpec.command, spawnSpec.args, {
4187
- timeoutMs: this.managementCommandTimeoutMs()
4220
+ timeoutMs: this.managementCommandTimeoutMs(),
4221
+ stage: "set-mode"
4188
4222
  });
4189
4223
  if (result.code !== 0) {
4190
4224
  throw new Error(result.stderr || result.stdout || "set-mode failed");
@@ -4200,7 +4234,8 @@ class BridgeRuntime {
4200
4234
  input.modelId
4201
4235
  ]));
4202
4236
  const result = await this.run(spawnSpec.command, spawnSpec.args, {
4203
- timeoutMs: this.managementCommandTimeoutMs()
4237
+ timeoutMs: this.managementCommandTimeoutMs(),
4238
+ stage: "set-model"
4204
4239
  });
4205
4240
  if (result.code !== 0) {
4206
4241
  throw new Error(result.stderr || result.stdout || "set-model failed");
@@ -4214,7 +4249,8 @@ class BridgeRuntime {
4214
4249
  input.name
4215
4250
  ], { format: "json" }));
4216
4251
  const result = await this.run(spawnSpec.command, spawnSpec.args, {
4217
- timeoutMs: this.managementCommandTimeoutMs()
4252
+ timeoutMs: this.managementCommandTimeoutMs(),
4253
+ stage: "get-session-model"
4218
4254
  });
4219
4255
  if (result.code !== 0) {
4220
4256
  throw new Error(result.stderr || result.stdout || "status failed");
@@ -4236,7 +4272,8 @@ class BridgeRuntime {
4236
4272
  input.name
4237
4273
  ]));
4238
4274
  const result = await this.run(spawnSpec.command, spawnSpec.args, {
4239
- timeoutMs: this.managementCommandTimeoutMs()
4275
+ timeoutMs: this.managementCommandTimeoutMs(),
4276
+ stage: "cancel"
4240
4277
  });
4241
4278
  if (result.code !== 0) {
4242
4279
  throw new Error(result.stderr || result.stdout || "cancel failed");
@@ -4253,7 +4290,8 @@ class BridgeRuntime {
4253
4290
  input.name
4254
4291
  ]));
4255
4292
  const result = await this.run(spawnSpec.command, spawnSpec.args, {
4256
- timeoutMs: this.managementCommandTimeoutMs()
4293
+ timeoutMs: this.managementCommandTimeoutMs(),
4294
+ stage: "remove-session"
4257
4295
  });
4258
4296
  if (result.code === 0) {
4259
4297
  return {};
@@ -4326,7 +4364,11 @@ function spawnCapture(command, args, options) {
4326
4364
  const timeoutId = typeof options?.timeoutMs === "number" && Number.isFinite(options.timeoutMs) && options.timeoutMs > 0 ? setTimeout(() => {
4327
4365
  const kill = options.killProcessTreeFn ?? ((pid) => terminateProcessTree(pid, { detachedProcessGroup: false }));
4328
4366
  kill(child.pid ?? 0);
4329
- reject(new CommandTimeoutError(options.timeoutMs, [command, ...args].join(" ")));
4367
+ reject(new CommandTimeoutError(options.timeoutMs, [command, ...args].join(" "), {
4368
+ stage: options.stage,
4369
+ stdout,
4370
+ stderr
4371
+ }));
4330
4372
  }, options.timeoutMs) : undefined;
4331
4373
  child.stdout.on("data", (chunk) => {
4332
4374
  stdout += String(chunk);
@@ -4543,6 +4585,15 @@ class BridgeServer {
4543
4585
  const message = error instanceof Error ? error.message : String(error);
4544
4586
  const ensureSessionFields = error instanceof EnsureSessionFailedError ? { kind: error.kind, ...error.data ? { data: error.data } : {} } : {};
4545
4587
  const promptDetails = error instanceof PromptCommandError ? { details: { exitCode: error.exitCode, stdout: error.stdout, stderr: error.stderr } } : {};
4588
+ const timeoutDetails = error instanceof CommandTimeoutError ? {
4589
+ timeout: {
4590
+ timeoutMs: error.timeoutMs,
4591
+ command: error.command,
4592
+ ...error.stage ? { stage: error.stage } : {},
4593
+ ...error.stdoutTail ? { stdoutTail: error.stdoutTail } : {},
4594
+ ...error.stderrTail ? { stderrTail: error.stderrTail } : {}
4595
+ }
4596
+ } : {};
4546
4597
  return `${JSON.stringify({
4547
4598
  id: requestId,
4548
4599
  ok: false,
@@ -4550,7 +4601,8 @@ class BridgeServer {
4550
4601
  code: error instanceof BridgeInvalidRequestError ? "BRIDGE_INVALID_REQUEST" : "BRIDGE_INTERNAL_ERROR",
4551
4602
  message,
4552
4603
  ...ensureSessionFields,
4553
- ...promptDetails
4604
+ ...promptDetails,
4605
+ ...timeoutDetails
4554
4606
  }
4555
4607
  })}
4556
4608
  `;