happy-imou-cloud 2.1.49 → 2.1.51
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/AcpBackend-CqO3D07V.mjs +2619 -0
- package/dist/AcpBackend-XPiTd6ph.cjs +2621 -0
- package/dist/{BaseReasoningProcessor-Dn9NcoHz.cjs → BaseReasoningProcessor-BD9tiwep.cjs} +1 -144
- package/dist/{BaseReasoningProcessor-CAVeOdyo.mjs → BaseReasoningProcessor-CjlayL2f.mjs} +2 -144
- package/dist/ConversationHistory-Bl2doTA-.cjs +780 -0
- package/dist/ConversationHistory-CI5bBfuA.mjs +771 -0
- package/dist/{ProviderSelectionHandler-BJJc7qOR.cjs → ProviderSelectionHandler-C7GE5QjX.cjs} +6 -6
- package/dist/{ProviderSelectionHandler-DIYidT13.mjs → ProviderSelectionHandler-uQ8jzdzr.mjs} +2 -2
- package/dist/RuntimeShell-BDt42io_.mjs +252 -0
- package/dist/RuntimeShell-D_Te12wq.cjs +258 -0
- package/dist/bootstrapManagedProviderSession-Bln-TwyB.cjs +147 -0
- package/dist/bootstrapManagedProviderSession-D2Z6YU3n.mjs +145 -0
- package/dist/claude-BKNT-2fG.cjs +1080 -0
- package/dist/claude-CnN5WCWj.mjs +1073 -0
- package/dist/codex-DLGP8WF6.mjs +577 -0
- package/dist/codex-Fv2eali8.cjs +582 -0
- package/dist/{command-VcH4hbhi.cjs → command-BWPlJyCN.cjs} +16 -8
- package/dist/{command-CzfRRhVe.mjs → command-CELwsYoG.mjs} +15 -7
- package/dist/config-CFL0Gkqt.cjs +184 -0
- package/dist/config-ChSPe7p9.mjs +174 -0
- package/dist/createDefaultRuntimeShell-BXu3vCvT.cjs +33 -0
- package/dist/createDefaultRuntimeShell-DOg6g3-G.mjs +31 -0
- package/dist/cursor-Blq1cHdr.cjs +91 -0
- package/dist/cursor-CwPNSy_A.mjs +88 -0
- package/dist/future-Dq4Ha1Dn.cjs +24 -0
- package/dist/future-xRdLl3vf.mjs +22 -0
- package/dist/{index-xa1kwZoj.cjs → index-B_JYgMUS.cjs} +189 -5352
- package/dist/{index-7Z93BoVn.mjs → index-CX-F_fuk.mjs} +177 -5331
- package/dist/index.cjs +2 -2
- package/dist/index.mjs +2 -2
- package/dist/installFatalProcessHandlers-0vaw9MAz.mjs +55 -0
- package/dist/installFatalProcessHandlers-CyURn5Bp.cjs +57 -0
- package/dist/launch-BoCCEd5p.mjs +63 -0
- package/dist/launch-wZA5BcvS.cjs +66 -0
- package/dist/lib.cjs +2 -3
- package/dist/lib.d.cts +20 -17
- package/dist/lib.d.mts +20 -17
- package/dist/lib.mjs +1 -2
- package/dist/resolveCommand-B3BGyBE2.mjs +189 -0
- package/dist/resolveCommand-DYMd9PNC.cjs +193 -0
- package/dist/{runClaude-zCwRhpOw.mjs → runClaude-Be0myF9k.mjs} +8 -5
- package/dist/{runClaude-BBGNmGj6.cjs → runClaude-DZJt5er7.cjs} +46 -43
- package/dist/{runCodex-BbgLVjb9.mjs → runCodex-BSnyN4m7.mjs} +226 -117
- package/dist/{runCodex-jUU6U2tZ.cjs → runCodex-DTCcGRue.cjs} +269 -160
- package/dist/runCursor-Bn1PuwJy.cjs +506 -0
- package/dist/runCursor-M6dQ6bGF.mjs +504 -0
- package/dist/{runGemini-DcwNsudA.mjs → runGemini-BNm4vYKA.mjs} +279 -5
- package/dist/{runGemini-C0NT8MHK.cjs → runGemini-Bn3lFhz6.cjs} +309 -35
- package/dist/{registerKillSessionHandler-DLDg2EES.mjs → sessionControl-1bT_7OI6.mjs} +1643 -2405
- package/dist/{registerKillSessionHandler-CfCya6si.cjs → sessionControl-flKnQrx0.cjs} +1647 -2417
- package/dist/{api-DnqaNvyV.mjs → types-B5vtxa38.mjs} +55 -5
- package/dist/{api-D7nAeZi7.cjs → types-CttABk32.cjs} +55 -4
- package/package.json +2 -2
- package/dist/types-CiliQpqS.mjs +0 -52
- package/dist/types-DVk3crez.cjs +0 -54
|
@@ -3,10 +3,13 @@
|
|
|
3
3
|
var ink = require('ink');
|
|
4
4
|
var React = require('react');
|
|
5
5
|
var node_crypto = require('node:crypto');
|
|
6
|
-
var persistence = require('./
|
|
7
|
-
var
|
|
8
|
-
var
|
|
9
|
-
var
|
|
6
|
+
var persistence = require('./types-CttABk32.cjs');
|
|
7
|
+
var ConversationHistory$1 = require('./ConversationHistory-Bl2doTA-.cjs');
|
|
8
|
+
var sessionControl = require('./sessionControl-flKnQrx0.cjs');
|
|
9
|
+
var index = require('./index-B_JYgMUS.cjs');
|
|
10
|
+
var AcpBackend = require('./AcpBackend-XPiTd6ph.cjs');
|
|
11
|
+
var config = require('./config-CFL0Gkqt.cjs');
|
|
12
|
+
var BaseReasoningProcessor = require('./BaseReasoningProcessor-BD9tiwep.cjs');
|
|
10
13
|
require('cross-spawn');
|
|
11
14
|
require('@agentclientprotocol/sdk');
|
|
12
15
|
require('ps-list');
|
|
@@ -15,6 +18,7 @@ require('node:path');
|
|
|
15
18
|
require('node:os');
|
|
16
19
|
require('node:child_process');
|
|
17
20
|
require('node:readline');
|
|
21
|
+
var bootstrapManagedProviderSession = require('./bootstrapManagedProviderSession-Bln-TwyB.cjs');
|
|
18
22
|
require('tweetnacl');
|
|
19
23
|
require('axios');
|
|
20
24
|
require('open');
|
|
@@ -29,7 +33,7 @@ require('socket.io-client');
|
|
|
29
33
|
require('fs/promises');
|
|
30
34
|
require('crypto');
|
|
31
35
|
require('expo-server-sdk');
|
|
32
|
-
require('./
|
|
36
|
+
require('./RuntimeShell-D_Te12wq.cjs');
|
|
33
37
|
require('os');
|
|
34
38
|
require('qrcode-terminal');
|
|
35
39
|
require('node:module');
|
|
@@ -40,6 +44,276 @@ require('http');
|
|
|
40
44
|
require('util');
|
|
41
45
|
require('node:url');
|
|
42
46
|
|
|
47
|
+
const GEMINI_TIMEOUTS = {
|
|
48
|
+
/** Gemini CLI can be slow on first start (downloading models, etc.) */
|
|
49
|
+
init: 12e4,
|
|
50
|
+
/** Gemini ACP can swallow an initialize request sent too early after spawn */
|
|
51
|
+
initDelay: 2500,
|
|
52
|
+
/** Standard tool call timeout */
|
|
53
|
+
toolCall: 10 * 6e4,
|
|
54
|
+
/** Investigation tools (codebase_investigator) can run for a long time */
|
|
55
|
+
investigation: 30 * 6e4,
|
|
56
|
+
/** Think tools are usually quick */
|
|
57
|
+
think: 2 * 6e4,
|
|
58
|
+
/** Idle detection after last message chunk */
|
|
59
|
+
idle: 500
|
|
60
|
+
};
|
|
61
|
+
const GEMINI_TOOL_PATTERNS = [
|
|
62
|
+
{
|
|
63
|
+
name: "save_memory",
|
|
64
|
+
patterns: ["save_memory", "save-memory"],
|
|
65
|
+
inputFields: ["memory", "content"]
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
name: "think",
|
|
69
|
+
patterns: ["think"],
|
|
70
|
+
inputFields: ["thought", "thinking"]
|
|
71
|
+
}
|
|
72
|
+
];
|
|
73
|
+
const AVAILABLE_MODELS = [
|
|
74
|
+
"gemini-2.5-pro",
|
|
75
|
+
"gemini-2.5-flash",
|
|
76
|
+
"gemini-2.5-flash-lite"
|
|
77
|
+
];
|
|
78
|
+
class GeminiTransport {
|
|
79
|
+
agentName = "gemini";
|
|
80
|
+
getTimeoutProfile() {
|
|
81
|
+
return index.resolveAcpSessionPreferences({ agentName: this.agentName }).timeoutProfile;
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Gemini CLI needs 2 minutes for first start (model download, warm-up)
|
|
85
|
+
*/
|
|
86
|
+
getInitTimeout() {
|
|
87
|
+
return index.scaleAcpTimeoutMs(GEMINI_TIMEOUTS.init, "init", this.getTimeoutProfile());
|
|
88
|
+
}
|
|
89
|
+
getInitDelayMs() {
|
|
90
|
+
return GEMINI_TIMEOUTS.initDelay;
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Filter Gemini CLI debug output from stdout.
|
|
94
|
+
*
|
|
95
|
+
* Gemini CLI outputs various debug info (experiments, flags, etc.) to stdout
|
|
96
|
+
* that breaks ACP JSON-RPC parsing. We only keep valid JSON lines.
|
|
97
|
+
*/
|
|
98
|
+
filterStdoutLine(line) {
|
|
99
|
+
const trimmed = line.trim();
|
|
100
|
+
if (!trimmed) {
|
|
101
|
+
return null;
|
|
102
|
+
}
|
|
103
|
+
if (!trimmed.startsWith("{") && !trimmed.startsWith("[")) {
|
|
104
|
+
return null;
|
|
105
|
+
}
|
|
106
|
+
try {
|
|
107
|
+
const parsed = JSON.parse(trimmed);
|
|
108
|
+
if (typeof parsed !== "object" || parsed === null) {
|
|
109
|
+
return null;
|
|
110
|
+
}
|
|
111
|
+
return line;
|
|
112
|
+
} catch {
|
|
113
|
+
return null;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Handle Gemini CLI stderr output.
|
|
118
|
+
*
|
|
119
|
+
* Detects:
|
|
120
|
+
* - Rate limit errors (429) - logged but not shown (CLI handles retries)
|
|
121
|
+
* - Model not found (404) - emit error with available models
|
|
122
|
+
* - Other errors during investigation - logged for debugging
|
|
123
|
+
*/
|
|
124
|
+
handleStderr(text, context) {
|
|
125
|
+
const trimmed = text.trim();
|
|
126
|
+
if (!trimmed) {
|
|
127
|
+
return { message: null, suppress: true };
|
|
128
|
+
}
|
|
129
|
+
if (trimmed.includes("status 429") || trimmed.includes('code":429') || trimmed.includes("rateLimitExceeded") || trimmed.includes("RESOURCE_EXHAUSTED")) {
|
|
130
|
+
return {
|
|
131
|
+
message: null,
|
|
132
|
+
suppress: false
|
|
133
|
+
// Log for debugging but don't show to user
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
if (trimmed.includes("status 404") || trimmed.includes('code":404')) {
|
|
137
|
+
const errorMessage = {
|
|
138
|
+
type: "status",
|
|
139
|
+
status: "error",
|
|
140
|
+
detail: `Model not found. Available models: ${AVAILABLE_MODELS.join(", ")}`
|
|
141
|
+
};
|
|
142
|
+
return { message: errorMessage };
|
|
143
|
+
}
|
|
144
|
+
if (context.hasActiveInvestigation) {
|
|
145
|
+
const hasError = trimmed.includes("timeout") || trimmed.includes("Timeout") || trimmed.includes("failed") || trimmed.includes("Failed") || trimmed.includes("error") || trimmed.includes("Error");
|
|
146
|
+
if (hasError) {
|
|
147
|
+
return { message: null, suppress: false };
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
return { message: null };
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* Gemini-specific tool patterns
|
|
154
|
+
*/
|
|
155
|
+
getToolPatterns() {
|
|
156
|
+
return GEMINI_TOOL_PATTERNS;
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* Check if tool is an investigation tool (needs longer timeout)
|
|
160
|
+
*/
|
|
161
|
+
isInvestigationTool(toolCallId, toolKind) {
|
|
162
|
+
const lowerId = toolCallId.toLowerCase();
|
|
163
|
+
return lowerId.includes("codebase_investigator") || lowerId.includes("investigator") || typeof toolKind === "string" && toolKind.includes("investigator");
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* Get timeout for a tool call
|
|
167
|
+
*/
|
|
168
|
+
getToolCallTimeout(toolCallId, toolKind) {
|
|
169
|
+
if (this.isInvestigationTool(toolCallId, toolKind)) {
|
|
170
|
+
return index.scaleAcpTimeoutMs(GEMINI_TIMEOUTS.investigation, "investigation", this.getTimeoutProfile());
|
|
171
|
+
}
|
|
172
|
+
if (toolKind === "think") {
|
|
173
|
+
return index.scaleAcpTimeoutMs(GEMINI_TIMEOUTS.think, "think", this.getTimeoutProfile());
|
|
174
|
+
}
|
|
175
|
+
return index.scaleAcpTimeoutMs(GEMINI_TIMEOUTS.toolCall, "tool", this.getTimeoutProfile());
|
|
176
|
+
}
|
|
177
|
+
/**
|
|
178
|
+
* Get idle detection timeout
|
|
179
|
+
*/
|
|
180
|
+
getIdleTimeout() {
|
|
181
|
+
return GEMINI_TIMEOUTS.idle;
|
|
182
|
+
}
|
|
183
|
+
/**
|
|
184
|
+
* Extract tool name from toolCallId using Gemini patterns.
|
|
185
|
+
*
|
|
186
|
+
* Tool IDs often contain the tool name as a prefix (e.g., "save_memory-1765385846663" -> "save_memory")
|
|
187
|
+
*/
|
|
188
|
+
extractToolNameFromId(toolCallId) {
|
|
189
|
+
const lowerId = toolCallId.toLowerCase();
|
|
190
|
+
for (const toolPattern of GEMINI_TOOL_PATTERNS) {
|
|
191
|
+
for (const pattern of toolPattern.patterns) {
|
|
192
|
+
if (lowerId.includes(pattern.toLowerCase())) {
|
|
193
|
+
return toolPattern.name;
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
return null;
|
|
198
|
+
}
|
|
199
|
+
/**
|
|
200
|
+
* Check if input is effectively empty
|
|
201
|
+
*/
|
|
202
|
+
isEmptyInput(input) {
|
|
203
|
+
if (!input) return true;
|
|
204
|
+
if (Array.isArray(input)) return input.length === 0;
|
|
205
|
+
if (typeof input === "object") return Object.keys(input).length === 0;
|
|
206
|
+
return false;
|
|
207
|
+
}
|
|
208
|
+
/**
|
|
209
|
+
* Determine the real tool name from various sources.
|
|
210
|
+
*
|
|
211
|
+
* When Gemini sends "other" or "Unknown tool", tries to determine the real name from:
|
|
212
|
+
* 1. toolCallId patterns (most reliable - tool name often embedded in ID)
|
|
213
|
+
* 2. Input field signatures (specific fields indicate specific tools)
|
|
214
|
+
* 3. Empty input default (some tools like think have empty input)
|
|
215
|
+
*
|
|
216
|
+
* Context-based heuristics were removed as they were fragile and the above
|
|
217
|
+
* methods cover all known cases.
|
|
218
|
+
*/
|
|
219
|
+
determineToolName(toolName, toolCallId, input, _context) {
|
|
220
|
+
if (toolName !== "other" && toolName !== "Unknown tool") {
|
|
221
|
+
return toolName;
|
|
222
|
+
}
|
|
223
|
+
const idToolName = this.extractToolNameFromId(toolCallId);
|
|
224
|
+
if (idToolName) {
|
|
225
|
+
return idToolName;
|
|
226
|
+
}
|
|
227
|
+
if (input && typeof input === "object" && !Array.isArray(input)) {
|
|
228
|
+
const inputKeys = Object.keys(input);
|
|
229
|
+
for (const toolPattern of GEMINI_TOOL_PATTERNS) {
|
|
230
|
+
if (toolPattern.inputFields) {
|
|
231
|
+
const hasMatchingField = toolPattern.inputFields.some(
|
|
232
|
+
(field) => inputKeys.some((key) => key.toLowerCase() === field.toLowerCase())
|
|
233
|
+
);
|
|
234
|
+
if (hasMatchingField) {
|
|
235
|
+
return toolPattern.name;
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
if (this.isEmptyInput(input) && toolName === "other") {
|
|
241
|
+
const defaultTool = GEMINI_TOOL_PATTERNS.find((p) => p.emptyInputDefault);
|
|
242
|
+
if (defaultTool) {
|
|
243
|
+
return defaultTool.name;
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
if (toolName === "other" || toolName === "Unknown tool") {
|
|
247
|
+
const inputKeys = input && typeof input === "object" ? Object.keys(input) : [];
|
|
248
|
+
persistence.logger.debug(
|
|
249
|
+
`[GeminiTransport] Unknown tool pattern - toolCallId: "${toolCallId}", toolName: "${toolName}", inputKeys: [${inputKeys.join(", ")}]. Consider adding a new pattern to GEMINI_TOOL_PATTERNS if this tool appears frequently.`
|
|
250
|
+
);
|
|
251
|
+
}
|
|
252
|
+
return toolName;
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
const geminiTransport = new GeminiTransport();
|
|
256
|
+
|
|
257
|
+
function createGeminiBackend(options) {
|
|
258
|
+
const localConfig = config.readGeminiLocalConfig();
|
|
259
|
+
let apiKey = options.cloudToken || localConfig.token || process.env[config.GEMINI_API_KEY_ENV] || process.env[config.GOOGLE_API_KEY_ENV] || options.apiKey;
|
|
260
|
+
if (!apiKey) {
|
|
261
|
+
persistence.logger.warn(`[Gemini] No API key found. Run 'happy connect gemini' to authenticate via Google OAuth, or set ${config.GEMINI_API_KEY_ENV} environment variable.`);
|
|
262
|
+
}
|
|
263
|
+
const geminiCommand = "gemini";
|
|
264
|
+
const model = config.determineGeminiModel(options.model, localConfig);
|
|
265
|
+
const geminiArgs = ["--experimental-acp"];
|
|
266
|
+
let googleCloudProject = null;
|
|
267
|
+
if (localConfig.googleCloudProject) {
|
|
268
|
+
const storedEmail = localConfig.googleCloudProjectEmail;
|
|
269
|
+
const currentEmail = options.currentUserEmail;
|
|
270
|
+
if (!storedEmail || storedEmail === currentEmail) {
|
|
271
|
+
googleCloudProject = localConfig.googleCloudProject;
|
|
272
|
+
persistence.logger.debug(`[Gemini] Using Google Cloud Project: ${googleCloudProject}${storedEmail ? ` (for ${storedEmail})` : " (global)"}`);
|
|
273
|
+
} else {
|
|
274
|
+
persistence.logger.debug(`[Gemini] Skipping stored Google Cloud Project (stored for ${storedEmail}, current user is ${currentEmail || "unknown"})`);
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
const backendOptions = {
|
|
278
|
+
agentName: "gemini",
|
|
279
|
+
cwd: options.cwd,
|
|
280
|
+
command: geminiCommand,
|
|
281
|
+
args: geminiArgs,
|
|
282
|
+
env: {
|
|
283
|
+
...options.env,
|
|
284
|
+
...apiKey ? { [config.GEMINI_API_KEY_ENV]: apiKey, [config.GOOGLE_API_KEY_ENV]: apiKey } : {},
|
|
285
|
+
// Pass model via env var - gemini CLI reads GEMINI_MODEL automatically
|
|
286
|
+
[config.GEMINI_MODEL_ENV]: model,
|
|
287
|
+
// Pass Google Cloud Project for Workspace accounts
|
|
288
|
+
...googleCloudProject ? {
|
|
289
|
+
GOOGLE_CLOUD_PROJECT: googleCloudProject,
|
|
290
|
+
GOOGLE_CLOUD_PROJECT_ID: googleCloudProject
|
|
291
|
+
} : {},
|
|
292
|
+
// Suppress debug output from gemini CLI to avoid stdout pollution
|
|
293
|
+
NODE_ENV: "production",
|
|
294
|
+
DEBUG: ""
|
|
295
|
+
},
|
|
296
|
+
mcpServers: options.mcpServers,
|
|
297
|
+
permissionHandler: options.permissionHandler,
|
|
298
|
+
transportHandler: geminiTransport
|
|
299
|
+
};
|
|
300
|
+
const modelSource = config.getGeminiModelSource(options.model, localConfig);
|
|
301
|
+
persistence.logger.debug("[Gemini] Creating ACP SDK backend with options:", {
|
|
302
|
+
cwd: backendOptions.cwd,
|
|
303
|
+
command: backendOptions.command,
|
|
304
|
+
args: backendOptions.args,
|
|
305
|
+
hasApiKey: !!apiKey,
|
|
306
|
+
model,
|
|
307
|
+
modelSource,
|
|
308
|
+
mcpServerCount: options.mcpServers ? Object.keys(options.mcpServers).length : 0
|
|
309
|
+
});
|
|
310
|
+
return {
|
|
311
|
+
backend: new AcpBackend.AcpBackend(backendOptions),
|
|
312
|
+
model,
|
|
313
|
+
modelSource
|
|
314
|
+
};
|
|
315
|
+
}
|
|
316
|
+
|
|
43
317
|
const GeminiDisplay = ({ messageBuffer, logPath, currentModel, onExit }) => {
|
|
44
318
|
const [messages, setMessages] = React.useState([]);
|
|
45
319
|
const [confirmationMode, setConfirmationMode] = React.useState(false);
|
|
@@ -183,7 +457,7 @@ const GeminiDisplay = ({ messageBuffer, logPath, currentModel, onExit }) => {
|
|
|
183
457
|
));
|
|
184
458
|
};
|
|
185
459
|
|
|
186
|
-
class GeminiPermissionHandler extends
|
|
460
|
+
class GeminiPermissionHandler extends sessionControl.BasePermissionHandler {
|
|
187
461
|
currentPermissionMode = "default";
|
|
188
462
|
constructor(session) {
|
|
189
463
|
super(session);
|
|
@@ -420,7 +694,7 @@ function formatOptionsXml(options) {
|
|
|
420
694
|
return "\n<options>\n" + options.map((opt) => ` <option>${opt}</option>`).join("\n") + "\n</options>";
|
|
421
695
|
}
|
|
422
696
|
|
|
423
|
-
class ConversationHistory extends
|
|
697
|
+
class ConversationHistory extends ConversationHistory$1.ConversationHistory {
|
|
424
698
|
currentModel;
|
|
425
699
|
setCurrentModel(model) {
|
|
426
700
|
this.currentModel = model;
|
|
@@ -489,7 +763,7 @@ ${originalUserMessage}`;
|
|
|
489
763
|
function bindGeminiUserMessageQueue(opts) {
|
|
490
764
|
let currentState = { ...opts.initialState };
|
|
491
765
|
opts.session.onUserMessage((message) => {
|
|
492
|
-
const happyOrgResult = opts.happyOrg ?
|
|
766
|
+
const happyOrgResult = opts.happyOrg ? sessionControl.resolveHappyOrgQueuedTurn({
|
|
493
767
|
metadata: opts.happyOrg.getMetadata(),
|
|
494
768
|
message,
|
|
495
769
|
sessionId: opts.happyOrg.getSessionId?.() ?? null
|
|
@@ -547,12 +821,12 @@ async function runGemini(opts) {
|
|
|
547
821
|
const api = await persistence.ApiClient.create(opts.credentials);
|
|
548
822
|
let machineId;
|
|
549
823
|
try {
|
|
550
|
-
machineId = await
|
|
824
|
+
machineId = await sessionControl.ensureManagedProviderMachine({
|
|
551
825
|
api,
|
|
552
826
|
missingMachineIdMessage: "[START] No machine ID found in settings, which is unexpected since authAndSetupMachineIfNeeded should have created it. Please report this issue on https://github.com/slopus/happy-cli/issues"
|
|
553
827
|
});
|
|
554
828
|
} catch (error) {
|
|
555
|
-
if (error instanceof
|
|
829
|
+
if (error instanceof sessionControl.MissingMachineIdError) {
|
|
556
830
|
console.error(error.message);
|
|
557
831
|
process.exit(1);
|
|
558
832
|
}
|
|
@@ -600,7 +874,7 @@ async function runGemini(opts) {
|
|
|
600
874
|
pendingSessionSwap = null;
|
|
601
875
|
}
|
|
602
876
|
};
|
|
603
|
-
const { metadata, session: initialSession, reconnectionHandle } = await
|
|
877
|
+
const { metadata, session: initialSession, reconnectionHandle } = await bootstrapManagedProviderSession.bootstrapManagedProviderSession({
|
|
604
878
|
api,
|
|
605
879
|
sessionTag,
|
|
606
880
|
flavor: "gemini",
|
|
@@ -618,12 +892,12 @@ async function runGemini(opts) {
|
|
|
618
892
|
}
|
|
619
893
|
bindSessionTranscriptHistory?.(newSession);
|
|
620
894
|
}
|
|
621
|
-
void
|
|
895
|
+
void sessionControl.syncControlledByUserState(newSession, false);
|
|
622
896
|
}
|
|
623
897
|
});
|
|
624
898
|
session = initialSession;
|
|
625
|
-
await
|
|
626
|
-
const messageQueue = new
|
|
899
|
+
await sessionControl.syncControlledByUserState(session, false);
|
|
900
|
+
const messageQueue = new sessionControl.MessageQueue2((mode) => persistence.hashObject({
|
|
627
901
|
permissionMode: mode.permissionMode,
|
|
628
902
|
model: mode.model,
|
|
629
903
|
happyOrg: mode.happyOrg ? {
|
|
@@ -652,7 +926,7 @@ async function runGemini(opts) {
|
|
|
652
926
|
return;
|
|
653
927
|
}
|
|
654
928
|
try {
|
|
655
|
-
const notification =
|
|
929
|
+
const notification = ConversationHistory$1.buildReadyPushNotification({
|
|
656
930
|
providerLabel: "Gemini",
|
|
657
931
|
metadata: session.getMetadataSnapshot?.() ?? null,
|
|
658
932
|
sessionId: session.sessionId
|
|
@@ -740,10 +1014,10 @@ async function runGemini(opts) {
|
|
|
740
1014
|
}
|
|
741
1015
|
};
|
|
742
1016
|
session.rpcHandlerManager.registerHandler("abort", handleAbort);
|
|
743
|
-
|
|
1017
|
+
sessionControl.registerKillSessionHandler(session.rpcHandlerManager, handleKillSession);
|
|
744
1018
|
const hasTTY = process.stdout.isTTY && process.stdin.isTTY;
|
|
745
|
-
const messageBuffer = new
|
|
746
|
-
const renderSessionTranscript =
|
|
1019
|
+
const messageBuffer = new ConversationHistory$1.MessageBuffer({ enabled: hasTTY });
|
|
1020
|
+
const renderSessionTranscript = ConversationHistory$1.createSessionTranscriptInkRenderer({ messageBuffer });
|
|
747
1021
|
let inkInstance = null;
|
|
748
1022
|
bindSessionTranscriptHistory = (nextSession) => {
|
|
749
1023
|
if (typeof nextSession.onSessionMessage !== "function") {
|
|
@@ -757,9 +1031,9 @@ async function runGemini(opts) {
|
|
|
757
1031
|
});
|
|
758
1032
|
};
|
|
759
1033
|
bindSessionTranscriptHistory(session);
|
|
760
|
-
let displayedModel =
|
|
761
|
-
const localConfig =
|
|
762
|
-
persistence.logger.debug(`[gemini] Initial model setup: env[GEMINI_MODEL_ENV]=${process.env[
|
|
1034
|
+
let displayedModel = config.getInitialGeminiModel();
|
|
1035
|
+
const localConfig = config.readGeminiLocalConfig();
|
|
1036
|
+
persistence.logger.debug(`[gemini] Initial model setup: env[GEMINI_MODEL_ENV]=${process.env[config.GEMINI_MODEL_ENV] || "not set"}, localConfig=${localConfig.model || "not set"}, displayedModel=${displayedModel}`);
|
|
763
1037
|
const updateDisplayedModel = (model, saveToConfig = false) => {
|
|
764
1038
|
if (model === void 0) {
|
|
765
1039
|
persistence.logger.debug(`[gemini] updateDisplayedModel called with undefined, skipping update`);
|
|
@@ -769,7 +1043,7 @@ async function runGemini(opts) {
|
|
|
769
1043
|
displayedModel = model;
|
|
770
1044
|
persistence.logger.debug(`[gemini] updateDisplayedModel called: oldModel=${oldModel}, newModel=${model}, saveToConfig=${saveToConfig}`);
|
|
771
1045
|
if (saveToConfig) {
|
|
772
|
-
|
|
1046
|
+
config.saveGeminiModelToConfig(model);
|
|
773
1047
|
}
|
|
774
1048
|
if (hasTTY && oldModel !== model) {
|
|
775
1049
|
persistence.logger.debug(`[gemini] Adding model update message to buffer: [MODEL:${model}]`);
|
|
@@ -972,7 +1246,7 @@ async function runGemini(opts) {
|
|
|
972
1246
|
};
|
|
973
1247
|
function setupGeminiMessageHandler(activeRuntimeHandle) {
|
|
974
1248
|
const forwardAgentMessage = (agentMessage) => {
|
|
975
|
-
|
|
1249
|
+
sessionControl.forwardAgentMessageToProviderSession(agentMessage, {
|
|
976
1250
|
provider: "gemini",
|
|
977
1251
|
send: (body) => session.sendAgentMessage("gemini", body)
|
|
978
1252
|
});
|
|
@@ -1065,7 +1339,7 @@ Guide: https://goo.gle/gemini-cli-auth-docs#workspace-gca`;
|
|
|
1065
1339
|
forwardAgentMessage(msg);
|
|
1066
1340
|
break;
|
|
1067
1341
|
case "tool-result":
|
|
1068
|
-
const isError =
|
|
1342
|
+
const isError = sessionControl.inferToolResultError(msg.result);
|
|
1069
1343
|
const resultText = typeof msg.result === "string" ? msg.result.substring(0, 200) : JSON.stringify(msg.result).substring(0, 200);
|
|
1070
1344
|
const truncatedResult = resultText + (typeof msg.result === "string" && msg.result.length > 200 ? "..." : "");
|
|
1071
1345
|
const resultSize = typeof msg.result === "string" ? msg.result.length : JSON.stringify(msg.result).length;
|
|
@@ -1091,12 +1365,12 @@ Guide: https://goo.gle/gemini-cli-auth-docs#workspace-gca`;
|
|
|
1091
1365
|
forwardAgentMessage(msg);
|
|
1092
1366
|
break;
|
|
1093
1367
|
case "terminal-output": {
|
|
1094
|
-
const terminalOutput =
|
|
1368
|
+
const terminalOutput = sessionControl.renderTerminalOutputPreview(msg.data);
|
|
1095
1369
|
if (!terminalOutput) {
|
|
1096
1370
|
break;
|
|
1097
1371
|
}
|
|
1098
1372
|
messageBuffer.addMessage(terminalOutput, "result");
|
|
1099
|
-
const forwardedOutput =
|
|
1373
|
+
const forwardedOutput = sessionControl.prepareTerminalOutputForForwarding(msg.data);
|
|
1100
1374
|
if (forwardedOutput) {
|
|
1101
1375
|
forwardAgentMessage({
|
|
1102
1376
|
...msg,
|
|
@@ -1107,8 +1381,8 @@ Guide: https://goo.gle/gemini-cli-auth-docs#workspace-gca`;
|
|
|
1107
1381
|
}
|
|
1108
1382
|
case "permission-request":
|
|
1109
1383
|
try {
|
|
1110
|
-
const permissionRequest =
|
|
1111
|
-
const notification =
|
|
1384
|
+
const permissionRequest = ConversationHistory$1.extractPermissionRequestPushContext(msg);
|
|
1385
|
+
const notification = ConversationHistory$1.buildPermissionPushNotification({
|
|
1112
1386
|
providerLabel: "Gemini",
|
|
1113
1387
|
metadata: session.getMetadataSnapshot?.() ?? null,
|
|
1114
1388
|
sessionId: session.sessionId,
|
|
@@ -1185,11 +1459,11 @@ Guide: https://goo.gle/gemini-cli-auth-docs#workspace-gca`;
|
|
|
1185
1459
|
const modelToUse = mode.model === void 0 ? void 0 : mode.model || null;
|
|
1186
1460
|
let backendResult;
|
|
1187
1461
|
updatePermissionMode(mode.permissionMode);
|
|
1188
|
-
const { session: nextRuntimeHandle, factoryResult } = await
|
|
1462
|
+
const { session: nextRuntimeHandle, factoryResult } = await ConversationHistory$1.launchRuntimeHandleWithFactoryResult({
|
|
1189
1463
|
provider: "gemini",
|
|
1190
1464
|
cwd: process.cwd(),
|
|
1191
1465
|
createBackendResult: (opts2) => {
|
|
1192
|
-
const createdBackendResult =
|
|
1466
|
+
const createdBackendResult = createGeminiBackend({
|
|
1193
1467
|
...opts2,
|
|
1194
1468
|
mcpServers: {},
|
|
1195
1469
|
permissionHandler,
|
|
@@ -1294,7 +1568,7 @@ Guide: https://goo.gle/gemini-cli-auth-docs#workspace-gca`;
|
|
|
1294
1568
|
persistence.logger.debug(`[gemini] Injected conversation history context (${historyContext.length} chars)`);
|
|
1295
1569
|
}
|
|
1296
1570
|
if (message.mode.happyOrg) {
|
|
1297
|
-
promptToSend =
|
|
1571
|
+
promptToSend = sessionControl.buildHappyOrgTurnPrompt(promptToSend, message.mode.happyOrg);
|
|
1298
1572
|
}
|
|
1299
1573
|
conversationHistory.addUserMessage(userMessageToShow);
|
|
1300
1574
|
persistence.logger.debug(`[gemini] Sending prompt to Gemini (length: ${promptToSend.length}): ${promptToSend.substring(0, 100)}...`);
|
|
@@ -1306,7 +1580,7 @@ Guide: https://goo.gle/gemini-cli-auth-docs#workspace-gca`;
|
|
|
1306
1580
|
try {
|
|
1307
1581
|
await activeHandle.sendPrompt(promptToSend);
|
|
1308
1582
|
persistence.logger.debug("[gemini] Prompt sent successfully");
|
|
1309
|
-
await
|
|
1583
|
+
await sessionControl.waitForResponseCompleteWithAbort(activeHandle.backend, abortController.signal);
|
|
1310
1584
|
persistence.logger.debug("[gemini] Response complete");
|
|
1311
1585
|
shouldInjectHistoryOnNextSession = false;
|
|
1312
1586
|
break;
|
|
@@ -1404,7 +1678,7 @@ Guide: https://goo.gle/gemini-cli-auth-docs#workspace-gca`;
|
|
|
1404
1678
|
permissionHandler.reset();
|
|
1405
1679
|
reasoningProcessor.abort();
|
|
1406
1680
|
diffProcessor.reset();
|
|
1407
|
-
const finalizedTurn = await
|
|
1681
|
+
const finalizedTurn = await sessionControl.finalizeHappyOrgTurnWithBusinessAck({
|
|
1408
1682
|
metadata: session.getMetadataSnapshot?.() ?? null,
|
|
1409
1683
|
queuedTurn: message.mode.happyOrg,
|
|
1410
1684
|
responseText: accumulatedResponse,
|
|
@@ -1446,7 +1720,7 @@ Guide: https://goo.gle/gemini-cli-auth-docs#workspace-gca`;
|
|
|
1446
1720
|
session.sendAgentMessage("gemini", messagePayload);
|
|
1447
1721
|
if (!shouldExit) {
|
|
1448
1722
|
try {
|
|
1449
|
-
const notification =
|
|
1723
|
+
const notification = ConversationHistory$1.buildTurnResultPushNotification({
|
|
1450
1724
|
providerLabel: "Gemini",
|
|
1451
1725
|
metadata: finalizedTurn.nextMetadata ?? session.getMetadataSnapshot?.() ?? null,
|
|
1452
1726
|
sessionId: session.sessionId,
|
|
@@ -1469,7 +1743,7 @@ Guide: https://goo.gle/gemini-cli-auth-docs#workspace-gca`;
|
|
|
1469
1743
|
isResponseInProgress = false;
|
|
1470
1744
|
} else if (!shouldExit && finalizedTurn.report) {
|
|
1471
1745
|
try {
|
|
1472
|
-
const notification =
|
|
1746
|
+
const notification = ConversationHistory$1.buildTurnResultPushNotification({
|
|
1473
1747
|
providerLabel: "Gemini",
|
|
1474
1748
|
metadata: finalizedTurn.nextMetadata ?? session.getMetadataSnapshot?.() ?? null,
|
|
1475
1749
|
sessionId: session.sessionId,
|