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,6 +1,6 @@
1
1
  import{createRequire as _pkgrollCR}from"node:module";const require=_pkgrollCR(import.meta.url);import chalk from 'chalk';
2
- import { l as logger, e as encodeBase64, c as configuration, h as buildAuthenticatedHeaders, S as SigningBootstrapRequiredError, j as SIGNING_BOOTSTRAP_REQUIRED_MESSAGE, k as encodeBase64Url, f as delay, m as buildClientHeaders, n as decodeBase64, H as HAPPY_CLOUD_DAEMON_PORT, p as packageJson, A as ApiClient, o as getLatestDaemonLog } from './api-DpQIC-DJ.mjs';
3
- import { writeCredentialsLegacy, writeCredentialsDataKey, readCredentials, readSettings, updateSettings, readDaemonState, clearDaemonState, acquireDaemonLock, writeDaemonState, releaseDaemonLock, validateProfileForAgent, getProfileEnvironmentVariables, clearCredentials, clearMachineId } from './persistence-CqgPgbzN.mjs';
2
+ import { l as logger, e as encodeBase64, c as configuration, h as buildAuthenticatedHeaders, S as SigningBootstrapRequiredError, j as SIGNING_BOOTSTRAP_REQUIRED_MESSAGE, k as encodeBase64Url, f as delay, m as buildClientHeaders, n as decodeBase64, H as HAPPY_CLOUD_DAEMON_PORT, p as packageJson, A as ApiClient, o as getLatestDaemonLog } from './api-DoHt-HyL.mjs';
3
+ import { writeCredentialsLegacy, writeCredentialsDataKey, readCredentials, readSettings, updateSettings, readDaemonState, clearDaemonState, acquireDaemonLock, writeDaemonState, releaseDaemonLock, validateProfileForAgent, getProfileEnvironmentVariables, clearCredentials, clearMachineId } from './persistence-QqeBvUxX.mjs';
4
4
  import { z } from 'zod';
5
5
  import fs from 'fs/promises';
6
6
  import os, { homedir } from 'os';
@@ -4505,6 +4505,107 @@ function parseArgsFromContent(content) {
4505
4505
  }
4506
4506
  return {};
4507
4507
  }
4508
+ function appendToolOutput(existing, next) {
4509
+ if (!existing || existing.length === 0) {
4510
+ return next;
4511
+ }
4512
+ if (next === existing || existing.endsWith(next)) {
4513
+ return existing;
4514
+ }
4515
+ if (next.startsWith(existing)) {
4516
+ return next;
4517
+ }
4518
+ return `${existing}${next}`;
4519
+ }
4520
+ function isRecord(value) {
4521
+ return typeof value === "object" && value !== null && !Array.isArray(value);
4522
+ }
4523
+ function hasMeaningfulContent(value) {
4524
+ if (value === null || value === void 0) {
4525
+ return false;
4526
+ }
4527
+ if (typeof value === "string") {
4528
+ return value.length > 0;
4529
+ }
4530
+ if (Array.isArray(value)) {
4531
+ return value.length > 0;
4532
+ }
4533
+ if (isRecord(value)) {
4534
+ return Object.keys(value).length > 0;
4535
+ }
4536
+ return true;
4537
+ }
4538
+ function looksLikeToolMetadata(record) {
4539
+ const metadataKeys = [
4540
+ "command",
4541
+ "cmd",
4542
+ "script",
4543
+ "argv",
4544
+ "cwd",
4545
+ "workingDirectory",
4546
+ "description",
4547
+ "title",
4548
+ "parsed_cmd"
4549
+ ];
4550
+ if (metadataKeys.some((key) => key in record)) {
4551
+ return true;
4552
+ }
4553
+ const nestedKeys = ["input", "toolCall", "arguments", "content"];
4554
+ for (const key of nestedKeys) {
4555
+ const nested = record[key];
4556
+ if (isRecord(nested) && looksLikeToolMetadata(nested)) {
4557
+ return true;
4558
+ }
4559
+ }
4560
+ return false;
4561
+ }
4562
+ function extractToolOutputChunk(content) {
4563
+ if (typeof content === "string") {
4564
+ return content.length > 0 ? content : null;
4565
+ }
4566
+ if (Array.isArray(content)) {
4567
+ const parts = content.map((item) => extractToolOutputChunk(item)).filter((item) => Boolean(item));
4568
+ return parts.length > 0 ? parts.join("") : null;
4569
+ }
4570
+ if (!isRecord(content)) {
4571
+ return null;
4572
+ }
4573
+ const outputKeys = ["stdout", "stderr", "output", "text", "message", "data", "error", "reason"];
4574
+ const hasOutputKey = outputKeys.some((key) => key in content);
4575
+ if (!hasOutputKey && looksLikeToolMetadata(content)) {
4576
+ return null;
4577
+ }
4578
+ for (const key of outputKeys) {
4579
+ if (!(key in content)) {
4580
+ continue;
4581
+ }
4582
+ const value = content[key];
4583
+ const formatted2 = typeof value === "string" ? value : formatDisplayMessage(value);
4584
+ if (formatted2.length > 0) {
4585
+ return formatted2;
4586
+ }
4587
+ }
4588
+ const formatted = formatDisplayMessage(content);
4589
+ return formatted.length > 0 ? formatted : null;
4590
+ }
4591
+ function mergeStreamedOutputWithResult(content, streamedOutput) {
4592
+ if (!streamedOutput || streamedOutput.length === 0) {
4593
+ return content;
4594
+ }
4595
+ if (!hasMeaningfulContent(content)) {
4596
+ return streamedOutput;
4597
+ }
4598
+ if (isRecord(content)) {
4599
+ const hasStructuredOutput = ["stdout", "stderr", "output", "text", "message", "data"].some((key) => key in content);
4600
+ if (!hasStructuredOutput) {
4601
+ return {
4602
+ ...content,
4603
+ stdout: streamedOutput
4604
+ };
4605
+ }
4606
+ }
4607
+ return content;
4608
+ }
4508
4609
  function extractErrorDetail(content) {
4509
4610
  if (!content) return void 0;
4510
4611
  if (typeof content === "string") {
@@ -4652,11 +4753,13 @@ function completeToolCall(toolCallId, toolKind, content, ctx) {
4652
4753
  clearTimeout(timeout);
4653
4754
  ctx.toolCallTimeouts.delete(toolCallId);
4654
4755
  }
4756
+ const streamedOutput = ctx.toolCallOutputs.get(toolCallId);
4757
+ ctx.toolCallOutputs.delete(toolCallId);
4655
4758
  logger.debug(`[AcpBackend] \u2705 Tool call COMPLETED: ${toolCallId} (${toolKindStr}) - Duration: ${duration}. Active tool calls: ${ctx.activeToolCalls.size}`);
4656
4759
  ctx.emit({
4657
4760
  type: "tool-result",
4658
4761
  toolName: toolKindStr,
4659
- result: content,
4762
+ result: mergeStreamedOutputWithResult(content, streamedOutput),
4660
4763
  callId: toolCallId
4661
4764
  });
4662
4765
  if (ctx.activeToolCalls.size === 0) {
@@ -4698,6 +4801,8 @@ function failToolCall(toolCallId, status, toolKind, content, ctx) {
4698
4801
  }
4699
4802
  const durationStr = formatDuration(startTime);
4700
4803
  logger.debug(`[AcpBackend] \u274C Tool call ${status.toUpperCase()}: ${toolCallId} (${toolKindStr}) - Duration: ${durationStr}. Active tool calls: ${ctx.activeToolCalls.size}`);
4804
+ const streamedOutput = ctx.toolCallOutputs.get(toolCallId);
4805
+ ctx.toolCallOutputs.delete(toolCallId);
4701
4806
  const errorDetail = extractErrorDetail(content);
4702
4807
  if (errorDetail) {
4703
4808
  logger.debug(`[AcpBackend] \u274C Tool call error details: ${errorDetail.substring(0, 500)}`);
@@ -4707,7 +4812,11 @@ function failToolCall(toolCallId, status, toolKind, content, ctx) {
4707
4812
  ctx.emit({
4708
4813
  type: "tool-result",
4709
4814
  toolName: toolKindStr,
4710
- result: errorDetail ? { error: errorDetail, status } : { error: `Tool call ${status}`, status },
4815
+ result: streamedOutput ? {
4816
+ stdout: streamedOutput,
4817
+ error: errorDetail || `Tool call ${status}`,
4818
+ status
4819
+ } : errorDetail ? { error: errorDetail, status } : { error: `Tool call ${status}`, status },
4711
4820
  callId: toolCallId
4712
4821
  });
4713
4822
  if (ctx.activeToolCalls.size === 0) {
@@ -4723,8 +4832,13 @@ function handleToolCallUpdate(update, ctx) {
4723
4832
  logger.debug("[AcpBackend] Tool call update without toolCallId:", update);
4724
4833
  return { handled: false };
4725
4834
  }
4726
- const toolKind = update.kind || "unknown";
4835
+ const toolKind = update.kind || ctx.toolCallIdToNameMap.get(toolCallId) || "unknown";
4727
4836
  let toolCallCountSincePrompt = ctx.toolCallCountSincePrompt;
4837
+ const outputChunk = extractToolOutputChunk(update.content);
4838
+ if (outputChunk) {
4839
+ const nextOutput = appendToolOutput(ctx.toolCallOutputs.get(toolCallId), outputChunk);
4840
+ ctx.toolCallOutputs.set(toolCallId, nextOutput);
4841
+ }
4728
4842
  if (status === "in_progress" || status === "pending") {
4729
4843
  if (!ctx.activeToolCalls.has(toolCallId)) {
4730
4844
  toolCallCountSincePrompt++;
@@ -4928,15 +5042,17 @@ async function withRetry(operation, options) {
4928
5042
  return await operation();
4929
5043
  } catch (error) {
4930
5044
  lastError = normalizeAcpError(error);
4931
- if (attempt < options.maxAttempts) {
4932
- const delayMs = Math.min(
4933
- options.baseDelayMs * Math.pow(2, attempt - 1),
4934
- options.maxDelayMs
4935
- );
4936
- logger.debug(`[AcpBackend] ${options.operationName} failed (attempt ${attempt}/${options.maxAttempts}): ${lastError.message}. Retrying in ${delayMs}ms...`);
4937
- options.onRetry?.(attempt, lastError);
4938
- await delay(delayMs);
5045
+ const retryable = options.shouldRetry?.(lastError) ?? true;
5046
+ if (!retryable || attempt >= options.maxAttempts) {
5047
+ throw lastError;
4939
5048
  }
5049
+ const delayMs = Math.min(
5050
+ options.baseDelayMs * Math.pow(2, attempt - 1),
5051
+ options.maxDelayMs
5052
+ );
5053
+ logger.debug(`[AcpBackend] ${options.operationName} failed (attempt ${attempt}/${options.maxAttempts}): ${lastError.message}. Retrying in ${delayMs}ms...`);
5054
+ options.onRetry?.(attempt, lastError);
5055
+ await delay(delayMs);
4940
5056
  }
4941
5057
  }
4942
5058
  throw lastError;
@@ -4973,6 +5089,11 @@ function normalizeAcpError(error) {
4973
5089
  }
4974
5090
  return normalized;
4975
5091
  }
5092
+ function createAcpAbortError(message) {
5093
+ const error = new Error(message);
5094
+ error.name = "AbortError";
5095
+ return error;
5096
+ }
4976
5097
  function enrichAcpError(error, stderrExcerpt) {
4977
5098
  const normalized = normalizeAcpError(error);
4978
5099
  if (!stderrExcerpt.trim()) {
@@ -4984,6 +5105,77 @@ function enrichAcpError(error, stderrExcerpt) {
4984
5105
  }
4985
5106
  return normalized;
4986
5107
  }
5108
+ class AcpProcessStartupError extends Error {
5109
+ constructor(message, exitCode, signal) {
5110
+ super(message);
5111
+ this.exitCode = exitCode;
5112
+ this.signal = signal;
5113
+ this.name = "AcpProcessStartupError";
5114
+ }
5115
+ }
5116
+ function createProcessStartupError(agentName, operationName, code, signal) {
5117
+ if (code !== null) {
5118
+ return new AcpProcessStartupError(
5119
+ `${agentName} exited with code ${code} during ${operationName}`,
5120
+ code,
5121
+ signal
5122
+ );
5123
+ }
5124
+ if (signal) {
5125
+ return new AcpProcessStartupError(
5126
+ `${agentName} exited due to signal ${signal} during ${operationName}`,
5127
+ code,
5128
+ signal
5129
+ );
5130
+ }
5131
+ return new AcpProcessStartupError(
5132
+ `${agentName} exited unexpectedly during ${operationName}`,
5133
+ code,
5134
+ signal
5135
+ );
5136
+ }
5137
+ async function raceWithProcessExit(childProcess, operation, options) {
5138
+ if (childProcess.exitCode !== null) {
5139
+ throw createProcessStartupError(
5140
+ options.agentName,
5141
+ options.operationName,
5142
+ childProcess.exitCode,
5143
+ childProcess.signalCode ?? null
5144
+ );
5145
+ }
5146
+ return await new Promise((resolve, reject) => {
5147
+ let settled = false;
5148
+ const cleanup = () => {
5149
+ childProcess.off("error", handleError);
5150
+ childProcess.off("exit", handleExit);
5151
+ };
5152
+ const settleResolve = (value) => {
5153
+ if (settled) {
5154
+ return;
5155
+ }
5156
+ settled = true;
5157
+ cleanup();
5158
+ resolve(value);
5159
+ };
5160
+ const settleReject = (error) => {
5161
+ if (settled) {
5162
+ return;
5163
+ }
5164
+ settled = true;
5165
+ cleanup();
5166
+ reject(normalizeAcpError(error));
5167
+ };
5168
+ const handleError = (error) => {
5169
+ settleReject(error);
5170
+ };
5171
+ const handleExit = (code, signal) => {
5172
+ settleReject(createProcessStartupError(options.agentName, options.operationName, code, signal));
5173
+ };
5174
+ childProcess.once("error", handleError);
5175
+ childProcess.once("exit", handleExit);
5176
+ operation.then(settleResolve, settleReject);
5177
+ });
5178
+ }
4987
5179
  class AcpBackend {
4988
5180
  constructor(options) {
4989
5181
  this.options = options;
@@ -4999,6 +5191,8 @@ class AcpBackend {
4999
5191
  toolCallTimeouts = /* @__PURE__ */ new Map();
5000
5192
  /** Track tool call start times for performance monitoring */
5001
5193
  toolCallStartTimes = /* @__PURE__ */ new Map();
5194
+ /** Track streamed tool output between ACP updates and final completion */
5195
+ toolCallOutputs = /* @__PURE__ */ new Map();
5002
5196
  /** Pending permission requests that need response */
5003
5197
  pendingPermissions = /* @__PURE__ */ new Map();
5004
5198
  /** Map from permission request ID to real tool call ID for tracking */
@@ -5009,6 +5203,14 @@ class AcpBackend {
5009
5203
  toolCallCountSincePrompt = 0;
5010
5204
  /** Timeout for emitting 'idle' status after last message chunk */
5011
5205
  idleTimeout = null;
5206
+ /** Promise resolver for waitForResponseComplete */
5207
+ idleResolver = null;
5208
+ /** Promise rejecter for waitForResponseComplete */
5209
+ idleRejecter = null;
5210
+ /** Completion signal captured before waitForResponseComplete is attached */
5211
+ responseCompletionOutcome = null;
5212
+ /** Whether the current prompt is still waiting for completion */
5213
+ waitingForResponse = false;
5012
5214
  /** Transport handler for agent-specific behavior */
5013
5215
  transport;
5014
5216
  /** Keep a short rolling stderr buffer so startup failures can surface the real cause. */
@@ -5026,6 +5228,44 @@ class AcpBackend {
5026
5228
  getRecentStderrExcerpt() {
5027
5229
  return this.recentStderrLines.slice(-6).join("\n");
5028
5230
  }
5231
+ clearIdleTimeoutState() {
5232
+ if (this.idleTimeout) {
5233
+ clearTimeout(this.idleTimeout);
5234
+ this.idleTimeout = null;
5235
+ }
5236
+ }
5237
+ clearToolCallTracking() {
5238
+ this.activeToolCalls.clear();
5239
+ for (const timeout of this.toolCallTimeouts.values()) {
5240
+ clearTimeout(timeout);
5241
+ }
5242
+ this.toolCallTimeouts.clear();
5243
+ this.toolCallStartTimes.clear();
5244
+ this.toolCallIdToNameMap.clear();
5245
+ this.toolCallOutputs.clear();
5246
+ this.toolCallCountSincePrompt = 0;
5247
+ }
5248
+ resetResponseTrackingForNewPrompt() {
5249
+ this.responseCompletionOutcome = null;
5250
+ this.clearIdleTimeoutState();
5251
+ this.clearToolCallTracking();
5252
+ }
5253
+ settleResponseWaiter(outcome) {
5254
+ const hasActiveWaiter = Boolean(this.idleResolver || this.idleRejecter);
5255
+ if (!this.waitingForResponse && !hasActiveWaiter) {
5256
+ return;
5257
+ }
5258
+ if (!hasActiveWaiter) {
5259
+ this.waitingForResponse = false;
5260
+ this.responseCompletionOutcome = outcome;
5261
+ return;
5262
+ }
5263
+ if (outcome.kind === "resolved") {
5264
+ this.idleResolver?.();
5265
+ return;
5266
+ }
5267
+ this.idleRejecter?.(outcome.error);
5268
+ }
5029
5269
  onMessage(handler) {
5030
5270
  this.listeners.push(handler);
5031
5271
  }
@@ -5100,10 +5340,15 @@ class AcpBackend {
5100
5340
  });
5101
5341
  this.process.on("error", (err) => {
5102
5342
  logger.debug(`[AcpBackend] Process error:`, err);
5343
+ this.settleResponseWaiter({ kind: "rejected", error: err });
5103
5344
  this.emit({ type: "status", status: "error", detail: err.message });
5104
5345
  });
5105
5346
  this.process.on("exit", (code, signal) => {
5106
5347
  if (!this.disposed && code !== 0 && code !== null) {
5348
+ this.settleResponseWaiter({
5349
+ kind: "rejected",
5350
+ error: new Error(`ACP process exited with code ${code}${signal ? ` (${signal})` : ""}`)
5351
+ });
5107
5352
  logger.debug(`[AcpBackend] Process exited with code ${code}, signal ${signal}`);
5108
5353
  this.emit({ type: "status", status: "stopped", detail: `Exit code: ${code}` });
5109
5354
  }
@@ -5331,20 +5576,27 @@ class AcpBackend {
5331
5576
  async () => {
5332
5577
  let timeoutHandle = null;
5333
5578
  try {
5334
- const result = await Promise.race([
5335
- this.connection.initialize(initRequest).then((res) => {
5336
- if (timeoutHandle) {
5337
- clearTimeout(timeoutHandle);
5338
- timeoutHandle = null;
5339
- }
5340
- return res;
5341
- }),
5342
- new Promise((_, reject) => {
5343
- timeoutHandle = setTimeout(() => {
5344
- reject(new Error(`Initialize timeout after ${initTimeout}ms - ${this.transport.agentName} did not respond`));
5345
- }, initTimeout);
5346
- })
5347
- ]);
5579
+ const result = await raceWithProcessExit(
5580
+ this.process,
5581
+ Promise.race([
5582
+ this.connection.initialize(initRequest).then((res) => {
5583
+ if (timeoutHandle) {
5584
+ clearTimeout(timeoutHandle);
5585
+ timeoutHandle = null;
5586
+ }
5587
+ return res;
5588
+ }),
5589
+ new Promise((_, reject) => {
5590
+ timeoutHandle = setTimeout(() => {
5591
+ reject(new Error(`Initialize timeout after ${initTimeout}ms - ${this.transport.agentName} did not respond`));
5592
+ }, initTimeout);
5593
+ })
5594
+ ]),
5595
+ {
5596
+ agentName: this.transport.agentName,
5597
+ operationName: "initialize"
5598
+ }
5599
+ );
5348
5600
  return result;
5349
5601
  } finally {
5350
5602
  if (timeoutHandle) {
@@ -5356,7 +5608,8 @@ class AcpBackend {
5356
5608
  operationName: "Initialize",
5357
5609
  maxAttempts: RETRY_CONFIG.maxAttempts,
5358
5610
  baseDelayMs: RETRY_CONFIG.baseDelayMs,
5359
- maxDelayMs: RETRY_CONFIG.maxDelayMs
5611
+ maxDelayMs: RETRY_CONFIG.maxDelayMs,
5612
+ shouldRetry: (error) => !(error instanceof AcpProcessStartupError)
5360
5613
  }
5361
5614
  );
5362
5615
  logger.debug(`[AcpBackend] Initialize completed`);
@@ -5375,20 +5628,27 @@ class AcpBackend {
5375
5628
  async () => {
5376
5629
  let timeoutHandle = null;
5377
5630
  try {
5378
- const result = await Promise.race([
5379
- this.connection.newSession(newSessionRequest).then((res) => {
5380
- if (timeoutHandle) {
5381
- clearTimeout(timeoutHandle);
5382
- timeoutHandle = null;
5383
- }
5384
- return res;
5385
- }),
5386
- new Promise((_, reject) => {
5387
- timeoutHandle = setTimeout(() => {
5388
- reject(new Error(`New session timeout after ${initTimeout}ms - ${this.transport.agentName} did not respond`));
5389
- }, initTimeout);
5390
- })
5391
- ]);
5631
+ const result = await raceWithProcessExit(
5632
+ this.process,
5633
+ Promise.race([
5634
+ this.connection.newSession(newSessionRequest).then((res) => {
5635
+ if (timeoutHandle) {
5636
+ clearTimeout(timeoutHandle);
5637
+ timeoutHandle = null;
5638
+ }
5639
+ return res;
5640
+ }),
5641
+ new Promise((_, reject) => {
5642
+ timeoutHandle = setTimeout(() => {
5643
+ reject(new Error(`New session timeout after ${initTimeout}ms - ${this.transport.agentName} did not respond`));
5644
+ }, initTimeout);
5645
+ })
5646
+ ]),
5647
+ {
5648
+ agentName: this.transport.agentName,
5649
+ operationName: "new session"
5650
+ }
5651
+ );
5392
5652
  return result;
5393
5653
  } finally {
5394
5654
  if (timeoutHandle) {
@@ -5400,7 +5660,8 @@ class AcpBackend {
5400
5660
  operationName: "NewSession",
5401
5661
  maxAttempts: RETRY_CONFIG.maxAttempts,
5402
5662
  baseDelayMs: RETRY_CONFIG.baseDelayMs,
5403
- maxDelayMs: RETRY_CONFIG.maxDelayMs
5663
+ maxDelayMs: RETRY_CONFIG.maxDelayMs,
5664
+ shouldRetry: (error) => !(error instanceof AcpProcessStartupError)
5404
5665
  }
5405
5666
  );
5406
5667
  this.acpSessionId = sessionResponse.sessionId;
@@ -5434,6 +5695,7 @@ class AcpBackend {
5434
5695
  toolCallStartTimes: this.toolCallStartTimes,
5435
5696
  toolCallTimeouts: this.toolCallTimeouts,
5436
5697
  toolCallIdToNameMap: this.toolCallIdToNameMap,
5698
+ toolCallOutputs: this.toolCallOutputs,
5437
5699
  idleTimeout: this.idleTimeout,
5438
5700
  toolCallCountSincePrompt: this.toolCallCountSincePrompt,
5439
5701
  emit: (msg) => this.emit(msg),
@@ -5510,20 +5772,24 @@ class AcpBackend {
5510
5772
  this.emitUsageTelemetry(update, "acp-usage-update");
5511
5773
  continue;
5512
5774
  }
5775
+ if (sessionUpdateType === "task_complete") {
5776
+ this.emitUsageTelemetry(update.usage, "acp-session-usage");
5777
+ ctx.clearIdleTimeout();
5778
+ logger.debug("[AcpBackend] task_complete received, emitting idle status");
5779
+ this.emitIdleStatus();
5780
+ continue;
5781
+ }
5513
5782
  const handledLegacy = handleLegacyMessageChunk(update, ctx).handled;
5514
5783
  const handledPlan = handlePlanUpdate(update, ctx).handled;
5515
5784
  const handledThinking = handleThinkingUpdate(update, ctx).handled;
5516
5785
  const handledUsage = this.emitUsageTelemetry(update.usage, "acp-session-usage");
5517
5786
  const updateTypeStr = sessionUpdateType;
5518
- const handledTypes = ["agent_message_chunk", "tool_call_update", "agent_thought_chunk", "tool_call", "usage_update"];
5787
+ const handledTypes = ["agent_message_chunk", "tool_call_update", "agent_thought_chunk", "tool_call", "usage_update", "task_complete"];
5519
5788
  if (updateTypeStr && !handledTypes.includes(updateTypeStr) && !handledLegacy && !handledPlan && !handledThinking && !handledUsage) {
5520
5789
  logger.debug(`[AcpBackend] Unhandled session update type: ${updateTypeStr}`, JSON.stringify(update, null, 2));
5521
5790
  }
5522
5791
  }
5523
5792
  }
5524
- // Promise resolver for waitForIdle - set when waiting for response to complete
5525
- idleResolver = null;
5526
- waitingForResponse = false;
5527
5793
  async sendPrompt(sessionId, prompt) {
5528
5794
  this.toolCallCountSincePrompt = 0;
5529
5795
  if (this.disposed) {
@@ -5532,6 +5798,7 @@ class AcpBackend {
5532
5798
  if (!this.connection || !this.acpSessionId) {
5533
5799
  throw new Error("Session not started");
5534
5800
  }
5801
+ this.resetResponseTrackingForNewPrompt();
5535
5802
  this.emit({ type: "status", status: "running" });
5536
5803
  this.waitingForResponse = true;
5537
5804
  try {
@@ -5550,7 +5817,6 @@ class AcpBackend {
5550
5817
  logger.debug("[AcpBackend] Prompt request sent to ACP connection");
5551
5818
  } catch (error) {
5552
5819
  logger.debug("[AcpBackend] Error sending prompt:", error);
5553
- this.waitingForResponse = false;
5554
5820
  let errorDetail;
5555
5821
  if (error instanceof Error) {
5556
5822
  errorDetail = error.message;
@@ -5564,6 +5830,10 @@ class AcpBackend {
5564
5830
  status: "error",
5565
5831
  detail: errorDetail
5566
5832
  });
5833
+ this.settleResponseWaiter({
5834
+ kind: "rejected",
5835
+ error: error instanceof Error ? error : normalizeAcpError(error)
5836
+ });
5567
5837
  throw error;
5568
5838
  }
5569
5839
  }
@@ -5572,21 +5842,38 @@ class AcpBackend {
5572
5842
  * Call this after sendPrompt to wait for Gemini to finish responding
5573
5843
  */
5574
5844
  async waitForResponseComplete(timeoutMs = 12e4) {
5845
+ const pendingOutcome = this.responseCompletionOutcome;
5846
+ if (pendingOutcome) {
5847
+ this.responseCompletionOutcome = null;
5848
+ if (pendingOutcome.kind === "rejected") {
5849
+ throw pendingOutcome.error;
5850
+ }
5851
+ return;
5852
+ }
5575
5853
  if (!this.waitingForResponse) {
5576
5854
  return;
5577
5855
  }
5578
5856
  return new Promise((resolve, reject) => {
5579
5857
  const timeout = setTimeout(() => {
5580
5858
  this.idleResolver = null;
5859
+ this.idleRejecter = null;
5581
5860
  this.waitingForResponse = false;
5582
5861
  reject(new Error("Timeout waiting for response to complete"));
5583
5862
  }, timeoutMs);
5584
5863
  this.idleResolver = () => {
5585
5864
  clearTimeout(timeout);
5586
5865
  this.idleResolver = null;
5866
+ this.idleRejecter = null;
5587
5867
  this.waitingForResponse = false;
5588
5868
  resolve();
5589
5869
  };
5870
+ this.idleRejecter = (error) => {
5871
+ clearTimeout(timeout);
5872
+ this.idleResolver = null;
5873
+ this.idleRejecter = null;
5874
+ this.waitingForResponse = false;
5875
+ reject(error);
5876
+ };
5590
5877
  });
5591
5878
  }
5592
5879
  /**
@@ -5594,18 +5881,19 @@ class AcpBackend {
5594
5881
  */
5595
5882
  emitIdleStatus() {
5596
5883
  this.emit({ type: "status", status: "idle" });
5597
- if (this.idleResolver) {
5598
- logger.debug("[AcpBackend] Resolving idle waiter");
5599
- this.idleResolver();
5600
- }
5884
+ this.settleResponseWaiter({ kind: "resolved" });
5601
5885
  }
5602
5886
  async cancel(sessionId) {
5887
+ const cancelError = createAcpAbortError("Cancelled by user");
5888
+ this.clearIdleTimeoutState();
5889
+ this.clearToolCallTracking();
5890
+ this.settleResponseWaiter({ kind: "rejected", error: cancelError });
5891
+ this.emit({ type: "status", status: "stopped", detail: "Cancelled by user" });
5603
5892
  if (!this.connection || !this.acpSessionId) {
5604
5893
  return;
5605
5894
  }
5606
5895
  try {
5607
5896
  await this.connection.cancel({ sessionId: this.acpSessionId });
5608
- this.emit({ type: "status", status: "stopped", detail: "Cancelled by user" });
5609
5897
  } catch (error) {
5610
5898
  logger.debug("[AcpBackend] Error cancelling:", error);
5611
5899
  }
@@ -5633,6 +5921,10 @@ class AcpBackend {
5633
5921
  if (this.disposed) return;
5634
5922
  logger.debug("[AcpBackend] Disposing backend");
5635
5923
  this.disposed = true;
5924
+ this.settleResponseWaiter({
5925
+ kind: "rejected",
5926
+ error: createAcpAbortError("ACP backend disposed")
5927
+ });
5636
5928
  if (this.connection && this.acpSessionId) {
5637
5929
  try {
5638
5930
  await Promise.race([
@@ -5661,19 +5953,11 @@ class AcpBackend {
5661
5953
  });
5662
5954
  this.process = null;
5663
5955
  }
5664
- if (this.idleTimeout) {
5665
- clearTimeout(this.idleTimeout);
5666
- this.idleTimeout = null;
5667
- }
5956
+ this.clearIdleTimeoutState();
5668
5957
  this.listeners = [];
5669
5958
  this.connection = null;
5670
5959
  this.acpSessionId = null;
5671
- this.activeToolCalls.clear();
5672
- for (const timeout of this.toolCallTimeouts.values()) {
5673
- clearTimeout(timeout);
5674
- }
5675
- this.toolCallTimeouts.clear();
5676
- this.toolCallStartTimes.clear();
5960
+ this.clearToolCallTracking();
5677
5961
  this.pendingPermissions.clear();
5678
5962
  }
5679
5963
  }
@@ -5908,6 +6192,7 @@ function registerGeminiAgent() {
5908
6192
  logger.debug("[Gemini] Registered with agent registry");
5909
6193
  }
5910
6194
 
6195
+ const DEFAULT_CODEX_ACP_NPX_PACKAGE = "@zed-industries/codex-acp@0.9.5";
5911
6196
  function readFirstEnv(...names) {
5912
6197
  for (const name of names) {
5913
6198
  const raw = process.env[name];
@@ -5962,6 +6247,10 @@ function readCodexAcpNpxMode() {
5962
6247
  }
5963
6248
  return "auto";
5964
6249
  }
6250
+ function readCodexAcpNpxPackage() {
6251
+ const configured = readFirstEnv("HAPPY_CODEX_ACP_PACKAGE", "HAPPIER_CODEX_ACP_PACKAGE");
6252
+ return configured || DEFAULT_CODEX_ACP_NPX_PACKAGE;
6253
+ }
5965
6254
  function isBinOnPath(baseName) {
5966
6255
  return resolveCommandOnPath(baseName) !== null;
5967
6256
  }
@@ -6027,7 +6316,7 @@ function resolveCodexAcpSpawn(options = {}) {
6027
6316
  }
6028
6317
  return {
6029
6318
  command: resolveNpxCommand(),
6030
- args: ["--prefer-offline", "-y", "@zed-industries/codex-acp", ...directArgs]
6319
+ args: ["--prefer-offline", "-y", readCodexAcpNpxPackage(), ...directArgs]
6031
6320
  };
6032
6321
  }
6033
6322
  function validateCodexAcpSpawn(options = {}) {
@@ -6314,12 +6603,12 @@ async function ensureUnifiedDaemonStarted() {
6314
6603
  async function executeUnifiedProvider(opts) {
6315
6604
  const credentials = await ensureUnifiedRuntimePrerequisites(opts.credentials);
6316
6605
  if (opts.provider === "claude") {
6317
- const { runClaude } = await import('./runClaude-D6Pdkevn.mjs');
6606
+ const { runClaude } = await import('./runClaude-CZ8gxaJL.mjs');
6318
6607
  await runClaude(credentials, opts.claudeOptions ?? {});
6319
6608
  return;
6320
6609
  }
6321
6610
  if (opts.provider === "codex") {
6322
- const { runCodex } = await import('./runCodex-CsfUU1Wb.mjs');
6611
+ const { runCodex } = await import('./runCodex-DT7g4MPm.mjs');
6323
6612
  await runCodex({
6324
6613
  credentials,
6325
6614
  startedBy: opts.startedBy,
@@ -6329,7 +6618,7 @@ async function executeUnifiedProvider(opts) {
6329
6618
  return;
6330
6619
  }
6331
6620
  if (opts.provider === "gemini") {
6332
- const { runGemini } = await import('./runGemini-CrH3dQ0Y.mjs');
6621
+ const { runGemini } = await import('./runGemini-CmY5386l.mjs');
6333
6622
  await runGemini({
6334
6623
  credentials,
6335
6624
  startedBy: opts.startedBy
@@ -6371,7 +6660,7 @@ function shouldRunMainClaudeFlow(opts) {
6371
6660
  return;
6372
6661
  } else if (subcommand === "runtime") {
6373
6662
  if (args[1] === "providers") {
6374
- const { renderRuntimeProviders } = await import('./command-DRqrBuHM.mjs');
6663
+ const { renderRuntimeProviders } = await import('./command-Dl9SrMnv.mjs');
6375
6664
  console.log(renderRuntimeProviders());
6376
6665
  return;
6377
6666
  }
@@ -6549,8 +6838,8 @@ function shouldRunMainClaudeFlow(opts) {
6549
6838
  const projectId = args[3];
6550
6839
  try {
6551
6840
  const { saveGoogleCloudProjectToConfig } = await Promise.resolve().then(function () { return config; });
6552
- const { readCredentials: readCredentials2 } = await import('./persistence-CqgPgbzN.mjs');
6553
- const { ApiClient: ApiClient2 } = await import('./api-DpQIC-DJ.mjs').then(function (n) { return n.q; });
6841
+ const { readCredentials: readCredentials2 } = await import('./persistence-QqeBvUxX.mjs');
6842
+ const { ApiClient: ApiClient2 } = await import('./api-DoHt-HyL.mjs').then(function (n) { return n.q; });
6554
6843
  let userEmail = void 0;
6555
6844
  try {
6556
6845
  const credentials = await readCredentials2();