happy-imou-cloud 2.0.3 → 2.0.5

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 (23) hide show
  1. package/dist/{BaseReasoningProcessor-_wxlqKB8.cjs → BaseReasoningProcessor-DPVZIJ4n.cjs} +2 -2
  2. package/dist/{BaseReasoningProcessor-B37yOHxo.mjs → BaseReasoningProcessor-bFVTvf3Q.mjs} +2 -2
  3. package/dist/{api-D9dIR956.cjs → api-DaqnNHfl.cjs} +4 -2
  4. package/dist/{api-DpQIC-DJ.mjs → api-DoHt-HyL.mjs} +4 -2
  5. package/dist/{command-CdXv1zNF.cjs → command-D9-hmqVq.cjs} +3 -3
  6. package/dist/{command-DRqrBuHM.mjs → command-Dl9SrMnv.mjs} +3 -3
  7. package/dist/{index-CriPm_z9.mjs → index-C5wR2qKT.mjs} +359 -70
  8. package/dist/{index-LYPXVO_L.cjs → index-Dc92gnxM.cjs} +361 -72
  9. package/dist/index.cjs +3 -3
  10. package/dist/index.mjs +3 -3
  11. package/dist/lib.cjs +1 -1
  12. package/dist/lib.mjs +1 -1
  13. package/dist/{persistence-PzKU0QCa.cjs → persistence-D6Y0604_.cjs} +1 -1
  14. package/dist/{persistence-CqgPgbzN.mjs → persistence-QqeBvUxX.mjs} +1 -1
  15. package/dist/{registerKillSessionHandler-BDBPoQSA.cjs → registerKillSessionHandler-C6yXr8ky.cjs} +2 -2
  16. package/dist/{registerKillSessionHandler-C3M_-4Zg.mjs → registerKillSessionHandler-CC9zGBPE.mjs} +2 -2
  17. package/dist/{runClaude-D6Pdkevn.mjs → runClaude-CZ8gxaJL.mjs} +4 -4
  18. package/dist/{runClaude-IeRSC5qX.cjs → runClaude-gHKFB1UG.cjs} +5 -5
  19. package/dist/{runCodex-WRmgSK6L.cjs → runCodex-CdjzG1N7.cjs} +113 -25
  20. package/dist/{runCodex-CsfUU1Wb.mjs → runCodex-DT7g4MPm.mjs} +111 -26
  21. package/dist/{runGemini-CrH3dQ0Y.mjs → runGemini-CmY5386l.mjs} +55 -21
  22. package/dist/{runGemini-qBh6zs5G.cjs → runGemini-DxjvRmOc.cjs} +55 -21
  23. package/package.json +2 -1
@@ -1,8 +1,8 @@
1
1
  'use strict';
2
2
 
3
3
  var chalk = require('chalk');
4
- var api = require('./api-D9dIR956.cjs');
5
- var persistence = require('./persistence-PzKU0QCa.cjs');
4
+ var api = require('./api-DaqnNHfl.cjs');
5
+ var persistence = require('./persistence-D6Y0604_.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-LYPXVO_L.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-Dc92gnxM.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-LYPXVO_L.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-Dc92gnxM.cjs', document.baseURI).href))));
697
697
  function projectPath() {
698
698
  const path$1 = path.resolve(__dirname$1, "..");
699
699
  return path$1;
@@ -4527,6 +4527,107 @@ function parseArgsFromContent(content) {
4527
4527
  }
4528
4528
  return {};
4529
4529
  }
4530
+ function appendToolOutput(existing, next) {
4531
+ if (!existing || existing.length === 0) {
4532
+ return next;
4533
+ }
4534
+ if (next === existing || existing.endsWith(next)) {
4535
+ return existing;
4536
+ }
4537
+ if (next.startsWith(existing)) {
4538
+ return next;
4539
+ }
4540
+ return `${existing}${next}`;
4541
+ }
4542
+ function isRecord(value) {
4543
+ return typeof value === "object" && value !== null && !Array.isArray(value);
4544
+ }
4545
+ function hasMeaningfulContent(value) {
4546
+ if (value === null || value === void 0) {
4547
+ return false;
4548
+ }
4549
+ if (typeof value === "string") {
4550
+ return value.length > 0;
4551
+ }
4552
+ if (Array.isArray(value)) {
4553
+ return value.length > 0;
4554
+ }
4555
+ if (isRecord(value)) {
4556
+ return Object.keys(value).length > 0;
4557
+ }
4558
+ return true;
4559
+ }
4560
+ function looksLikeToolMetadata(record) {
4561
+ const metadataKeys = [
4562
+ "command",
4563
+ "cmd",
4564
+ "script",
4565
+ "argv",
4566
+ "cwd",
4567
+ "workingDirectory",
4568
+ "description",
4569
+ "title",
4570
+ "parsed_cmd"
4571
+ ];
4572
+ if (metadataKeys.some((key) => key in record)) {
4573
+ return true;
4574
+ }
4575
+ const nestedKeys = ["input", "toolCall", "arguments", "content"];
4576
+ for (const key of nestedKeys) {
4577
+ const nested = record[key];
4578
+ if (isRecord(nested) && looksLikeToolMetadata(nested)) {
4579
+ return true;
4580
+ }
4581
+ }
4582
+ return false;
4583
+ }
4584
+ function extractToolOutputChunk(content) {
4585
+ if (typeof content === "string") {
4586
+ return content.length > 0 ? content : null;
4587
+ }
4588
+ if (Array.isArray(content)) {
4589
+ const parts = content.map((item) => extractToolOutputChunk(item)).filter((item) => Boolean(item));
4590
+ return parts.length > 0 ? parts.join("") : null;
4591
+ }
4592
+ if (!isRecord(content)) {
4593
+ return null;
4594
+ }
4595
+ const outputKeys = ["stdout", "stderr", "output", "text", "message", "data", "error", "reason"];
4596
+ const hasOutputKey = outputKeys.some((key) => key in content);
4597
+ if (!hasOutputKey && looksLikeToolMetadata(content)) {
4598
+ return null;
4599
+ }
4600
+ for (const key of outputKeys) {
4601
+ if (!(key in content)) {
4602
+ continue;
4603
+ }
4604
+ const value = content[key];
4605
+ const formatted2 = typeof value === "string" ? value : formatDisplayMessage(value);
4606
+ if (formatted2.length > 0) {
4607
+ return formatted2;
4608
+ }
4609
+ }
4610
+ const formatted = formatDisplayMessage(content);
4611
+ return formatted.length > 0 ? formatted : null;
4612
+ }
4613
+ function mergeStreamedOutputWithResult(content, streamedOutput) {
4614
+ if (!streamedOutput || streamedOutput.length === 0) {
4615
+ return content;
4616
+ }
4617
+ if (!hasMeaningfulContent(content)) {
4618
+ return streamedOutput;
4619
+ }
4620
+ if (isRecord(content)) {
4621
+ const hasStructuredOutput = ["stdout", "stderr", "output", "text", "message", "data"].some((key) => key in content);
4622
+ if (!hasStructuredOutput) {
4623
+ return {
4624
+ ...content,
4625
+ stdout: streamedOutput
4626
+ };
4627
+ }
4628
+ }
4629
+ return content;
4630
+ }
4530
4631
  function extractErrorDetail(content) {
4531
4632
  if (!content) return void 0;
4532
4633
  if (typeof content === "string") {
@@ -4674,11 +4775,13 @@ function completeToolCall(toolCallId, toolKind, content, ctx) {
4674
4775
  clearTimeout(timeout);
4675
4776
  ctx.toolCallTimeouts.delete(toolCallId);
4676
4777
  }
4778
+ const streamedOutput = ctx.toolCallOutputs.get(toolCallId);
4779
+ ctx.toolCallOutputs.delete(toolCallId);
4677
4780
  api.logger.debug(`[AcpBackend] \u2705 Tool call COMPLETED: ${toolCallId} (${toolKindStr}) - Duration: ${duration}. Active tool calls: ${ctx.activeToolCalls.size}`);
4678
4781
  ctx.emit({
4679
4782
  type: "tool-result",
4680
4783
  toolName: toolKindStr,
4681
- result: content,
4784
+ result: mergeStreamedOutputWithResult(content, streamedOutput),
4682
4785
  callId: toolCallId
4683
4786
  });
4684
4787
  if (ctx.activeToolCalls.size === 0) {
@@ -4720,6 +4823,8 @@ function failToolCall(toolCallId, status, toolKind, content, ctx) {
4720
4823
  }
4721
4824
  const durationStr = formatDuration(startTime);
4722
4825
  api.logger.debug(`[AcpBackend] \u274C Tool call ${status.toUpperCase()}: ${toolCallId} (${toolKindStr}) - Duration: ${durationStr}. Active tool calls: ${ctx.activeToolCalls.size}`);
4826
+ const streamedOutput = ctx.toolCallOutputs.get(toolCallId);
4827
+ ctx.toolCallOutputs.delete(toolCallId);
4723
4828
  const errorDetail = extractErrorDetail(content);
4724
4829
  if (errorDetail) {
4725
4830
  api.logger.debug(`[AcpBackend] \u274C Tool call error details: ${errorDetail.substring(0, 500)}`);
@@ -4729,7 +4834,11 @@ function failToolCall(toolCallId, status, toolKind, content, ctx) {
4729
4834
  ctx.emit({
4730
4835
  type: "tool-result",
4731
4836
  toolName: toolKindStr,
4732
- result: errorDetail ? { error: errorDetail, status } : { error: `Tool call ${status}`, status },
4837
+ result: streamedOutput ? {
4838
+ stdout: streamedOutput,
4839
+ error: errorDetail || `Tool call ${status}`,
4840
+ status
4841
+ } : errorDetail ? { error: errorDetail, status } : { error: `Tool call ${status}`, status },
4733
4842
  callId: toolCallId
4734
4843
  });
4735
4844
  if (ctx.activeToolCalls.size === 0) {
@@ -4745,8 +4854,13 @@ function handleToolCallUpdate(update, ctx) {
4745
4854
  api.logger.debug("[AcpBackend] Tool call update without toolCallId:", update);
4746
4855
  return { handled: false };
4747
4856
  }
4748
- const toolKind = update.kind || "unknown";
4857
+ const toolKind = update.kind || ctx.toolCallIdToNameMap.get(toolCallId) || "unknown";
4749
4858
  let toolCallCountSincePrompt = ctx.toolCallCountSincePrompt;
4859
+ const outputChunk = extractToolOutputChunk(update.content);
4860
+ if (outputChunk) {
4861
+ const nextOutput = appendToolOutput(ctx.toolCallOutputs.get(toolCallId), outputChunk);
4862
+ ctx.toolCallOutputs.set(toolCallId, nextOutput);
4863
+ }
4750
4864
  if (status === "in_progress" || status === "pending") {
4751
4865
  if (!ctx.activeToolCalls.has(toolCallId)) {
4752
4866
  toolCallCountSincePrompt++;
@@ -4950,15 +5064,17 @@ async function withRetry(operation, options) {
4950
5064
  return await operation();
4951
5065
  } catch (error) {
4952
5066
  lastError = normalizeAcpError(error);
4953
- if (attempt < options.maxAttempts) {
4954
- const delayMs = Math.min(
4955
- options.baseDelayMs * Math.pow(2, attempt - 1),
4956
- options.maxDelayMs
4957
- );
4958
- api.logger.debug(`[AcpBackend] ${options.operationName} failed (attempt ${attempt}/${options.maxAttempts}): ${lastError.message}. Retrying in ${delayMs}ms...`);
4959
- options.onRetry?.(attempt, lastError);
4960
- await api.delay(delayMs);
5067
+ const retryable = options.shouldRetry?.(lastError) ?? true;
5068
+ if (!retryable || attempt >= options.maxAttempts) {
5069
+ throw lastError;
4961
5070
  }
5071
+ const delayMs = Math.min(
5072
+ options.baseDelayMs * Math.pow(2, attempt - 1),
5073
+ options.maxDelayMs
5074
+ );
5075
+ api.logger.debug(`[AcpBackend] ${options.operationName} failed (attempt ${attempt}/${options.maxAttempts}): ${lastError.message}. Retrying in ${delayMs}ms...`);
5076
+ options.onRetry?.(attempt, lastError);
5077
+ await api.delay(delayMs);
4962
5078
  }
4963
5079
  }
4964
5080
  throw lastError;
@@ -4995,6 +5111,11 @@ function normalizeAcpError(error) {
4995
5111
  }
4996
5112
  return normalized;
4997
5113
  }
5114
+ function createAcpAbortError(message) {
5115
+ const error = new Error(message);
5116
+ error.name = "AbortError";
5117
+ return error;
5118
+ }
4998
5119
  function enrichAcpError(error, stderrExcerpt) {
4999
5120
  const normalized = normalizeAcpError(error);
5000
5121
  if (!stderrExcerpt.trim()) {
@@ -5006,6 +5127,77 @@ function enrichAcpError(error, stderrExcerpt) {
5006
5127
  }
5007
5128
  return normalized;
5008
5129
  }
5130
+ class AcpProcessStartupError extends Error {
5131
+ constructor(message, exitCode, signal) {
5132
+ super(message);
5133
+ this.exitCode = exitCode;
5134
+ this.signal = signal;
5135
+ this.name = "AcpProcessStartupError";
5136
+ }
5137
+ }
5138
+ function createProcessStartupError(agentName, operationName, code, signal) {
5139
+ if (code !== null) {
5140
+ return new AcpProcessStartupError(
5141
+ `${agentName} exited with code ${code} during ${operationName}`,
5142
+ code,
5143
+ signal
5144
+ );
5145
+ }
5146
+ if (signal) {
5147
+ return new AcpProcessStartupError(
5148
+ `${agentName} exited due to signal ${signal} during ${operationName}`,
5149
+ code,
5150
+ signal
5151
+ );
5152
+ }
5153
+ return new AcpProcessStartupError(
5154
+ `${agentName} exited unexpectedly during ${operationName}`,
5155
+ code,
5156
+ signal
5157
+ );
5158
+ }
5159
+ async function raceWithProcessExit(childProcess, operation, options) {
5160
+ if (childProcess.exitCode !== null) {
5161
+ throw createProcessStartupError(
5162
+ options.agentName,
5163
+ options.operationName,
5164
+ childProcess.exitCode,
5165
+ childProcess.signalCode ?? null
5166
+ );
5167
+ }
5168
+ return await new Promise((resolve, reject) => {
5169
+ let settled = false;
5170
+ const cleanup = () => {
5171
+ childProcess.off("error", handleError);
5172
+ childProcess.off("exit", handleExit);
5173
+ };
5174
+ const settleResolve = (value) => {
5175
+ if (settled) {
5176
+ return;
5177
+ }
5178
+ settled = true;
5179
+ cleanup();
5180
+ resolve(value);
5181
+ };
5182
+ const settleReject = (error) => {
5183
+ if (settled) {
5184
+ return;
5185
+ }
5186
+ settled = true;
5187
+ cleanup();
5188
+ reject(normalizeAcpError(error));
5189
+ };
5190
+ const handleError = (error) => {
5191
+ settleReject(error);
5192
+ };
5193
+ const handleExit = (code, signal) => {
5194
+ settleReject(createProcessStartupError(options.agentName, options.operationName, code, signal));
5195
+ };
5196
+ childProcess.once("error", handleError);
5197
+ childProcess.once("exit", handleExit);
5198
+ operation.then(settleResolve, settleReject);
5199
+ });
5200
+ }
5009
5201
  class AcpBackend {
5010
5202
  constructor(options) {
5011
5203
  this.options = options;
@@ -5021,6 +5213,8 @@ class AcpBackend {
5021
5213
  toolCallTimeouts = /* @__PURE__ */ new Map();
5022
5214
  /** Track tool call start times for performance monitoring */
5023
5215
  toolCallStartTimes = /* @__PURE__ */ new Map();
5216
+ /** Track streamed tool output between ACP updates and final completion */
5217
+ toolCallOutputs = /* @__PURE__ */ new Map();
5024
5218
  /** Pending permission requests that need response */
5025
5219
  pendingPermissions = /* @__PURE__ */ new Map();
5026
5220
  /** Map from permission request ID to real tool call ID for tracking */
@@ -5031,6 +5225,14 @@ class AcpBackend {
5031
5225
  toolCallCountSincePrompt = 0;
5032
5226
  /** Timeout for emitting 'idle' status after last message chunk */
5033
5227
  idleTimeout = null;
5228
+ /** Promise resolver for waitForResponseComplete */
5229
+ idleResolver = null;
5230
+ /** Promise rejecter for waitForResponseComplete */
5231
+ idleRejecter = null;
5232
+ /** Completion signal captured before waitForResponseComplete is attached */
5233
+ responseCompletionOutcome = null;
5234
+ /** Whether the current prompt is still waiting for completion */
5235
+ waitingForResponse = false;
5034
5236
  /** Transport handler for agent-specific behavior */
5035
5237
  transport;
5036
5238
  /** Keep a short rolling stderr buffer so startup failures can surface the real cause. */
@@ -5048,6 +5250,44 @@ class AcpBackend {
5048
5250
  getRecentStderrExcerpt() {
5049
5251
  return this.recentStderrLines.slice(-6).join("\n");
5050
5252
  }
5253
+ clearIdleTimeoutState() {
5254
+ if (this.idleTimeout) {
5255
+ clearTimeout(this.idleTimeout);
5256
+ this.idleTimeout = null;
5257
+ }
5258
+ }
5259
+ clearToolCallTracking() {
5260
+ this.activeToolCalls.clear();
5261
+ for (const timeout of this.toolCallTimeouts.values()) {
5262
+ clearTimeout(timeout);
5263
+ }
5264
+ this.toolCallTimeouts.clear();
5265
+ this.toolCallStartTimes.clear();
5266
+ this.toolCallIdToNameMap.clear();
5267
+ this.toolCallOutputs.clear();
5268
+ this.toolCallCountSincePrompt = 0;
5269
+ }
5270
+ resetResponseTrackingForNewPrompt() {
5271
+ this.responseCompletionOutcome = null;
5272
+ this.clearIdleTimeoutState();
5273
+ this.clearToolCallTracking();
5274
+ }
5275
+ settleResponseWaiter(outcome) {
5276
+ const hasActiveWaiter = Boolean(this.idleResolver || this.idleRejecter);
5277
+ if (!this.waitingForResponse && !hasActiveWaiter) {
5278
+ return;
5279
+ }
5280
+ if (!hasActiveWaiter) {
5281
+ this.waitingForResponse = false;
5282
+ this.responseCompletionOutcome = outcome;
5283
+ return;
5284
+ }
5285
+ if (outcome.kind === "resolved") {
5286
+ this.idleResolver?.();
5287
+ return;
5288
+ }
5289
+ this.idleRejecter?.(outcome.error);
5290
+ }
5051
5291
  onMessage(handler) {
5052
5292
  this.listeners.push(handler);
5053
5293
  }
@@ -5122,10 +5362,15 @@ class AcpBackend {
5122
5362
  });
5123
5363
  this.process.on("error", (err) => {
5124
5364
  api.logger.debug(`[AcpBackend] Process error:`, err);
5365
+ this.settleResponseWaiter({ kind: "rejected", error: err });
5125
5366
  this.emit({ type: "status", status: "error", detail: err.message });
5126
5367
  });
5127
5368
  this.process.on("exit", (code, signal) => {
5128
5369
  if (!this.disposed && code !== 0 && code !== null) {
5370
+ this.settleResponseWaiter({
5371
+ kind: "rejected",
5372
+ error: new Error(`ACP process exited with code ${code}${signal ? ` (${signal})` : ""}`)
5373
+ });
5129
5374
  api.logger.debug(`[AcpBackend] Process exited with code ${code}, signal ${signal}`);
5130
5375
  this.emit({ type: "status", status: "stopped", detail: `Exit code: ${code}` });
5131
5376
  }
@@ -5353,20 +5598,27 @@ class AcpBackend {
5353
5598
  async () => {
5354
5599
  let timeoutHandle = null;
5355
5600
  try {
5356
- const result = await Promise.race([
5357
- this.connection.initialize(initRequest).then((res) => {
5358
- if (timeoutHandle) {
5359
- clearTimeout(timeoutHandle);
5360
- timeoutHandle = null;
5361
- }
5362
- return res;
5363
- }),
5364
- new Promise((_, reject) => {
5365
- timeoutHandle = setTimeout(() => {
5366
- reject(new Error(`Initialize timeout after ${initTimeout}ms - ${this.transport.agentName} did not respond`));
5367
- }, initTimeout);
5368
- })
5369
- ]);
5601
+ const result = await raceWithProcessExit(
5602
+ this.process,
5603
+ Promise.race([
5604
+ this.connection.initialize(initRequest).then((res) => {
5605
+ if (timeoutHandle) {
5606
+ clearTimeout(timeoutHandle);
5607
+ timeoutHandle = null;
5608
+ }
5609
+ return res;
5610
+ }),
5611
+ new Promise((_, reject) => {
5612
+ timeoutHandle = setTimeout(() => {
5613
+ reject(new Error(`Initialize timeout after ${initTimeout}ms - ${this.transport.agentName} did not respond`));
5614
+ }, initTimeout);
5615
+ })
5616
+ ]),
5617
+ {
5618
+ agentName: this.transport.agentName,
5619
+ operationName: "initialize"
5620
+ }
5621
+ );
5370
5622
  return result;
5371
5623
  } finally {
5372
5624
  if (timeoutHandle) {
@@ -5378,7 +5630,8 @@ class AcpBackend {
5378
5630
  operationName: "Initialize",
5379
5631
  maxAttempts: RETRY_CONFIG.maxAttempts,
5380
5632
  baseDelayMs: RETRY_CONFIG.baseDelayMs,
5381
- maxDelayMs: RETRY_CONFIG.maxDelayMs
5633
+ maxDelayMs: RETRY_CONFIG.maxDelayMs,
5634
+ shouldRetry: (error) => !(error instanceof AcpProcessStartupError)
5382
5635
  }
5383
5636
  );
5384
5637
  api.logger.debug(`[AcpBackend] Initialize completed`);
@@ -5397,20 +5650,27 @@ class AcpBackend {
5397
5650
  async () => {
5398
5651
  let timeoutHandle = null;
5399
5652
  try {
5400
- const result = await Promise.race([
5401
- this.connection.newSession(newSessionRequest).then((res) => {
5402
- if (timeoutHandle) {
5403
- clearTimeout(timeoutHandle);
5404
- timeoutHandle = null;
5405
- }
5406
- return res;
5407
- }),
5408
- new Promise((_, reject) => {
5409
- timeoutHandle = setTimeout(() => {
5410
- reject(new Error(`New session timeout after ${initTimeout}ms - ${this.transport.agentName} did not respond`));
5411
- }, initTimeout);
5412
- })
5413
- ]);
5653
+ const result = await raceWithProcessExit(
5654
+ this.process,
5655
+ Promise.race([
5656
+ this.connection.newSession(newSessionRequest).then((res) => {
5657
+ if (timeoutHandle) {
5658
+ clearTimeout(timeoutHandle);
5659
+ timeoutHandle = null;
5660
+ }
5661
+ return res;
5662
+ }),
5663
+ new Promise((_, reject) => {
5664
+ timeoutHandle = setTimeout(() => {
5665
+ reject(new Error(`New session timeout after ${initTimeout}ms - ${this.transport.agentName} did not respond`));
5666
+ }, initTimeout);
5667
+ })
5668
+ ]),
5669
+ {
5670
+ agentName: this.transport.agentName,
5671
+ operationName: "new session"
5672
+ }
5673
+ );
5414
5674
  return result;
5415
5675
  } finally {
5416
5676
  if (timeoutHandle) {
@@ -5422,7 +5682,8 @@ class AcpBackend {
5422
5682
  operationName: "NewSession",
5423
5683
  maxAttempts: RETRY_CONFIG.maxAttempts,
5424
5684
  baseDelayMs: RETRY_CONFIG.baseDelayMs,
5425
- maxDelayMs: RETRY_CONFIG.maxDelayMs
5685
+ maxDelayMs: RETRY_CONFIG.maxDelayMs,
5686
+ shouldRetry: (error) => !(error instanceof AcpProcessStartupError)
5426
5687
  }
5427
5688
  );
5428
5689
  this.acpSessionId = sessionResponse.sessionId;
@@ -5456,6 +5717,7 @@ class AcpBackend {
5456
5717
  toolCallStartTimes: this.toolCallStartTimes,
5457
5718
  toolCallTimeouts: this.toolCallTimeouts,
5458
5719
  toolCallIdToNameMap: this.toolCallIdToNameMap,
5720
+ toolCallOutputs: this.toolCallOutputs,
5459
5721
  idleTimeout: this.idleTimeout,
5460
5722
  toolCallCountSincePrompt: this.toolCallCountSincePrompt,
5461
5723
  emit: (msg) => this.emit(msg),
@@ -5532,20 +5794,24 @@ class AcpBackend {
5532
5794
  this.emitUsageTelemetry(update, "acp-usage-update");
5533
5795
  continue;
5534
5796
  }
5797
+ if (sessionUpdateType === "task_complete") {
5798
+ this.emitUsageTelemetry(update.usage, "acp-session-usage");
5799
+ ctx.clearIdleTimeout();
5800
+ api.logger.debug("[AcpBackend] task_complete received, emitting idle status");
5801
+ this.emitIdleStatus();
5802
+ continue;
5803
+ }
5535
5804
  const handledLegacy = handleLegacyMessageChunk(update, ctx).handled;
5536
5805
  const handledPlan = handlePlanUpdate(update, ctx).handled;
5537
5806
  const handledThinking = handleThinkingUpdate(update, ctx).handled;
5538
5807
  const handledUsage = this.emitUsageTelemetry(update.usage, "acp-session-usage");
5539
5808
  const updateTypeStr = sessionUpdateType;
5540
- const handledTypes = ["agent_message_chunk", "tool_call_update", "agent_thought_chunk", "tool_call", "usage_update"];
5809
+ const handledTypes = ["agent_message_chunk", "tool_call_update", "agent_thought_chunk", "tool_call", "usage_update", "task_complete"];
5541
5810
  if (updateTypeStr && !handledTypes.includes(updateTypeStr) && !handledLegacy && !handledPlan && !handledThinking && !handledUsage) {
5542
5811
  api.logger.debug(`[AcpBackend] Unhandled session update type: ${updateTypeStr}`, JSON.stringify(update, null, 2));
5543
5812
  }
5544
5813
  }
5545
5814
  }
5546
- // Promise resolver for waitForIdle - set when waiting for response to complete
5547
- idleResolver = null;
5548
- waitingForResponse = false;
5549
5815
  async sendPrompt(sessionId, prompt) {
5550
5816
  this.toolCallCountSincePrompt = 0;
5551
5817
  if (this.disposed) {
@@ -5554,6 +5820,7 @@ class AcpBackend {
5554
5820
  if (!this.connection || !this.acpSessionId) {
5555
5821
  throw new Error("Session not started");
5556
5822
  }
5823
+ this.resetResponseTrackingForNewPrompt();
5557
5824
  this.emit({ type: "status", status: "running" });
5558
5825
  this.waitingForResponse = true;
5559
5826
  try {
@@ -5572,7 +5839,6 @@ class AcpBackend {
5572
5839
  api.logger.debug("[AcpBackend] Prompt request sent to ACP connection");
5573
5840
  } catch (error) {
5574
5841
  api.logger.debug("[AcpBackend] Error sending prompt:", error);
5575
- this.waitingForResponse = false;
5576
5842
  let errorDetail;
5577
5843
  if (error instanceof Error) {
5578
5844
  errorDetail = error.message;
@@ -5586,6 +5852,10 @@ class AcpBackend {
5586
5852
  status: "error",
5587
5853
  detail: errorDetail
5588
5854
  });
5855
+ this.settleResponseWaiter({
5856
+ kind: "rejected",
5857
+ error: error instanceof Error ? error : normalizeAcpError(error)
5858
+ });
5589
5859
  throw error;
5590
5860
  }
5591
5861
  }
@@ -5594,21 +5864,38 @@ class AcpBackend {
5594
5864
  * Call this after sendPrompt to wait for Gemini to finish responding
5595
5865
  */
5596
5866
  async waitForResponseComplete(timeoutMs = 12e4) {
5867
+ const pendingOutcome = this.responseCompletionOutcome;
5868
+ if (pendingOutcome) {
5869
+ this.responseCompletionOutcome = null;
5870
+ if (pendingOutcome.kind === "rejected") {
5871
+ throw pendingOutcome.error;
5872
+ }
5873
+ return;
5874
+ }
5597
5875
  if (!this.waitingForResponse) {
5598
5876
  return;
5599
5877
  }
5600
5878
  return new Promise((resolve, reject) => {
5601
5879
  const timeout = setTimeout(() => {
5602
5880
  this.idleResolver = null;
5881
+ this.idleRejecter = null;
5603
5882
  this.waitingForResponse = false;
5604
5883
  reject(new Error("Timeout waiting for response to complete"));
5605
5884
  }, timeoutMs);
5606
5885
  this.idleResolver = () => {
5607
5886
  clearTimeout(timeout);
5608
5887
  this.idleResolver = null;
5888
+ this.idleRejecter = null;
5609
5889
  this.waitingForResponse = false;
5610
5890
  resolve();
5611
5891
  };
5892
+ this.idleRejecter = (error) => {
5893
+ clearTimeout(timeout);
5894
+ this.idleResolver = null;
5895
+ this.idleRejecter = null;
5896
+ this.waitingForResponse = false;
5897
+ reject(error);
5898
+ };
5612
5899
  });
5613
5900
  }
5614
5901
  /**
@@ -5616,18 +5903,19 @@ class AcpBackend {
5616
5903
  */
5617
5904
  emitIdleStatus() {
5618
5905
  this.emit({ type: "status", status: "idle" });
5619
- if (this.idleResolver) {
5620
- api.logger.debug("[AcpBackend] Resolving idle waiter");
5621
- this.idleResolver();
5622
- }
5906
+ this.settleResponseWaiter({ kind: "resolved" });
5623
5907
  }
5624
5908
  async cancel(sessionId) {
5909
+ const cancelError = createAcpAbortError("Cancelled by user");
5910
+ this.clearIdleTimeoutState();
5911
+ this.clearToolCallTracking();
5912
+ this.settleResponseWaiter({ kind: "rejected", error: cancelError });
5913
+ this.emit({ type: "status", status: "stopped", detail: "Cancelled by user" });
5625
5914
  if (!this.connection || !this.acpSessionId) {
5626
5915
  return;
5627
5916
  }
5628
5917
  try {
5629
5918
  await this.connection.cancel({ sessionId: this.acpSessionId });
5630
- this.emit({ type: "status", status: "stopped", detail: "Cancelled by user" });
5631
5919
  } catch (error) {
5632
5920
  api.logger.debug("[AcpBackend] Error cancelling:", error);
5633
5921
  }
@@ -5655,6 +5943,10 @@ class AcpBackend {
5655
5943
  if (this.disposed) return;
5656
5944
  api.logger.debug("[AcpBackend] Disposing backend");
5657
5945
  this.disposed = true;
5946
+ this.settleResponseWaiter({
5947
+ kind: "rejected",
5948
+ error: createAcpAbortError("ACP backend disposed")
5949
+ });
5658
5950
  if (this.connection && this.acpSessionId) {
5659
5951
  try {
5660
5952
  await Promise.race([
@@ -5683,19 +5975,11 @@ class AcpBackend {
5683
5975
  });
5684
5976
  this.process = null;
5685
5977
  }
5686
- if (this.idleTimeout) {
5687
- clearTimeout(this.idleTimeout);
5688
- this.idleTimeout = null;
5689
- }
5978
+ this.clearIdleTimeoutState();
5690
5979
  this.listeners = [];
5691
5980
  this.connection = null;
5692
5981
  this.acpSessionId = null;
5693
- this.activeToolCalls.clear();
5694
- for (const timeout of this.toolCallTimeouts.values()) {
5695
- clearTimeout(timeout);
5696
- }
5697
- this.toolCallTimeouts.clear();
5698
- this.toolCallStartTimes.clear();
5982
+ this.clearToolCallTracking();
5699
5983
  this.pendingPermissions.clear();
5700
5984
  }
5701
5985
  }
@@ -5930,6 +6214,7 @@ function registerGeminiAgent() {
5930
6214
  api.logger.debug("[Gemini] Registered with agent registry");
5931
6215
  }
5932
6216
 
6217
+ const DEFAULT_CODEX_ACP_NPX_PACKAGE = "@zed-industries/codex-acp@0.9.5";
5933
6218
  function readFirstEnv(...names) {
5934
6219
  for (const name of names) {
5935
6220
  const raw = process.env[name];
@@ -5984,6 +6269,10 @@ function readCodexAcpNpxMode() {
5984
6269
  }
5985
6270
  return "auto";
5986
6271
  }
6272
+ function readCodexAcpNpxPackage() {
6273
+ const configured = readFirstEnv("HAPPY_CODEX_ACP_PACKAGE", "HAPPIER_CODEX_ACP_PACKAGE");
6274
+ return configured || DEFAULT_CODEX_ACP_NPX_PACKAGE;
6275
+ }
5987
6276
  function isBinOnPath(baseName) {
5988
6277
  return resolveCommandOnPath(baseName) !== null;
5989
6278
  }
@@ -6049,7 +6338,7 @@ function resolveCodexAcpSpawn(options = {}) {
6049
6338
  }
6050
6339
  return {
6051
6340
  command: resolveNpxCommand(),
6052
- args: ["--prefer-offline", "-y", "@zed-industries/codex-acp", ...directArgs]
6341
+ args: ["--prefer-offline", "-y", readCodexAcpNpxPackage(), ...directArgs]
6053
6342
  };
6054
6343
  }
6055
6344
  function validateCodexAcpSpawn(options = {}) {
@@ -6336,12 +6625,12 @@ async function ensureUnifiedDaemonStarted() {
6336
6625
  async function executeUnifiedProvider(opts) {
6337
6626
  const credentials = await ensureUnifiedRuntimePrerequisites(opts.credentials);
6338
6627
  if (opts.provider === "claude") {
6339
- const { runClaude } = await Promise.resolve().then(function () { return require('./runClaude-IeRSC5qX.cjs'); });
6628
+ const { runClaude } = await Promise.resolve().then(function () { return require('./runClaude-gHKFB1UG.cjs'); });
6340
6629
  await runClaude(credentials, opts.claudeOptions ?? {});
6341
6630
  return;
6342
6631
  }
6343
6632
  if (opts.provider === "codex") {
6344
- const { runCodex } = await Promise.resolve().then(function () { return require('./runCodex-WRmgSK6L.cjs'); });
6633
+ const { runCodex } = await Promise.resolve().then(function () { return require('./runCodex-CdjzG1N7.cjs'); });
6345
6634
  await runCodex({
6346
6635
  credentials,
6347
6636
  startedBy: opts.startedBy,
@@ -6351,7 +6640,7 @@ async function executeUnifiedProvider(opts) {
6351
6640
  return;
6352
6641
  }
6353
6642
  if (opts.provider === "gemini") {
6354
- const { runGemini } = await Promise.resolve().then(function () { return require('./runGemini-qBh6zs5G.cjs'); });
6643
+ const { runGemini } = await Promise.resolve().then(function () { return require('./runGemini-DxjvRmOc.cjs'); });
6355
6644
  await runGemini({
6356
6645
  credentials,
6357
6646
  startedBy: opts.startedBy
@@ -6393,7 +6682,7 @@ function shouldRunMainClaudeFlow(opts) {
6393
6682
  return;
6394
6683
  } else if (subcommand === "runtime") {
6395
6684
  if (args[1] === "providers") {
6396
- const { renderRuntimeProviders } = await Promise.resolve().then(function () { return require('./command-CdXv1zNF.cjs'); });
6685
+ const { renderRuntimeProviders } = await Promise.resolve().then(function () { return require('./command-D9-hmqVq.cjs'); });
6397
6686
  console.log(renderRuntimeProviders());
6398
6687
  return;
6399
6688
  }
@@ -6571,8 +6860,8 @@ function shouldRunMainClaudeFlow(opts) {
6571
6860
  const projectId = args[3];
6572
6861
  try {
6573
6862
  const { saveGoogleCloudProjectToConfig } = await Promise.resolve().then(function () { return config; });
6574
- const { readCredentials: readCredentials2 } = await Promise.resolve().then(function () { return require('./persistence-PzKU0QCa.cjs'); });
6575
- const { ApiClient: ApiClient2 } = await Promise.resolve().then(function () { return require('./api-D9dIR956.cjs'); }).then(function (n) { return n.api; });
6863
+ const { readCredentials: readCredentials2 } = await Promise.resolve().then(function () { return require('./persistence-D6Y0604_.cjs'); });
6864
+ const { ApiClient: ApiClient2 } = await Promise.resolve().then(function () { return require('./api-DaqnNHfl.cjs'); }).then(function (n) { return n.api; });
6576
6865
  let userEmail = void 0;
6577
6866
  try {
6578
6867
  const credentials = await readCredentials2();