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.
- package/dist/{BaseReasoningProcessor-_wxlqKB8.cjs → BaseReasoningProcessor-DPVZIJ4n.cjs} +2 -2
- package/dist/{BaseReasoningProcessor-B37yOHxo.mjs → BaseReasoningProcessor-bFVTvf3Q.mjs} +2 -2
- package/dist/{api-D9dIR956.cjs → api-DaqnNHfl.cjs} +4 -2
- package/dist/{api-DpQIC-DJ.mjs → api-DoHt-HyL.mjs} +4 -2
- package/dist/{command-CdXv1zNF.cjs → command-D9-hmqVq.cjs} +3 -3
- package/dist/{command-DRqrBuHM.mjs → command-Dl9SrMnv.mjs} +3 -3
- package/dist/{index-CriPm_z9.mjs → index-C5wR2qKT.mjs} +359 -70
- package/dist/{index-LYPXVO_L.cjs → index-Dc92gnxM.cjs} +361 -72
- package/dist/index.cjs +3 -3
- package/dist/index.mjs +3 -3
- package/dist/lib.cjs +1 -1
- package/dist/lib.mjs +1 -1
- package/dist/{persistence-PzKU0QCa.cjs → persistence-D6Y0604_.cjs} +1 -1
- package/dist/{persistence-CqgPgbzN.mjs → persistence-QqeBvUxX.mjs} +1 -1
- package/dist/{registerKillSessionHandler-BDBPoQSA.cjs → registerKillSessionHandler-C6yXr8ky.cjs} +2 -2
- package/dist/{registerKillSessionHandler-C3M_-4Zg.mjs → registerKillSessionHandler-CC9zGBPE.mjs} +2 -2
- package/dist/{runClaude-D6Pdkevn.mjs → runClaude-CZ8gxaJL.mjs} +4 -4
- package/dist/{runClaude-IeRSC5qX.cjs → runClaude-gHKFB1UG.cjs} +5 -5
- package/dist/{runCodex-WRmgSK6L.cjs → runCodex-CdjzG1N7.cjs} +113 -25
- package/dist/{runCodex-CsfUU1Wb.mjs → runCodex-DT7g4MPm.mjs} +111 -26
- package/dist/{runGemini-CrH3dQ0Y.mjs → runGemini-CmY5386l.mjs} +55 -21
- package/dist/{runGemini-qBh6zs5G.cjs → runGemini-DxjvRmOc.cjs} +55 -21
- 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-
|
|
5
|
-
var persistence = require('./persistence-
|
|
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-
|
|
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-
|
|
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:
|
|
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
|
-
|
|
4954
|
-
|
|
4955
|
-
|
|
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
|
|
5357
|
-
this.
|
|
5358
|
-
|
|
5359
|
-
|
|
5360
|
-
timeoutHandle
|
|
5361
|
-
|
|
5362
|
-
|
|
5363
|
-
|
|
5364
|
-
|
|
5365
|
-
|
|
5366
|
-
|
|
5367
|
-
|
|
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
|
|
5401
|
-
this.
|
|
5402
|
-
|
|
5403
|
-
|
|
5404
|
-
timeoutHandle
|
|
5405
|
-
|
|
5406
|
-
|
|
5407
|
-
|
|
5408
|
-
|
|
5409
|
-
|
|
5410
|
-
|
|
5411
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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.
|
|
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",
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
6575
|
-
const { ApiClient: ApiClient2 } = await Promise.resolve().then(function () { return require('./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();
|