happy-imou-cloud 2.0.4 → 2.0.6

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 (24) hide show
  1. package/dist/{BaseReasoningProcessor-Di1yEMMv.mjs → BaseReasoningProcessor-1EzrE03x.mjs} +2 -2
  2. package/dist/{BaseReasoningProcessor-DEEfNi5Y.cjs → BaseReasoningProcessor-BMyfwx3p.cjs} +2 -2
  3. package/dist/{api-CyJG1mr6.cjs → api-DccDghmF.cjs} +5 -3
  4. package/dist/{api-CIHTNilH.mjs → api-Emo3rSZH.mjs} +5 -3
  5. package/dist/{command-CPlJKXDn.cjs → command-C2v0VkPq.cjs} +3 -3
  6. package/dist/{command-BERqmFB0.mjs → command-D8Zz6B4t.mjs} +3 -3
  7. package/dist/{index-1zlH6s7a.cjs → index-Buq7nurH.cjs} +368 -131
  8. package/dist/{index-vNYxNqVZ.mjs → index-Dh8UTgm4.mjs} +366 -129
  9. package/dist/index.cjs +5 -5
  10. package/dist/index.mjs +5 -5
  11. package/dist/lib.cjs +1 -1
  12. package/dist/lib.mjs +1 -1
  13. package/dist/{persistence-sLEqV8vk.mjs → persistence-Blm1hTQA.mjs} +1 -1
  14. package/dist/{persistence-BeFVx6kI.cjs → persistence-BrTyBuT7.cjs} +1 -1
  15. package/dist/{registerKillSessionHandler-uVHqIC4h.mjs → registerKillSessionHandler-Bm7E-03E.mjs} +2 -2
  16. package/dist/{registerKillSessionHandler-CCxqGFjZ.cjs → registerKillSessionHandler-EFAsOnR_.cjs} +2 -2
  17. package/dist/{runClaude-Dz-PCSvb.cjs → runClaude-COy1pLhn.cjs} +5 -5
  18. package/dist/{runClaude-Dl9nIRIg.mjs → runClaude-CwA5UCO-.mjs} +4 -4
  19. package/dist/{runCodex-BtZplK1R.cjs → runCodex-BRMOT2dJ.cjs} +53 -17
  20. package/dist/{runCodex-DgKKw3IU.mjs → runCodex-DTPmqCyS.mjs} +53 -17
  21. package/dist/{runGemini-DUyH311Z.cjs → runGemini-BVPmTGxQ.cjs} +51 -19
  22. package/dist/{runGemini-CM1v3I24.mjs → runGemini-DDSR8BtO.mjs} +51 -19
  23. package/package.json +3 -2
  24. package/scripts/release-smoke.mjs +4 -0
@@ -1,8 +1,8 @@
1
1
  'use strict';
2
2
 
3
3
  var chalk = require('chalk');
4
- var api = require('./api-CyJG1mr6.cjs');
5
- var persistence = require('./persistence-BeFVx6kI.cjs');
4
+ var api = require('./api-DccDghmF.cjs');
5
+ var persistence = require('./persistence-BrTyBuT7.cjs');
6
6
  var z = require('zod');
7
7
  var fs$1 = require('fs/promises');
8
8
  var os$1 = require('os');
@@ -70,7 +70,7 @@ async function openBrowser(url) {
70
70
  }
71
71
  }
72
72
 
73
- const require$1 = node_module.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index-1zlH6s7a.cjs', document.baseURI).href)));
73
+ const require$1 = node_module.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index-Buq7nurH.cjs', document.baseURI).href)));
74
74
  const QRCode = require$1("qrcode-terminal/vendor/QRCode");
75
75
  const QRErrorCorrectLevel = require$1("qrcode-terminal/vendor/QRCode/QRErrorCorrectLevel");
76
76
  const pendingTempFiles = /* @__PURE__ */ new Set();
@@ -693,7 +693,7 @@ function setupCleanupHandlers() {
693
693
  });
694
694
  }
695
695
 
696
- const __dirname$1 = path.dirname(url.fileURLToPath((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index-1zlH6s7a.cjs', document.baseURI).href))));
696
+ const __dirname$1 = path.dirname(url.fileURLToPath((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index-Buq7nurH.cjs', document.baseURI).href))));
697
697
  function projectPath() {
698
698
  const path$1 = path.resolve(__dirname$1, "..");
699
699
  return path$1;
@@ -4928,6 +4928,205 @@ function handleThinkingUpdate(update, ctx) {
4928
4928
  return { handled: true };
4929
4929
  }
4930
4930
 
4931
+ function buildAcpSpawnSpec(params) {
4932
+ return {
4933
+ command: params.command,
4934
+ args: (params.args ?? []).map((arg) => String(arg)),
4935
+ options: {
4936
+ cwd: params.cwd,
4937
+ env: params.env,
4938
+ stdio: ["pipe", "pipe", "pipe"],
4939
+ windowsHide: process.platform === "win32"
4940
+ }
4941
+ };
4942
+ }
4943
+
4944
+ function createAcpFilteredStdoutReadable(params) {
4945
+ const maxMultilineBytes = typeof params.maxMultilineBytes === "number" && Number.isFinite(params.maxMultilineBytes) && params.maxMultilineBytes > 0 ? Math.trunc(params.maxMultilineBytes) : 1e6;
4946
+ const decoder = new TextDecoder();
4947
+ const encoder = new TextEncoder();
4948
+ return new ReadableStream({
4949
+ async start(controller) {
4950
+ const reader = params.readable.getReader();
4951
+ let buffer = "";
4952
+ let multiline = null;
4953
+ let controllerErrored = false;
4954
+ const drop = (reason, line) => {
4955
+ params.onDroppedLine?.({ reason, line });
4956
+ };
4957
+ const enqueueLine = (line) => {
4958
+ if (!line.trim()) {
4959
+ return;
4960
+ }
4961
+ const filtered = params.transport.filterStdoutLine?.(line);
4962
+ if (filtered === void 0) {
4963
+ controller.enqueue(encoder.encode(line + "\n"));
4964
+ return;
4965
+ }
4966
+ if (filtered === null) {
4967
+ drop("transport_filter_null", line);
4968
+ return;
4969
+ }
4970
+ controller.enqueue(encoder.encode(filtered + "\n"));
4971
+ };
4972
+ const tryFlushMultiline = (candidate) => {
4973
+ const trimmed = candidate.trim();
4974
+ if (!trimmed) {
4975
+ return false;
4976
+ }
4977
+ if (!trimmed.startsWith("{") && !trimmed.startsWith("[")) {
4978
+ return false;
4979
+ }
4980
+ try {
4981
+ const parsed = JSON.parse(trimmed);
4982
+ if (typeof parsed !== "object" || parsed === null) {
4983
+ return false;
4984
+ }
4985
+ enqueueLine(JSON.stringify(parsed));
4986
+ return true;
4987
+ } catch {
4988
+ return false;
4989
+ }
4990
+ };
4991
+ try {
4992
+ while (true) {
4993
+ const { value, done } = await reader.read();
4994
+ if (done) {
4995
+ break;
4996
+ }
4997
+ if (!value) {
4998
+ continue;
4999
+ }
5000
+ buffer += decoder.decode(value, { stream: true });
5001
+ const lines = buffer.split("\n");
5002
+ buffer = lines.pop() || "";
5003
+ for (const line of lines) {
5004
+ if (multiline) {
5005
+ const nextBuf = multiline.buf.length > 0 ? `${multiline.buf}
5006
+ ${line}` : line;
5007
+ const nextBytes = multiline.bytes + line.length + 1;
5008
+ if (nextBytes > maxMultilineBytes) {
5009
+ drop("multiline_overflow", multiline.buf);
5010
+ multiline = null;
5011
+ enqueueLine(line);
5012
+ continue;
5013
+ }
5014
+ multiline = { buf: nextBuf, bytes: nextBytes };
5015
+ if (tryFlushMultiline(multiline.buf)) {
5016
+ multiline = null;
5017
+ }
5018
+ continue;
5019
+ }
5020
+ const trimmed = line.trim();
5021
+ if (trimmed.startsWith("{") || trimmed.startsWith("[")) {
5022
+ try {
5023
+ const parsed = JSON.parse(trimmed);
5024
+ if (typeof parsed === "object" && parsed !== null) {
5025
+ enqueueLine(line);
5026
+ continue;
5027
+ }
5028
+ } catch {
5029
+ multiline = { buf: line, bytes: line.length };
5030
+ continue;
5031
+ }
5032
+ }
5033
+ enqueueLine(line);
5034
+ }
5035
+ }
5036
+ if (multiline) {
5037
+ if (!tryFlushMultiline(multiline.buf)) {
5038
+ drop("multiline_incomplete", multiline.buf);
5039
+ }
5040
+ multiline = null;
5041
+ }
5042
+ const trailing = buffer.trim();
5043
+ if (trailing) {
5044
+ drop("multiline_incomplete", buffer);
5045
+ }
5046
+ } catch (error) {
5047
+ controllerErrored = true;
5048
+ controller.error(error);
5049
+ } finally {
5050
+ reader.releaseLock();
5051
+ if (!controllerErrored) {
5052
+ controller.close();
5053
+ }
5054
+ }
5055
+ }
5056
+ });
5057
+ }
5058
+
5059
+ function isAlive(pid) {
5060
+ try {
5061
+ process.kill(pid, 0);
5062
+ return true;
5063
+ } catch {
5064
+ return false;
5065
+ }
5066
+ }
5067
+ async function resolveDescendantPids(rootPid) {
5068
+ const processes = await psList();
5069
+ const childrenByParent = /* @__PURE__ */ new Map();
5070
+ for (const proc of processes) {
5071
+ if (typeof proc.pid !== "number" || typeof proc.ppid !== "number") {
5072
+ continue;
5073
+ }
5074
+ const children = childrenByParent.get(proc.ppid) ?? [];
5075
+ children.push(proc.pid);
5076
+ childrenByParent.set(proc.ppid, children);
5077
+ }
5078
+ const descendants = [];
5079
+ const seen = /* @__PURE__ */ new Set();
5080
+ const visit = (pid) => {
5081
+ for (const childPid of childrenByParent.get(pid) ?? []) {
5082
+ if (seen.has(childPid)) {
5083
+ continue;
5084
+ }
5085
+ seen.add(childPid);
5086
+ visit(childPid);
5087
+ descendants.push(childPid);
5088
+ }
5089
+ };
5090
+ visit(rootPid);
5091
+ return descendants;
5092
+ }
5093
+ function bestEffortKillPid(pid, signal) {
5094
+ try {
5095
+ process.kill(pid, signal);
5096
+ } catch {
5097
+ }
5098
+ }
5099
+ async function waitForAllGone(pids, timeoutMs) {
5100
+ const start = Date.now();
5101
+ while (Date.now() - start < timeoutMs) {
5102
+ if (pids.every((pid) => !isAlive(pid))) {
5103
+ return;
5104
+ }
5105
+ await new Promise((resolve) => setTimeout(resolve, 25));
5106
+ }
5107
+ }
5108
+ async function killProcessTree(proc, options) {
5109
+ const pid = proc.pid;
5110
+ if (!pid) {
5111
+ return;
5112
+ }
5113
+ const graceMs = Math.max(1, options?.graceMs);
5114
+ const descendants = await resolveDescendantPids(pid).catch(() => []);
5115
+ const allPids = [...descendants, pid];
5116
+ for (const targetPid of allPids) {
5117
+ bestEffortKillPid(targetPid, "SIGTERM");
5118
+ }
5119
+ await waitForAllGone(allPids, graceMs);
5120
+ const remaining = allPids.filter((targetPid) => isAlive(targetPid));
5121
+ if (remaining.length === 0) {
5122
+ return;
5123
+ }
5124
+ for (const targetPid of remaining) {
5125
+ bestEffortKillPid(targetPid, "SIGKILL");
5126
+ }
5127
+ await waitForAllGone(remaining, Math.min(250, graceMs));
5128
+ }
5129
+
4931
5130
  const RETRY_CONFIG = {
4932
5131
  /** Maximum number of retry attempts for init/newSession */
4933
5132
  maxAttempts: 3,
@@ -5064,15 +5263,17 @@ async function withRetry(operation, options) {
5064
5263
  return await operation();
5065
5264
  } catch (error) {
5066
5265
  lastError = normalizeAcpError(error);
5067
- if (attempt < options.maxAttempts) {
5068
- const delayMs = Math.min(
5069
- options.baseDelayMs * Math.pow(2, attempt - 1),
5070
- options.maxDelayMs
5071
- );
5072
- api.logger.debug(`[AcpBackend] ${options.operationName} failed (attempt ${attempt}/${options.maxAttempts}): ${lastError.message}. Retrying in ${delayMs}ms...`);
5073
- options.onRetry?.(attempt, lastError);
5074
- await api.delay(delayMs);
5266
+ const retryable = options.shouldRetry?.(lastError) ?? true;
5267
+ if (!retryable || attempt >= options.maxAttempts) {
5268
+ throw lastError;
5075
5269
  }
5270
+ const delayMs = Math.min(
5271
+ options.baseDelayMs * Math.pow(2, attempt - 1),
5272
+ options.maxDelayMs
5273
+ );
5274
+ api.logger.debug(`[AcpBackend] ${options.operationName} failed (attempt ${attempt}/${options.maxAttempts}): ${lastError.message}. Retrying in ${delayMs}ms...`);
5275
+ options.onRetry?.(attempt, lastError);
5276
+ await api.delay(delayMs);
5076
5277
  }
5077
5278
  }
5078
5279
  throw lastError;
@@ -5125,6 +5326,77 @@ function enrichAcpError(error, stderrExcerpt) {
5125
5326
  }
5126
5327
  return normalized;
5127
5328
  }
5329
+ class AcpProcessStartupError extends Error {
5330
+ constructor(message, exitCode, signal) {
5331
+ super(message);
5332
+ this.exitCode = exitCode;
5333
+ this.signal = signal;
5334
+ this.name = "AcpProcessStartupError";
5335
+ }
5336
+ }
5337
+ function createProcessStartupError(agentName, operationName, code, signal) {
5338
+ if (code !== null) {
5339
+ return new AcpProcessStartupError(
5340
+ `${agentName} exited with code ${code} during ${operationName}`,
5341
+ code,
5342
+ signal
5343
+ );
5344
+ }
5345
+ if (signal) {
5346
+ return new AcpProcessStartupError(
5347
+ `${agentName} exited due to signal ${signal} during ${operationName}`,
5348
+ code,
5349
+ signal
5350
+ );
5351
+ }
5352
+ return new AcpProcessStartupError(
5353
+ `${agentName} exited unexpectedly during ${operationName}`,
5354
+ code,
5355
+ signal
5356
+ );
5357
+ }
5358
+ async function raceWithProcessExit(childProcess, operation, options) {
5359
+ if (childProcess.exitCode !== null) {
5360
+ throw createProcessStartupError(
5361
+ options.agentName,
5362
+ options.operationName,
5363
+ childProcess.exitCode,
5364
+ childProcess.signalCode ?? null
5365
+ );
5366
+ }
5367
+ return await new Promise((resolve, reject) => {
5368
+ let settled = false;
5369
+ const cleanup = () => {
5370
+ childProcess.off("error", handleError);
5371
+ childProcess.off("exit", handleExit);
5372
+ };
5373
+ const settleResolve = (value) => {
5374
+ if (settled) {
5375
+ return;
5376
+ }
5377
+ settled = true;
5378
+ cleanup();
5379
+ resolve(value);
5380
+ };
5381
+ const settleReject = (error) => {
5382
+ if (settled) {
5383
+ return;
5384
+ }
5385
+ settled = true;
5386
+ cleanup();
5387
+ reject(normalizeAcpError(error));
5388
+ };
5389
+ const handleError = (error) => {
5390
+ settleReject(error);
5391
+ };
5392
+ const handleExit = (code, signal) => {
5393
+ settleReject(createProcessStartupError(options.agentName, options.operationName, code, signal));
5394
+ };
5395
+ childProcess.once("error", handleError);
5396
+ childProcess.once("exit", handleExit);
5397
+ operation.then(settleResolve, settleReject);
5398
+ });
5399
+ }
5128
5400
  class AcpBackend {
5129
5401
  constructor(options) {
5130
5402
  this.options = options;
@@ -5243,24 +5515,13 @@ class AcpBackend {
5243
5515
  try {
5244
5516
  api.logger.debug(`[AcpBackend] Starting session: ${sessionId}`);
5245
5517
  this.recentStderrLines = [];
5246
- const args = this.options.args || [];
5247
- if (process.platform === "win32") {
5248
- const fullCommand = [this.options.command, ...args].join(" ");
5249
- this.process = node_child_process.spawn("cmd.exe", ["/c", fullCommand], {
5250
- cwd: this.options.cwd,
5251
- env: { ...process.env, ...this.options.env },
5252
- stdio: ["pipe", "pipe", "pipe"],
5253
- windowsHide: true
5254
- });
5255
- } else {
5256
- this.process = node_child_process.spawn(this.options.command, args, {
5257
- cwd: this.options.cwd,
5258
- env: { ...process.env, ...this.options.env },
5259
- // Use 'pipe' for all stdio to capture output without printing to console
5260
- // stdout and stderr will be handled by our event listeners
5261
- stdio: ["pipe", "pipe", "pipe"]
5262
- });
5263
- }
5518
+ const spawnSpec = buildAcpSpawnSpec({
5519
+ command: this.options.command,
5520
+ args: this.options.args ?? [],
5521
+ cwd: this.options.cwd,
5522
+ env: { ...process.env, ...this.options.env }
5523
+ });
5524
+ this.process = spawn(spawnSpec.command, spawnSpec.args, spawnSpec.options);
5264
5525
  if (this.process.stderr) {
5265
5526
  }
5266
5527
  if (!this.process.stdin || !this.process.stdout || !this.process.stderr) {
@@ -5308,57 +5569,20 @@ class AcpBackend {
5308
5569
  );
5309
5570
  const writable = streams.writable;
5310
5571
  const readable = streams.readable;
5311
- const transport = this.transport;
5312
- const filteredReadable = new ReadableStream({
5313
- async start(controller) {
5314
- const reader = readable.getReader();
5315
- const decoder = new TextDecoder();
5316
- const encoder = new TextEncoder();
5317
- let buffer = "";
5318
- let filteredCount = 0;
5319
- try {
5320
- while (true) {
5321
- const { done, value } = await reader.read();
5322
- if (done) {
5323
- if (buffer.trim()) {
5324
- const filtered = transport.filterStdoutLine?.(buffer);
5325
- if (filtered === void 0) {
5326
- controller.enqueue(encoder.encode(buffer));
5327
- } else if (filtered !== null) {
5328
- controller.enqueue(encoder.encode(filtered));
5329
- } else {
5330
- filteredCount++;
5331
- }
5332
- }
5333
- if (filteredCount > 0) {
5334
- api.logger.debug(`[AcpBackend] Filtered out ${filteredCount} non-JSON lines from ${transport.agentName} stdout`);
5335
- }
5336
- controller.close();
5337
- break;
5338
- }
5339
- buffer += decoder.decode(value, { stream: true });
5340
- const lines = buffer.split("\n");
5341
- buffer = lines.pop() || "";
5342
- for (const line of lines) {
5343
- if (!line.trim()) continue;
5344
- const filtered = transport.filterStdoutLine?.(line);
5345
- if (filtered === void 0) {
5346
- controller.enqueue(encoder.encode(line + "\n"));
5347
- } else if (filtered !== null) {
5348
- controller.enqueue(encoder.encode(filtered + "\n"));
5349
- } else {
5350
- filteredCount++;
5351
- }
5352
- }
5353
- }
5354
- } catch (error) {
5355
- api.logger.debug(`[AcpBackend] Error filtering stdout stream:`, error);
5356
- controller.error(error);
5357
- } finally {
5358
- reader.releaseLock();
5359
- }
5572
+ const droppedStdoutLines = [];
5573
+ const filteredReadable = createAcpFilteredStdoutReadable({
5574
+ readable,
5575
+ transport: this.transport,
5576
+ onDroppedLine: (entry) => {
5577
+ droppedStdoutLines.push(entry);
5360
5578
  }
5361
5579
  });
5580
+ if (droppedStdoutLines.length > 0) {
5581
+ api.logger.debug(
5582
+ `[AcpBackend] Filtered out ${droppedStdoutLines.length} stdout lines from ${this.transport.agentName}`,
5583
+ droppedStdoutLines.slice(0, 5)
5584
+ );
5585
+ }
5362
5586
  const stream = sdk.ndJsonStream(writable, filteredReadable);
5363
5587
  const client = {
5364
5588
  sessionUpdate: async (params) => {
@@ -5525,20 +5749,27 @@ class AcpBackend {
5525
5749
  async () => {
5526
5750
  let timeoutHandle = null;
5527
5751
  try {
5528
- const result = await Promise.race([
5529
- this.connection.initialize(initRequest).then((res) => {
5530
- if (timeoutHandle) {
5531
- clearTimeout(timeoutHandle);
5532
- timeoutHandle = null;
5533
- }
5534
- return res;
5535
- }),
5536
- new Promise((_, reject) => {
5537
- timeoutHandle = setTimeout(() => {
5538
- reject(new Error(`Initialize timeout after ${initTimeout}ms - ${this.transport.agentName} did not respond`));
5539
- }, initTimeout);
5540
- })
5541
- ]);
5752
+ const result = await raceWithProcessExit(
5753
+ this.process,
5754
+ Promise.race([
5755
+ this.connection.initialize(initRequest).then((res) => {
5756
+ if (timeoutHandle) {
5757
+ clearTimeout(timeoutHandle);
5758
+ timeoutHandle = null;
5759
+ }
5760
+ return res;
5761
+ }),
5762
+ new Promise((_, reject) => {
5763
+ timeoutHandle = setTimeout(() => {
5764
+ reject(new Error(`Initialize timeout after ${initTimeout}ms - ${this.transport.agentName} did not respond`));
5765
+ }, initTimeout);
5766
+ })
5767
+ ]),
5768
+ {
5769
+ agentName: this.transport.agentName,
5770
+ operationName: "initialize"
5771
+ }
5772
+ );
5542
5773
  return result;
5543
5774
  } finally {
5544
5775
  if (timeoutHandle) {
@@ -5550,7 +5781,8 @@ class AcpBackend {
5550
5781
  operationName: "Initialize",
5551
5782
  maxAttempts: RETRY_CONFIG.maxAttempts,
5552
5783
  baseDelayMs: RETRY_CONFIG.baseDelayMs,
5553
- maxDelayMs: RETRY_CONFIG.maxDelayMs
5784
+ maxDelayMs: RETRY_CONFIG.maxDelayMs,
5785
+ shouldRetry: (error) => !(error instanceof AcpProcessStartupError)
5554
5786
  }
5555
5787
  );
5556
5788
  api.logger.debug(`[AcpBackend] Initialize completed`);
@@ -5569,20 +5801,27 @@ class AcpBackend {
5569
5801
  async () => {
5570
5802
  let timeoutHandle = null;
5571
5803
  try {
5572
- const result = await Promise.race([
5573
- this.connection.newSession(newSessionRequest).then((res) => {
5574
- if (timeoutHandle) {
5575
- clearTimeout(timeoutHandle);
5576
- timeoutHandle = null;
5577
- }
5578
- return res;
5579
- }),
5580
- new Promise((_, reject) => {
5581
- timeoutHandle = setTimeout(() => {
5582
- reject(new Error(`New session timeout after ${initTimeout}ms - ${this.transport.agentName} did not respond`));
5583
- }, initTimeout);
5584
- })
5585
- ]);
5804
+ const result = await raceWithProcessExit(
5805
+ this.process,
5806
+ Promise.race([
5807
+ this.connection.newSession(newSessionRequest).then((res) => {
5808
+ if (timeoutHandle) {
5809
+ clearTimeout(timeoutHandle);
5810
+ timeoutHandle = null;
5811
+ }
5812
+ return res;
5813
+ }),
5814
+ new Promise((_, reject) => {
5815
+ timeoutHandle = setTimeout(() => {
5816
+ reject(new Error(`New session timeout after ${initTimeout}ms - ${this.transport.agentName} did not respond`));
5817
+ }, initTimeout);
5818
+ })
5819
+ ]),
5820
+ {
5821
+ agentName: this.transport.agentName,
5822
+ operationName: "new session"
5823
+ }
5824
+ );
5586
5825
  return result;
5587
5826
  } finally {
5588
5827
  if (timeoutHandle) {
@@ -5594,7 +5833,8 @@ class AcpBackend {
5594
5833
  operationName: "NewSession",
5595
5834
  maxAttempts: RETRY_CONFIG.maxAttempts,
5596
5835
  baseDelayMs: RETRY_CONFIG.baseDelayMs,
5597
- maxDelayMs: RETRY_CONFIG.maxDelayMs
5836
+ maxDelayMs: RETRY_CONFIG.maxDelayMs,
5837
+ shouldRetry: (error) => !(error instanceof AcpProcessStartupError)
5598
5838
  }
5599
5839
  );
5600
5840
  this.acpSessionId = sessionResponse.sessionId;
@@ -5870,21 +6110,13 @@ class AcpBackend {
5870
6110
  }
5871
6111
  }
5872
6112
  if (this.process) {
5873
- this.process.kill("SIGTERM");
5874
- await new Promise((resolve) => {
5875
- const timeout = setTimeout(() => {
5876
- if (this.process) {
5877
- api.logger.debug("[AcpBackend] Force killing process");
5878
- this.process.kill("SIGKILL");
5879
- }
5880
- resolve();
5881
- }, 1e3);
5882
- this.process?.once("exit", () => {
5883
- clearTimeout(timeout);
5884
- resolve();
5885
- });
5886
- });
5887
- this.process = null;
6113
+ try {
6114
+ await killProcessTree(this.process, { graceMs: 1e3 });
6115
+ } catch (error) {
6116
+ api.logger.debug("[AcpBackend] Failed to kill ACP process tree:", error);
6117
+ } finally {
6118
+ this.process = null;
6119
+ }
5888
6120
  }
5889
6121
  this.clearIdleTimeoutState();
5890
6122
  this.listeners = [];
@@ -6125,6 +6357,7 @@ function registerGeminiAgent() {
6125
6357
  api.logger.debug("[Gemini] Registered with agent registry");
6126
6358
  }
6127
6359
 
6360
+ const DEFAULT_CODEX_ACP_NPX_PACKAGE = "@zed-industries/codex-acp@0.9.5";
6128
6361
  function readFirstEnv(...names) {
6129
6362
  for (const name of names) {
6130
6363
  const raw = process.env[name];
@@ -6179,6 +6412,10 @@ function readCodexAcpNpxMode() {
6179
6412
  }
6180
6413
  return "auto";
6181
6414
  }
6415
+ function readCodexAcpNpxPackage() {
6416
+ const configured = readFirstEnv("HAPPY_CODEX_ACP_PACKAGE", "HAPPIER_CODEX_ACP_PACKAGE");
6417
+ return configured || DEFAULT_CODEX_ACP_NPX_PACKAGE;
6418
+ }
6182
6419
  function isBinOnPath(baseName) {
6183
6420
  return resolveCommandOnPath(baseName) !== null;
6184
6421
  }
@@ -6244,7 +6481,7 @@ function resolveCodexAcpSpawn(options = {}) {
6244
6481
  }
6245
6482
  return {
6246
6483
  command: resolveNpxCommand(),
6247
- args: ["--prefer-offline", "-y", "@zed-industries/codex-acp", ...directArgs]
6484
+ args: ["--prefer-offline", "-y", readCodexAcpNpxPackage(), ...directArgs]
6248
6485
  };
6249
6486
  }
6250
6487
  function validateCodexAcpSpawn(options = {}) {
@@ -6531,12 +6768,12 @@ async function ensureUnifiedDaemonStarted() {
6531
6768
  async function executeUnifiedProvider(opts) {
6532
6769
  const credentials = await ensureUnifiedRuntimePrerequisites(opts.credentials);
6533
6770
  if (opts.provider === "claude") {
6534
- const { runClaude } = await Promise.resolve().then(function () { return require('./runClaude-Dz-PCSvb.cjs'); });
6771
+ const { runClaude } = await Promise.resolve().then(function () { return require('./runClaude-COy1pLhn.cjs'); });
6535
6772
  await runClaude(credentials, opts.claudeOptions ?? {});
6536
6773
  return;
6537
6774
  }
6538
6775
  if (opts.provider === "codex") {
6539
- const { runCodex } = await Promise.resolve().then(function () { return require('./runCodex-BtZplK1R.cjs'); });
6776
+ const { runCodex } = await Promise.resolve().then(function () { return require('./runCodex-BRMOT2dJ.cjs'); });
6540
6777
  await runCodex({
6541
6778
  credentials,
6542
6779
  startedBy: opts.startedBy,
@@ -6546,7 +6783,7 @@ async function executeUnifiedProvider(opts) {
6546
6783
  return;
6547
6784
  }
6548
6785
  if (opts.provider === "gemini") {
6549
- const { runGemini } = await Promise.resolve().then(function () { return require('./runGemini-DUyH311Z.cjs'); });
6786
+ const { runGemini } = await Promise.resolve().then(function () { return require('./runGemini-BVPmTGxQ.cjs'); });
6550
6787
  await runGemini({
6551
6788
  credentials,
6552
6789
  startedBy: opts.startedBy
@@ -6588,7 +6825,7 @@ function shouldRunMainClaudeFlow(opts) {
6588
6825
  return;
6589
6826
  } else if (subcommand === "runtime") {
6590
6827
  if (args[1] === "providers") {
6591
- const { renderRuntimeProviders } = await Promise.resolve().then(function () { return require('./command-CPlJKXDn.cjs'); });
6828
+ const { renderRuntimeProviders } = await Promise.resolve().then(function () { return require('./command-C2v0VkPq.cjs'); });
6592
6829
  console.log(renderRuntimeProviders());
6593
6830
  return;
6594
6831
  }
@@ -6766,8 +7003,8 @@ function shouldRunMainClaudeFlow(opts) {
6766
7003
  const projectId = args[3];
6767
7004
  try {
6768
7005
  const { saveGoogleCloudProjectToConfig } = await Promise.resolve().then(function () { return config; });
6769
- const { readCredentials: readCredentials2 } = await Promise.resolve().then(function () { return require('./persistence-BeFVx6kI.cjs'); });
6770
- const { ApiClient: ApiClient2 } = await Promise.resolve().then(function () { return require('./api-CyJG1mr6.cjs'); }).then(function (n) { return n.api; });
7006
+ const { readCredentials: readCredentials2 } = await Promise.resolve().then(function () { return require('./persistence-BrTyBuT7.cjs'); });
7007
+ const { ApiClient: ApiClient2 } = await Promise.resolve().then(function () { return require('./api-DccDghmF.cjs'); }).then(function (n) { return n.api; });
6771
7008
  let userEmail = void 0;
6772
7009
  try {
6773
7010
  const credentials = await readCredentials2();