happy-imou-cloud 2.0.3 → 2.0.4
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-DEEfNi5Y.cjs} +2 -2
- package/dist/{BaseReasoningProcessor-B37yOHxo.mjs → BaseReasoningProcessor-Di1yEMMv.mjs} +2 -2
- package/dist/{api-DpQIC-DJ.mjs → api-CIHTNilH.mjs} +2 -2
- package/dist/{api-D9dIR956.cjs → api-CyJG1mr6.cjs} +2 -2
- package/dist/{command-DRqrBuHM.mjs → command-BERqmFB0.mjs} +3 -3
- package/dist/{command-CdXv1zNF.cjs → command-CPlJKXDn.cjs} +3 -3
- package/dist/{index-LYPXVO_L.cjs → index-1zlH6s7a.cjs} +228 -33
- package/dist/{index-CriPm_z9.mjs → index-vNYxNqVZ.mjs} +226 -31
- 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-BeFVx6kI.cjs} +1 -1
- package/dist/{persistence-CqgPgbzN.mjs → persistence-sLEqV8vk.mjs} +1 -1
- package/dist/{registerKillSessionHandler-BDBPoQSA.cjs → registerKillSessionHandler-CCxqGFjZ.cjs} +2 -2
- package/dist/{registerKillSessionHandler-C3M_-4Zg.mjs → registerKillSessionHandler-uVHqIC4h.mjs} +2 -2
- package/dist/{runClaude-D6Pdkevn.mjs → runClaude-Dl9nIRIg.mjs} +4 -4
- package/dist/{runClaude-IeRSC5qX.cjs → runClaude-Dz-PCSvb.cjs} +5 -5
- package/dist/{runCodex-WRmgSK6L.cjs → runCodex-BtZplK1R.cjs} +65 -13
- package/dist/{runCodex-CsfUU1Wb.mjs → runCodex-DgKKw3IU.mjs} +63 -14
- package/dist/{runGemini-CrH3dQ0Y.mjs → runGemini-CM1v3I24.mjs} +10 -8
- package/dist/{runGemini-qBh6zs5G.cjs → runGemini-DUyH311Z.cjs} +10 -8
- package/package.json +1 -1
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
var os = require('node:os');
|
|
4
4
|
var node_path = require('node:path');
|
|
5
|
-
var api = require('./api-
|
|
6
|
-
var index = require('./index-
|
|
5
|
+
var api = require('./api-CyJG1mr6.cjs');
|
|
6
|
+
var index = require('./index-1zlH6s7a.cjs');
|
|
7
7
|
var node_events = require('node:events');
|
|
8
8
|
var node_crypto = require('node:crypto');
|
|
9
9
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import os from 'node:os';
|
|
2
2
|
import { resolve } from 'node:path';
|
|
3
|
-
import { c as configuration, p as packageJson, s as startOfflineReconnection, l as logger } from './api-
|
|
4
|
-
import { p as projectPath } from './index-
|
|
3
|
+
import { c as configuration, p as packageJson, s as startOfflineReconnection, l as logger } from './api-CIHTNilH.mjs';
|
|
4
|
+
import { p as projectPath } from './index-vNYxNqVZ.mjs';
|
|
5
5
|
import { EventEmitter } from 'node:events';
|
|
6
6
|
import { randomUUID } from 'node:crypto';
|
|
7
7
|
|
|
@@ -17,7 +17,7 @@ import { resolve, join as join$1 } from 'path';
|
|
|
17
17
|
import { Expo } from 'expo-server-sdk';
|
|
18
18
|
|
|
19
19
|
var name = "happy-imou-cloud";
|
|
20
|
-
var version = "2.0.
|
|
20
|
+
var version = "2.0.4";
|
|
21
21
|
var description = "hicloud - Imou 企业定制版。关键是 happy!移动端远程 AI 编程工具,支持 Claude Code、Codex 和 Gemini CLI";
|
|
22
22
|
var author = "long.zhu";
|
|
23
23
|
var license = "MIT";
|
|
@@ -430,7 +430,7 @@ async function listDaemonLogFiles(limit = 50) {
|
|
|
430
430
|
return { file, path: fullPath, modified: stats.mtime };
|
|
431
431
|
}).sort((a, b) => b.modified.getTime() - a.modified.getTime());
|
|
432
432
|
try {
|
|
433
|
-
const { readDaemonState } = await import('./persistence-
|
|
433
|
+
const { readDaemonState } = await import('./persistence-sLEqV8vk.mjs');
|
|
434
434
|
const state = await readDaemonState();
|
|
435
435
|
if (!state) {
|
|
436
436
|
return logs;
|
|
@@ -19,7 +19,7 @@ var path = require('path');
|
|
|
19
19
|
var expoServerSdk = require('expo-server-sdk');
|
|
20
20
|
|
|
21
21
|
var name = "happy-imou-cloud";
|
|
22
|
-
var version = "2.0.
|
|
22
|
+
var version = "2.0.4";
|
|
23
23
|
var description = "hicloud - Imou 企业定制版。关键是 happy!移动端远程 AI 编程工具,支持 Claude Code、Codex 和 Gemini CLI";
|
|
24
24
|
var author = "long.zhu";
|
|
25
25
|
var license = "MIT";
|
|
@@ -432,7 +432,7 @@ async function listDaemonLogFiles(limit = 50) {
|
|
|
432
432
|
return { file, path: fullPath, modified: stats.mtime };
|
|
433
433
|
}).sort((a, b) => b.modified.getTime() - a.modified.getTime());
|
|
434
434
|
try {
|
|
435
|
-
const { readDaemonState } = await Promise.resolve().then(function () { return require('./persistence-
|
|
435
|
+
const { readDaemonState } = await Promise.resolve().then(function () { return require('./persistence-BeFVx6kI.cjs'); });
|
|
436
436
|
const state = await readDaemonState();
|
|
437
437
|
if (!state) {
|
|
438
438
|
return logs;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { c as createDefaultRuntimeShell } from './index-
|
|
1
|
+
import { c as createDefaultRuntimeShell } from './index-vNYxNqVZ.mjs';
|
|
2
2
|
import 'chalk';
|
|
3
|
-
import './api-
|
|
3
|
+
import './api-CIHTNilH.mjs';
|
|
4
4
|
import 'axios';
|
|
5
5
|
import 'fs';
|
|
6
6
|
import 'node:fs';
|
|
@@ -17,7 +17,7 @@ import 'fs/promises';
|
|
|
17
17
|
import 'crypto';
|
|
18
18
|
import 'path';
|
|
19
19
|
import 'expo-server-sdk';
|
|
20
|
-
import './persistence-
|
|
20
|
+
import './persistence-sLEqV8vk.mjs';
|
|
21
21
|
import 'node:fs/promises';
|
|
22
22
|
import 'os';
|
|
23
23
|
import 'tmp';
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var index = require('./index-
|
|
3
|
+
var index = require('./index-1zlH6s7a.cjs');
|
|
4
4
|
require('chalk');
|
|
5
|
-
require('./api-
|
|
5
|
+
require('./api-CyJG1mr6.cjs');
|
|
6
6
|
require('axios');
|
|
7
7
|
require('fs');
|
|
8
8
|
require('node:fs');
|
|
@@ -19,7 +19,7 @@ require('fs/promises');
|
|
|
19
19
|
require('crypto');
|
|
20
20
|
require('path');
|
|
21
21
|
require('expo-server-sdk');
|
|
22
|
-
require('./persistence-
|
|
22
|
+
require('./persistence-BeFVx6kI.cjs');
|
|
23
23
|
require('node:fs/promises');
|
|
24
24
|
require('os');
|
|
25
25
|
require('tmp');
|
|
@@ -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-CyJG1mr6.cjs');
|
|
5
|
+
var persistence = require('./persistence-BeFVx6kI.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-1zlH6s7a.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-1zlH6s7a.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++;
|
|
@@ -4995,6 +5109,11 @@ function normalizeAcpError(error) {
|
|
|
4995
5109
|
}
|
|
4996
5110
|
return normalized;
|
|
4997
5111
|
}
|
|
5112
|
+
function createAcpAbortError(message) {
|
|
5113
|
+
const error = new Error(message);
|
|
5114
|
+
error.name = "AbortError";
|
|
5115
|
+
return error;
|
|
5116
|
+
}
|
|
4998
5117
|
function enrichAcpError(error, stderrExcerpt) {
|
|
4999
5118
|
const normalized = normalizeAcpError(error);
|
|
5000
5119
|
if (!stderrExcerpt.trim()) {
|
|
@@ -5021,6 +5140,8 @@ class AcpBackend {
|
|
|
5021
5140
|
toolCallTimeouts = /* @__PURE__ */ new Map();
|
|
5022
5141
|
/** Track tool call start times for performance monitoring */
|
|
5023
5142
|
toolCallStartTimes = /* @__PURE__ */ new Map();
|
|
5143
|
+
/** Track streamed tool output between ACP updates and final completion */
|
|
5144
|
+
toolCallOutputs = /* @__PURE__ */ new Map();
|
|
5024
5145
|
/** Pending permission requests that need response */
|
|
5025
5146
|
pendingPermissions = /* @__PURE__ */ new Map();
|
|
5026
5147
|
/** Map from permission request ID to real tool call ID for tracking */
|
|
@@ -5031,6 +5152,14 @@ class AcpBackend {
|
|
|
5031
5152
|
toolCallCountSincePrompt = 0;
|
|
5032
5153
|
/** Timeout for emitting 'idle' status after last message chunk */
|
|
5033
5154
|
idleTimeout = null;
|
|
5155
|
+
/** Promise resolver for waitForResponseComplete */
|
|
5156
|
+
idleResolver = null;
|
|
5157
|
+
/** Promise rejecter for waitForResponseComplete */
|
|
5158
|
+
idleRejecter = null;
|
|
5159
|
+
/** Completion signal captured before waitForResponseComplete is attached */
|
|
5160
|
+
responseCompletionOutcome = null;
|
|
5161
|
+
/** Whether the current prompt is still waiting for completion */
|
|
5162
|
+
waitingForResponse = false;
|
|
5034
5163
|
/** Transport handler for agent-specific behavior */
|
|
5035
5164
|
transport;
|
|
5036
5165
|
/** Keep a short rolling stderr buffer so startup failures can surface the real cause. */
|
|
@@ -5048,6 +5177,44 @@ class AcpBackend {
|
|
|
5048
5177
|
getRecentStderrExcerpt() {
|
|
5049
5178
|
return this.recentStderrLines.slice(-6).join("\n");
|
|
5050
5179
|
}
|
|
5180
|
+
clearIdleTimeoutState() {
|
|
5181
|
+
if (this.idleTimeout) {
|
|
5182
|
+
clearTimeout(this.idleTimeout);
|
|
5183
|
+
this.idleTimeout = null;
|
|
5184
|
+
}
|
|
5185
|
+
}
|
|
5186
|
+
clearToolCallTracking() {
|
|
5187
|
+
this.activeToolCalls.clear();
|
|
5188
|
+
for (const timeout of this.toolCallTimeouts.values()) {
|
|
5189
|
+
clearTimeout(timeout);
|
|
5190
|
+
}
|
|
5191
|
+
this.toolCallTimeouts.clear();
|
|
5192
|
+
this.toolCallStartTimes.clear();
|
|
5193
|
+
this.toolCallIdToNameMap.clear();
|
|
5194
|
+
this.toolCallOutputs.clear();
|
|
5195
|
+
this.toolCallCountSincePrompt = 0;
|
|
5196
|
+
}
|
|
5197
|
+
resetResponseTrackingForNewPrompt() {
|
|
5198
|
+
this.responseCompletionOutcome = null;
|
|
5199
|
+
this.clearIdleTimeoutState();
|
|
5200
|
+
this.clearToolCallTracking();
|
|
5201
|
+
}
|
|
5202
|
+
settleResponseWaiter(outcome) {
|
|
5203
|
+
const hasActiveWaiter = Boolean(this.idleResolver || this.idleRejecter);
|
|
5204
|
+
if (!this.waitingForResponse && !hasActiveWaiter) {
|
|
5205
|
+
return;
|
|
5206
|
+
}
|
|
5207
|
+
if (!hasActiveWaiter) {
|
|
5208
|
+
this.waitingForResponse = false;
|
|
5209
|
+
this.responseCompletionOutcome = outcome;
|
|
5210
|
+
return;
|
|
5211
|
+
}
|
|
5212
|
+
if (outcome.kind === "resolved") {
|
|
5213
|
+
this.idleResolver?.();
|
|
5214
|
+
return;
|
|
5215
|
+
}
|
|
5216
|
+
this.idleRejecter?.(outcome.error);
|
|
5217
|
+
}
|
|
5051
5218
|
onMessage(handler) {
|
|
5052
5219
|
this.listeners.push(handler);
|
|
5053
5220
|
}
|
|
@@ -5122,10 +5289,15 @@ class AcpBackend {
|
|
|
5122
5289
|
});
|
|
5123
5290
|
this.process.on("error", (err) => {
|
|
5124
5291
|
api.logger.debug(`[AcpBackend] Process error:`, err);
|
|
5292
|
+
this.settleResponseWaiter({ kind: "rejected", error: err });
|
|
5125
5293
|
this.emit({ type: "status", status: "error", detail: err.message });
|
|
5126
5294
|
});
|
|
5127
5295
|
this.process.on("exit", (code, signal) => {
|
|
5128
5296
|
if (!this.disposed && code !== 0 && code !== null) {
|
|
5297
|
+
this.settleResponseWaiter({
|
|
5298
|
+
kind: "rejected",
|
|
5299
|
+
error: new Error(`ACP process exited with code ${code}${signal ? ` (${signal})` : ""}`)
|
|
5300
|
+
});
|
|
5129
5301
|
api.logger.debug(`[AcpBackend] Process exited with code ${code}, signal ${signal}`);
|
|
5130
5302
|
this.emit({ type: "status", status: "stopped", detail: `Exit code: ${code}` });
|
|
5131
5303
|
}
|
|
@@ -5456,6 +5628,7 @@ class AcpBackend {
|
|
|
5456
5628
|
toolCallStartTimes: this.toolCallStartTimes,
|
|
5457
5629
|
toolCallTimeouts: this.toolCallTimeouts,
|
|
5458
5630
|
toolCallIdToNameMap: this.toolCallIdToNameMap,
|
|
5631
|
+
toolCallOutputs: this.toolCallOutputs,
|
|
5459
5632
|
idleTimeout: this.idleTimeout,
|
|
5460
5633
|
toolCallCountSincePrompt: this.toolCallCountSincePrompt,
|
|
5461
5634
|
emit: (msg) => this.emit(msg),
|
|
@@ -5532,20 +5705,24 @@ class AcpBackend {
|
|
|
5532
5705
|
this.emitUsageTelemetry(update, "acp-usage-update");
|
|
5533
5706
|
continue;
|
|
5534
5707
|
}
|
|
5708
|
+
if (sessionUpdateType === "task_complete") {
|
|
5709
|
+
this.emitUsageTelemetry(update.usage, "acp-session-usage");
|
|
5710
|
+
ctx.clearIdleTimeout();
|
|
5711
|
+
api.logger.debug("[AcpBackend] task_complete received, emitting idle status");
|
|
5712
|
+
this.emitIdleStatus();
|
|
5713
|
+
continue;
|
|
5714
|
+
}
|
|
5535
5715
|
const handledLegacy = handleLegacyMessageChunk(update, ctx).handled;
|
|
5536
5716
|
const handledPlan = handlePlanUpdate(update, ctx).handled;
|
|
5537
5717
|
const handledThinking = handleThinkingUpdate(update, ctx).handled;
|
|
5538
5718
|
const handledUsage = this.emitUsageTelemetry(update.usage, "acp-session-usage");
|
|
5539
5719
|
const updateTypeStr = sessionUpdateType;
|
|
5540
|
-
const handledTypes = ["agent_message_chunk", "tool_call_update", "agent_thought_chunk", "tool_call", "usage_update"];
|
|
5720
|
+
const handledTypes = ["agent_message_chunk", "tool_call_update", "agent_thought_chunk", "tool_call", "usage_update", "task_complete"];
|
|
5541
5721
|
if (updateTypeStr && !handledTypes.includes(updateTypeStr) && !handledLegacy && !handledPlan && !handledThinking && !handledUsage) {
|
|
5542
5722
|
api.logger.debug(`[AcpBackend] Unhandled session update type: ${updateTypeStr}`, JSON.stringify(update, null, 2));
|
|
5543
5723
|
}
|
|
5544
5724
|
}
|
|
5545
5725
|
}
|
|
5546
|
-
// Promise resolver for waitForIdle - set when waiting for response to complete
|
|
5547
|
-
idleResolver = null;
|
|
5548
|
-
waitingForResponse = false;
|
|
5549
5726
|
async sendPrompt(sessionId, prompt) {
|
|
5550
5727
|
this.toolCallCountSincePrompt = 0;
|
|
5551
5728
|
if (this.disposed) {
|
|
@@ -5554,6 +5731,7 @@ class AcpBackend {
|
|
|
5554
5731
|
if (!this.connection || !this.acpSessionId) {
|
|
5555
5732
|
throw new Error("Session not started");
|
|
5556
5733
|
}
|
|
5734
|
+
this.resetResponseTrackingForNewPrompt();
|
|
5557
5735
|
this.emit({ type: "status", status: "running" });
|
|
5558
5736
|
this.waitingForResponse = true;
|
|
5559
5737
|
try {
|
|
@@ -5572,7 +5750,6 @@ class AcpBackend {
|
|
|
5572
5750
|
api.logger.debug("[AcpBackend] Prompt request sent to ACP connection");
|
|
5573
5751
|
} catch (error) {
|
|
5574
5752
|
api.logger.debug("[AcpBackend] Error sending prompt:", error);
|
|
5575
|
-
this.waitingForResponse = false;
|
|
5576
5753
|
let errorDetail;
|
|
5577
5754
|
if (error instanceof Error) {
|
|
5578
5755
|
errorDetail = error.message;
|
|
@@ -5586,6 +5763,10 @@ class AcpBackend {
|
|
|
5586
5763
|
status: "error",
|
|
5587
5764
|
detail: errorDetail
|
|
5588
5765
|
});
|
|
5766
|
+
this.settleResponseWaiter({
|
|
5767
|
+
kind: "rejected",
|
|
5768
|
+
error: error instanceof Error ? error : normalizeAcpError(error)
|
|
5769
|
+
});
|
|
5589
5770
|
throw error;
|
|
5590
5771
|
}
|
|
5591
5772
|
}
|
|
@@ -5594,21 +5775,38 @@ class AcpBackend {
|
|
|
5594
5775
|
* Call this after sendPrompt to wait for Gemini to finish responding
|
|
5595
5776
|
*/
|
|
5596
5777
|
async waitForResponseComplete(timeoutMs = 12e4) {
|
|
5778
|
+
const pendingOutcome = this.responseCompletionOutcome;
|
|
5779
|
+
if (pendingOutcome) {
|
|
5780
|
+
this.responseCompletionOutcome = null;
|
|
5781
|
+
if (pendingOutcome.kind === "rejected") {
|
|
5782
|
+
throw pendingOutcome.error;
|
|
5783
|
+
}
|
|
5784
|
+
return;
|
|
5785
|
+
}
|
|
5597
5786
|
if (!this.waitingForResponse) {
|
|
5598
5787
|
return;
|
|
5599
5788
|
}
|
|
5600
5789
|
return new Promise((resolve, reject) => {
|
|
5601
5790
|
const timeout = setTimeout(() => {
|
|
5602
5791
|
this.idleResolver = null;
|
|
5792
|
+
this.idleRejecter = null;
|
|
5603
5793
|
this.waitingForResponse = false;
|
|
5604
5794
|
reject(new Error("Timeout waiting for response to complete"));
|
|
5605
5795
|
}, timeoutMs);
|
|
5606
5796
|
this.idleResolver = () => {
|
|
5607
5797
|
clearTimeout(timeout);
|
|
5608
5798
|
this.idleResolver = null;
|
|
5799
|
+
this.idleRejecter = null;
|
|
5609
5800
|
this.waitingForResponse = false;
|
|
5610
5801
|
resolve();
|
|
5611
5802
|
};
|
|
5803
|
+
this.idleRejecter = (error) => {
|
|
5804
|
+
clearTimeout(timeout);
|
|
5805
|
+
this.idleResolver = null;
|
|
5806
|
+
this.idleRejecter = null;
|
|
5807
|
+
this.waitingForResponse = false;
|
|
5808
|
+
reject(error);
|
|
5809
|
+
};
|
|
5612
5810
|
});
|
|
5613
5811
|
}
|
|
5614
5812
|
/**
|
|
@@ -5616,18 +5814,19 @@ class AcpBackend {
|
|
|
5616
5814
|
*/
|
|
5617
5815
|
emitIdleStatus() {
|
|
5618
5816
|
this.emit({ type: "status", status: "idle" });
|
|
5619
|
-
|
|
5620
|
-
api.logger.debug("[AcpBackend] Resolving idle waiter");
|
|
5621
|
-
this.idleResolver();
|
|
5622
|
-
}
|
|
5817
|
+
this.settleResponseWaiter({ kind: "resolved" });
|
|
5623
5818
|
}
|
|
5624
5819
|
async cancel(sessionId) {
|
|
5820
|
+
const cancelError = createAcpAbortError("Cancelled by user");
|
|
5821
|
+
this.clearIdleTimeoutState();
|
|
5822
|
+
this.clearToolCallTracking();
|
|
5823
|
+
this.settleResponseWaiter({ kind: "rejected", error: cancelError });
|
|
5824
|
+
this.emit({ type: "status", status: "stopped", detail: "Cancelled by user" });
|
|
5625
5825
|
if (!this.connection || !this.acpSessionId) {
|
|
5626
5826
|
return;
|
|
5627
5827
|
}
|
|
5628
5828
|
try {
|
|
5629
5829
|
await this.connection.cancel({ sessionId: this.acpSessionId });
|
|
5630
|
-
this.emit({ type: "status", status: "stopped", detail: "Cancelled by user" });
|
|
5631
5830
|
} catch (error) {
|
|
5632
5831
|
api.logger.debug("[AcpBackend] Error cancelling:", error);
|
|
5633
5832
|
}
|
|
@@ -5655,6 +5854,10 @@ class AcpBackend {
|
|
|
5655
5854
|
if (this.disposed) return;
|
|
5656
5855
|
api.logger.debug("[AcpBackend] Disposing backend");
|
|
5657
5856
|
this.disposed = true;
|
|
5857
|
+
this.settleResponseWaiter({
|
|
5858
|
+
kind: "rejected",
|
|
5859
|
+
error: createAcpAbortError("ACP backend disposed")
|
|
5860
|
+
});
|
|
5658
5861
|
if (this.connection && this.acpSessionId) {
|
|
5659
5862
|
try {
|
|
5660
5863
|
await Promise.race([
|
|
@@ -5683,19 +5886,11 @@ class AcpBackend {
|
|
|
5683
5886
|
});
|
|
5684
5887
|
this.process = null;
|
|
5685
5888
|
}
|
|
5686
|
-
|
|
5687
|
-
clearTimeout(this.idleTimeout);
|
|
5688
|
-
this.idleTimeout = null;
|
|
5689
|
-
}
|
|
5889
|
+
this.clearIdleTimeoutState();
|
|
5690
5890
|
this.listeners = [];
|
|
5691
5891
|
this.connection = null;
|
|
5692
5892
|
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();
|
|
5893
|
+
this.clearToolCallTracking();
|
|
5699
5894
|
this.pendingPermissions.clear();
|
|
5700
5895
|
}
|
|
5701
5896
|
}
|
|
@@ -6336,12 +6531,12 @@ async function ensureUnifiedDaemonStarted() {
|
|
|
6336
6531
|
async function executeUnifiedProvider(opts) {
|
|
6337
6532
|
const credentials = await ensureUnifiedRuntimePrerequisites(opts.credentials);
|
|
6338
6533
|
if (opts.provider === "claude") {
|
|
6339
|
-
const { runClaude } = await Promise.resolve().then(function () { return require('./runClaude-
|
|
6534
|
+
const { runClaude } = await Promise.resolve().then(function () { return require('./runClaude-Dz-PCSvb.cjs'); });
|
|
6340
6535
|
await runClaude(credentials, opts.claudeOptions ?? {});
|
|
6341
6536
|
return;
|
|
6342
6537
|
}
|
|
6343
6538
|
if (opts.provider === "codex") {
|
|
6344
|
-
const { runCodex } = await Promise.resolve().then(function () { return require('./runCodex-
|
|
6539
|
+
const { runCodex } = await Promise.resolve().then(function () { return require('./runCodex-BtZplK1R.cjs'); });
|
|
6345
6540
|
await runCodex({
|
|
6346
6541
|
credentials,
|
|
6347
6542
|
startedBy: opts.startedBy,
|
|
@@ -6351,7 +6546,7 @@ async function executeUnifiedProvider(opts) {
|
|
|
6351
6546
|
return;
|
|
6352
6547
|
}
|
|
6353
6548
|
if (opts.provider === "gemini") {
|
|
6354
|
-
const { runGemini } = await Promise.resolve().then(function () { return require('./runGemini-
|
|
6549
|
+
const { runGemini } = await Promise.resolve().then(function () { return require('./runGemini-DUyH311Z.cjs'); });
|
|
6355
6550
|
await runGemini({
|
|
6356
6551
|
credentials,
|
|
6357
6552
|
startedBy: opts.startedBy
|
|
@@ -6393,7 +6588,7 @@ function shouldRunMainClaudeFlow(opts) {
|
|
|
6393
6588
|
return;
|
|
6394
6589
|
} else if (subcommand === "runtime") {
|
|
6395
6590
|
if (args[1] === "providers") {
|
|
6396
|
-
const { renderRuntimeProviders } = await Promise.resolve().then(function () { return require('./command-
|
|
6591
|
+
const { renderRuntimeProviders } = await Promise.resolve().then(function () { return require('./command-CPlJKXDn.cjs'); });
|
|
6397
6592
|
console.log(renderRuntimeProviders());
|
|
6398
6593
|
return;
|
|
6399
6594
|
}
|
|
@@ -6571,8 +6766,8 @@ function shouldRunMainClaudeFlow(opts) {
|
|
|
6571
6766
|
const projectId = args[3];
|
|
6572
6767
|
try {
|
|
6573
6768
|
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-
|
|
6769
|
+
const { readCredentials: readCredentials2 } = await Promise.resolve().then(function () { return require('./persistence-BeFVx6kI.cjs'); });
|
|
6770
|
+
const { ApiClient: ApiClient2 } = await Promise.resolve().then(function () { return require('./api-CyJG1mr6.cjs'); }).then(function (n) { return n.api; });
|
|
6576
6771
|
let userEmail = void 0;
|
|
6577
6772
|
try {
|
|
6578
6773
|
const credentials = await readCredentials2();
|