very-happy-cli 0.2.137 → 0.2.139
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-POcimRNQ.mjs → AcpBackend-BwTEBAyP.mjs} +2 -2
- package/dist/{AcpBackend-Bcmm51Ya.cjs → AcpBackend-ioCPQLt4.cjs} +2 -2
- package/dist/{AcpSessionManager-D54Juu2-.mjs → AcpSessionManager-Bh3KETfz.mjs} +1 -1
- package/dist/{AcpSessionManager-CjrwSZbh.cjs → AcpSessionManager-o9T6W69-.cjs} +1 -1
- package/dist/{agentGuidance-DulugsMk.mjs → agentGuidance-DRnXdFAY.mjs} +1 -1
- package/dist/{agentGuidance-D1tKg2UW.cjs → agentGuidance-Dxt2uz3R.cjs} +1 -1
- package/dist/codex/happyMcpStdioBridge.cjs +2 -2
- package/dist/codex/happyMcpStdioBridge.mjs +2 -2
- package/dist/{config-Dr3A4IGp.cjs → config-nyMHCx-i.cjs} +4 -4
- package/dist/{config-C1gQprK_.mjs → config-o9NFsj8x.mjs} +4 -4
- package/dist/{index-D5MRxCHs.mjs → index-BZr5l8TH.mjs} +185 -230
- package/dist/{index-B11rFE7f.mjs → index-BkmfJyCf.mjs} +7 -7
- package/dist/{index-B0KIJdSt.cjs → index-C3NtU4Ch.cjs} +216 -266
- package/dist/{index-C3agc8KT.mjs → index-CTemcNko.mjs} +4 -4
- package/dist/{index-hGg5G5uO.cjs → index-gkFhwPXq.cjs} +4 -4
- package/dist/{index-C3JqT3Ql.cjs → index-klhxcpC8.cjs} +7 -7
- package/dist/index.cjs +4 -4
- package/dist/index.mjs +4 -4
- package/dist/{installTerminalHooks-DfZTXVWO.mjs → installTerminalHooks-8CHTgUC-.mjs} +4 -4
- package/dist/{installTerminalHooks-Culr259-.cjs → installTerminalHooks-DZUBgnFh.cjs} +4 -4
- package/dist/lib.cjs +2 -2
- package/dist/lib.d.cts +21 -0
- package/dist/lib.d.mts +21 -0
- package/dist/lib.mjs +2 -2
- package/dist/{limits-CJrrAhB4.cjs → limits-C_RGzva6.cjs} +26 -7
- package/dist/{limits-CAD4UF8w.mjs → limits-DefXc1TL.mjs} +26 -8
- package/dist/{mcp-CdnZbYKV.mjs → mcp-8DcunR0J.mjs} +19 -19
- package/dist/{mcp-5Jf6V4eb.cjs → mcp-czNIfD59.cjs} +21 -21
- package/dist/{runGemini-CwWEorS7.mjs → runGemini-CDUObQTD.mjs} +6 -6
- package/dist/{runGemini-GjBPzXEt.cjs → runGemini-Dy3y-lD9.cjs} +7 -7
- package/dist/{runOpenClaw-BZHHy9T7.mjs → runOpenClaw-B6KMCsVB.mjs} +5 -5
- package/dist/{runOpenClaw-DGe5c571.cjs → runOpenClaw-CJusckVM.cjs} +6 -6
- package/dist/{send-teYpfTtw.cjs → send-B4Qo-87h.cjs} +4 -4
- package/dist/{send-BN2PncAH.mjs → send-BT32Jiel.mjs} +4 -4
- package/dist/{sessions-qP1YUf5E.cjs → sessions-CN2y0xBl.cjs} +4 -4
- package/dist/{sessions-TLUfYdLX.mjs → sessions-Dh0Lg-5z.mjs} +4 -4
- package/dist/{spawn-D3P8wJ_r.mjs → spawn-DFIyobCt.mjs} +6 -6
- package/dist/{spawn-GekaZ7h2.cjs → spawn-jWj3xFhX.cjs} +8 -8
- package/dist/{teams-BSqAW2S5.cjs → teams-BhFspeAY.cjs} +4 -4
- package/dist/{teams-WSjEXh4d.mjs → teams-CZ9ICWeB.mjs} +4 -4
- package/dist/{todo-DsnXWl77.cjs → todo-B0kvqUTQ.cjs} +3 -3
- package/dist/{todo-BblDgT77.mjs → todo-jL3ttna3.mjs} +3 -3
- package/dist/{types-B8g_V-LQ.mjs → types-CrKeJuyF.mjs} +616 -13
- package/dist/{types-BAhQF6Xp.cjs → types-CxGm_YJ-.cjs} +629 -13
- package/package.json +7 -7
|
@@ -3,13 +3,13 @@
|
|
|
3
3
|
var chalk = require('chalk');
|
|
4
4
|
var os = require('node:os');
|
|
5
5
|
var node_crypto = require('node:crypto');
|
|
6
|
-
var api = require('./types-
|
|
7
|
-
var persistence = require('./limits-
|
|
6
|
+
var api = require('./types-CxGm_YJ-.cjs');
|
|
7
|
+
var persistence = require('./limits-C_RGzva6.cjs');
|
|
8
8
|
var spawn = require('cross-spawn');
|
|
9
9
|
var path = require('node:path');
|
|
10
10
|
var node_readline = require('node:readline');
|
|
11
11
|
var node_fs = require('node:fs');
|
|
12
|
-
var agentGuidance = require('./agentGuidance-
|
|
12
|
+
var agentGuidance = require('./agentGuidance-Dxt2uz3R.cjs');
|
|
13
13
|
var promises = require('node:fs/promises');
|
|
14
14
|
var fs = require('fs/promises');
|
|
15
15
|
var ink = require('ink');
|
|
@@ -115,212 +115,6 @@ function withoutServerSnapshot(response) {
|
|
|
115
115
|
return { ...response, metadataVersion: 0, agentStateVersion: 0 };
|
|
116
116
|
}
|
|
117
117
|
|
|
118
|
-
function daemonControlHeaders(controlToken) {
|
|
119
|
-
return {
|
|
120
|
-
"Content-Type": "application/json",
|
|
121
|
-
...controlToken ? { Authorization: `Bearer ${controlToken}` } : {}
|
|
122
|
-
};
|
|
123
|
-
}
|
|
124
|
-
async function daemonPost(path, body) {
|
|
125
|
-
const state = await persistence.readDaemonState();
|
|
126
|
-
if (!state?.httpPort) {
|
|
127
|
-
const errorMessage = "No daemon running, no state file found";
|
|
128
|
-
persistence.logger.debug(`[CONTROL CLIENT] ${errorMessage}`);
|
|
129
|
-
return {
|
|
130
|
-
error: errorMessage
|
|
131
|
-
};
|
|
132
|
-
}
|
|
133
|
-
try {
|
|
134
|
-
process.kill(state.pid, 0);
|
|
135
|
-
} catch (error) {
|
|
136
|
-
const errorMessage = "Daemon is not running, file is stale";
|
|
137
|
-
persistence.logger.debug(`[CONTROL CLIENT] ${errorMessage}`);
|
|
138
|
-
return {
|
|
139
|
-
error: errorMessage
|
|
140
|
-
};
|
|
141
|
-
}
|
|
142
|
-
try {
|
|
143
|
-
const timeout = process.env.HAPPY_DAEMON_HTTP_TIMEOUT ? parseInt(process.env.HAPPY_DAEMON_HTTP_TIMEOUT) : 1e4;
|
|
144
|
-
const response = await fetch(`http://127.0.0.1:${state.httpPort}${path}`, {
|
|
145
|
-
method: "POST",
|
|
146
|
-
// A state written by an old daemon has no token and must remain callable;
|
|
147
|
-
// a new daemon always writes one and rejects requests without it.
|
|
148
|
-
headers: daemonControlHeaders(state.controlToken),
|
|
149
|
-
body: JSON.stringify(body || {}),
|
|
150
|
-
// Mostly increased for stress test
|
|
151
|
-
signal: AbortSignal.timeout(timeout)
|
|
152
|
-
});
|
|
153
|
-
if (!response.ok) {
|
|
154
|
-
const failure = await response.json().catch(() => null);
|
|
155
|
-
const reason = typeof failure?.error === "string" && failure.error ? failure.error : `HTTP ${response.status}`;
|
|
156
|
-
const errorMessage = `Request failed: ${path}, ${reason}`;
|
|
157
|
-
persistence.logger.debug(`[CONTROL CLIENT] ${errorMessage}`);
|
|
158
|
-
return {
|
|
159
|
-
error: errorMessage
|
|
160
|
-
};
|
|
161
|
-
}
|
|
162
|
-
return await response.json();
|
|
163
|
-
} catch (error) {
|
|
164
|
-
const errorMessage = `Request failed: ${path}, ${error instanceof Error ? error.message : "Unknown error"}`;
|
|
165
|
-
persistence.logger.debug(`[CONTROL CLIENT] ${errorMessage}`);
|
|
166
|
-
return {
|
|
167
|
-
error: errorMessage
|
|
168
|
-
};
|
|
169
|
-
}
|
|
170
|
-
}
|
|
171
|
-
const SESSION_STARTED_RETRY_TIMEOUT_MS = 3e3;
|
|
172
|
-
const SESSION_STARTED_RETRY_INTERVAL_MS = 100;
|
|
173
|
-
async function notifyDaemonSessionStarted(sessionId, metadata, encryption) {
|
|
174
|
-
const payload = { sessionId, metadata, encryption };
|
|
175
|
-
const deadline = Date.now() + SESSION_STARTED_RETRY_TIMEOUT_MS;
|
|
176
|
-
let result;
|
|
177
|
-
while (true) {
|
|
178
|
-
result = await daemonPost("/session-started", payload);
|
|
179
|
-
if (!result?.error) {
|
|
180
|
-
return result;
|
|
181
|
-
}
|
|
182
|
-
if (Date.now() >= deadline) {
|
|
183
|
-
return result;
|
|
184
|
-
}
|
|
185
|
-
await new Promise((resolve) => setTimeout(resolve, SESSION_STARTED_RETRY_INTERVAL_MS));
|
|
186
|
-
}
|
|
187
|
-
}
|
|
188
|
-
async function listDaemonSessions() {
|
|
189
|
-
const result = await daemonPost("/list");
|
|
190
|
-
return result.children || [];
|
|
191
|
-
}
|
|
192
|
-
async function stopDaemonSession(sessionId) {
|
|
193
|
-
const result = await daemonPost("/stop-session", { sessionId });
|
|
194
|
-
return result.success || false;
|
|
195
|
-
}
|
|
196
|
-
async function spawnDaemonSession(directory, sessionId, opts) {
|
|
197
|
-
const result = await daemonPost("/spawn-session", {
|
|
198
|
-
directory,
|
|
199
|
-
sessionId,
|
|
200
|
-
spawnedBy: opts?.spawnedBy,
|
|
201
|
-
permissionMode: opts?.permissionMode,
|
|
202
|
-
agent: opts?.agent,
|
|
203
|
-
environmentVariables: opts?.environmentVariables
|
|
204
|
-
});
|
|
205
|
-
return result;
|
|
206
|
-
}
|
|
207
|
-
async function notifyDaemonSessionEvent(sessionId, event, spawnedBy) {
|
|
208
|
-
return daemonPost("/session-event", { sessionId, event, spawnedBy });
|
|
209
|
-
}
|
|
210
|
-
async function notifyDaemonClaudeAuthFailed(sessionId) {
|
|
211
|
-
return daemonPost("/session-event", { sessionId, event: "auth_failed" });
|
|
212
|
-
}
|
|
213
|
-
async function stopDaemonHttp() {
|
|
214
|
-
await daemonPost("/stop");
|
|
215
|
-
}
|
|
216
|
-
async function pushClipboardViaDaemon(text) {
|
|
217
|
-
const result = await daemonPost("/clipboard", { text });
|
|
218
|
-
if (result?.error && result.delivered === void 0) {
|
|
219
|
-
return { delivered: false, error: result.error };
|
|
220
|
-
}
|
|
221
|
-
return result;
|
|
222
|
-
}
|
|
223
|
-
async function setTerminalTitleViaDaemon(terminalId, title, ifAbsent = false) {
|
|
224
|
-
const result = await daemonPost("/terminal-title", { terminalId, title, ifAbsent });
|
|
225
|
-
if (result?.error) {
|
|
226
|
-
return { ok: false, error: result.error };
|
|
227
|
-
}
|
|
228
|
-
return { ok: result?.status === "ok", error: result?.status === "ok" ? void 0 : "unexpected daemon response" };
|
|
229
|
-
}
|
|
230
|
-
async function checkIfDaemonRunningAndCleanupStaleState() {
|
|
231
|
-
const state = await persistence.readDaemonState();
|
|
232
|
-
if (!state) {
|
|
233
|
-
return false;
|
|
234
|
-
}
|
|
235
|
-
try {
|
|
236
|
-
process.kill(state.pid, 0);
|
|
237
|
-
} catch {
|
|
238
|
-
persistence.logger.debug("[DAEMON RUN] Daemon PID not running, cleaning up state");
|
|
239
|
-
await cleanupDaemonState();
|
|
240
|
-
return false;
|
|
241
|
-
}
|
|
242
|
-
if (state.httpPort) {
|
|
243
|
-
try {
|
|
244
|
-
const response = await fetch(`http://127.0.0.1:${state.httpPort}/list`, {
|
|
245
|
-
method: "POST",
|
|
246
|
-
headers: daemonControlHeaders(state.controlToken),
|
|
247
|
-
body: "{}",
|
|
248
|
-
signal: AbortSignal.timeout(2e3)
|
|
249
|
-
});
|
|
250
|
-
if (response.ok) {
|
|
251
|
-
return true;
|
|
252
|
-
}
|
|
253
|
-
} catch {
|
|
254
|
-
persistence.logger.debug(`[DAEMON RUN] PID ${state.pid} is alive but HTTP health check failed on port ${state.httpPort}, cleaning up stale state`);
|
|
255
|
-
await cleanupDaemonState();
|
|
256
|
-
return false;
|
|
257
|
-
}
|
|
258
|
-
}
|
|
259
|
-
return true;
|
|
260
|
-
}
|
|
261
|
-
async function isDaemonRunningCurrentlyInstalledHappyVersion() {
|
|
262
|
-
persistence.logger.debug("[DAEMON CONTROL] Checking if daemon is running same version");
|
|
263
|
-
const runningDaemon = await checkIfDaemonRunningAndCleanupStaleState();
|
|
264
|
-
if (!runningDaemon) {
|
|
265
|
-
persistence.logger.debug("[DAEMON CONTROL] No daemon running, returning false");
|
|
266
|
-
return false;
|
|
267
|
-
}
|
|
268
|
-
const state = await persistence.readDaemonState();
|
|
269
|
-
if (!state) {
|
|
270
|
-
persistence.logger.debug("[DAEMON CONTROL] No daemon state found, returning false");
|
|
271
|
-
return false;
|
|
272
|
-
}
|
|
273
|
-
const currentCliVersion = persistence.configuration.currentCliVersion;
|
|
274
|
-
persistence.logger.debug(`[DAEMON CONTROL] Current CLI version: ${currentCliVersion}, Daemon started with version: ${state.startedWithCliVersion}`);
|
|
275
|
-
return currentCliVersion === state.startedWithCliVersion;
|
|
276
|
-
}
|
|
277
|
-
async function cleanupDaemonState() {
|
|
278
|
-
try {
|
|
279
|
-
await persistence.clearDaemonState();
|
|
280
|
-
persistence.logger.debug("[DAEMON RUN] Daemon state file removed");
|
|
281
|
-
} catch (error) {
|
|
282
|
-
persistence.logger.debug("[DAEMON RUN] Error cleaning up daemon metadata", error);
|
|
283
|
-
}
|
|
284
|
-
}
|
|
285
|
-
async function stopDaemon() {
|
|
286
|
-
try {
|
|
287
|
-
const state = await persistence.readDaemonState();
|
|
288
|
-
if (!state) {
|
|
289
|
-
persistence.logger.debug("No daemon state found");
|
|
290
|
-
return;
|
|
291
|
-
}
|
|
292
|
-
persistence.logger.debug(`Stopping daemon with PID ${state.pid}`);
|
|
293
|
-
try {
|
|
294
|
-
await stopDaemonHttp();
|
|
295
|
-
await waitForProcessDeath(state.pid, 2e3);
|
|
296
|
-
persistence.logger.debug("Daemon stopped gracefully via HTTP");
|
|
297
|
-
return;
|
|
298
|
-
} catch (error) {
|
|
299
|
-
persistence.logger.debug("HTTP stop failed, will force kill", error);
|
|
300
|
-
}
|
|
301
|
-
try {
|
|
302
|
-
process.kill(state.pid, "SIGKILL");
|
|
303
|
-
persistence.logger.debug("Force killed daemon");
|
|
304
|
-
} catch (error) {
|
|
305
|
-
persistence.logger.debug("Daemon already dead");
|
|
306
|
-
}
|
|
307
|
-
} catch (error) {
|
|
308
|
-
persistence.logger.debug("Error stopping daemon", error);
|
|
309
|
-
}
|
|
310
|
-
}
|
|
311
|
-
async function waitForProcessDeath(pid, timeout) {
|
|
312
|
-
const start = Date.now();
|
|
313
|
-
while (Date.now() - start < timeout) {
|
|
314
|
-
try {
|
|
315
|
-
process.kill(pid, 0);
|
|
316
|
-
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
317
|
-
} catch {
|
|
318
|
-
return;
|
|
319
|
-
}
|
|
320
|
-
}
|
|
321
|
-
throw new Error("Process did not die within timeout");
|
|
322
|
-
}
|
|
323
|
-
|
|
324
118
|
class Session {
|
|
325
119
|
path;
|
|
326
120
|
logPath;
|
|
@@ -493,7 +287,7 @@ class Session {
|
|
|
493
287
|
reportEventToDaemon = (event) => {
|
|
494
288
|
const spawnedBy = process.env.HAPPY_SPAWNED_BY;
|
|
495
289
|
if (!spawnedBy) return;
|
|
496
|
-
void notifyDaemonSessionEvent(this.client.sessionId, event, spawnedBy).catch((error) => persistence.logger.debug("[Session] Failed to report session event to daemon:", error));
|
|
290
|
+
void api.notifyDaemonSessionEvent(this.client.sessionId, event, spawnedBy).catch((error) => persistence.logger.debug("[Session] Failed to report session event to daemon:", error));
|
|
497
291
|
};
|
|
498
292
|
/** Produce an `error` notification for an unexpected session failure. */
|
|
499
293
|
onSessionError = (message) => {
|
|
@@ -4442,7 +4236,7 @@ async function claudeRemoteLauncher(session, onPermissionModeChange, onEffective
|
|
|
4442
4236
|
},
|
|
4443
4237
|
onAuthFailure: (reason) => {
|
|
4444
4238
|
session.client.sendSessionEvent({ type: "message", message: `Claude Code auth: ${reason}`, kind: "claude-auth-failed" });
|
|
4445
|
-
void notifyDaemonClaudeAuthFailed(session.client.sessionId).catch((error) => persistence.logger.debug("[remote]: auth_failed report to daemon failed:", error));
|
|
4239
|
+
void api.notifyDaemonClaudeAuthFailed(session.client.sessionId).catch((error) => persistence.logger.debug("[remote]: auth_failed report to daemon failed:", error));
|
|
4446
4240
|
},
|
|
4447
4241
|
onSessionReset: () => {
|
|
4448
4242
|
persistence.logger.debug("[remote]: Session reset");
|
|
@@ -5313,7 +5107,7 @@ function getLogFiles(logDir) {
|
|
|
5313
5107
|
async function runDoctorDaemon() {
|
|
5314
5108
|
console.log(chalk.bold("\n\u{1F916} Daemon Status"));
|
|
5315
5109
|
try {
|
|
5316
|
-
const isRunning = await checkIfDaemonRunningAndCleanupStaleState();
|
|
5110
|
+
const isRunning = await api.checkIfDaemonRunningAndCleanupStaleState();
|
|
5317
5111
|
const state = await persistence.readDaemonState();
|
|
5318
5112
|
if (isRunning && state) {
|
|
5319
5113
|
console.log(chalk.green("\u2713 Daemon is running"));
|
|
@@ -5516,7 +5310,7 @@ ${typeLabels[type] || type}:`));
|
|
|
5516
5310
|
}
|
|
5517
5311
|
console.log(chalk.bold("\n\u{1F916} Daemon Status"));
|
|
5518
5312
|
try {
|
|
5519
|
-
const isRunning = await checkIfDaemonRunningAndCleanupStaleState();
|
|
5313
|
+
const isRunning = await api.checkIfDaemonRunningAndCleanupStaleState();
|
|
5520
5314
|
const state = await persistence.readDaemonState();
|
|
5521
5315
|
const summary = daemonReadiness(authenticated, isRunning, Boolean(state));
|
|
5522
5316
|
if (summary.level === "ready" && state) {
|
|
@@ -6281,6 +6075,7 @@ function startDaemonControlServer({
|
|
|
6281
6075
|
onHappySessionWebhook,
|
|
6282
6076
|
onSessionStateEvent,
|
|
6283
6077
|
onClaudeAuthFailed,
|
|
6078
|
+
onSessionTurnEvent,
|
|
6284
6079
|
pushClipboard,
|
|
6285
6080
|
onTerminalHook,
|
|
6286
6081
|
setTerminalTitle
|
|
@@ -6337,7 +6132,7 @@ function startDaemonControlServer({
|
|
|
6337
6132
|
schema: {
|
|
6338
6133
|
body: z.z.object({
|
|
6339
6134
|
sessionId: z.z.string(),
|
|
6340
|
-
event: z.z.enum(["completed", "needs_input", "auth_failed"]),
|
|
6135
|
+
event: z.z.enum(["completed", "needs_input", "auth_failed", "turn_started", "turn_ended"]),
|
|
6341
6136
|
spawnedBy: z.z.string().optional()
|
|
6342
6137
|
}),
|
|
6343
6138
|
response: {
|
|
@@ -6353,6 +6148,10 @@ function startDaemonControlServer({
|
|
|
6353
6148
|
onClaudeAuthFailed?.(sessionId);
|
|
6354
6149
|
return { status: "ok" };
|
|
6355
6150
|
}
|
|
6151
|
+
if (event === "turn_started" || event === "turn_ended") {
|
|
6152
|
+
onSessionTurnEvent?.(sessionId, event);
|
|
6153
|
+
return { status: "ok" };
|
|
6154
|
+
}
|
|
6356
6155
|
onSessionStateEvent?.(sessionId, event, spawnedBy);
|
|
6357
6156
|
return { status: "ok" };
|
|
6358
6157
|
});
|
|
@@ -8055,7 +7854,7 @@ function parseJsonObject(text) {
|
|
|
8055
7854
|
return null;
|
|
8056
7855
|
}
|
|
8057
7856
|
}
|
|
8058
|
-
function resolveSdkClaudeBinary(platform = process.platform, arch = process.arch, resolver = (s) => node_module.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index-
|
|
7857
|
+
function resolveSdkClaudeBinary(platform = process.platform, arch = process.arch, resolver = (s) => node_module.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index-C3NtU4Ch.cjs', document.baseURI).href))).resolve(s)) {
|
|
8059
7858
|
const platformArch = `${platform}-${arch}`;
|
|
8060
7859
|
const candidates = [
|
|
8061
7860
|
`@anthropic-ai/claude-agent-sdk-${platformArch}/claude`,
|
|
@@ -9670,7 +9469,7 @@ function toSummary(id, persisted, extra) {
|
|
|
9670
9469
|
};
|
|
9671
9470
|
}
|
|
9672
9471
|
async function listSessions(options = {}) {
|
|
9673
|
-
const live = await listDaemonSessions();
|
|
9472
|
+
const live = await api.listDaemonSessions();
|
|
9674
9473
|
return mergeSessionSummaries(live, persistence.readPersistedSessions(), options);
|
|
9675
9474
|
}
|
|
9676
9475
|
function summarizeAccountSession(row, persisted, liveIds, now) {
|
|
@@ -9740,7 +9539,7 @@ async function listAccountSessions(options = {}) {
|
|
|
9740
9539
|
});
|
|
9741
9540
|
const rows = Array.isArray(response.data?.sessions) ? response.data.sessions : [];
|
|
9742
9541
|
const persisted = persistence.readPersistedSessions();
|
|
9743
|
-
const live = await listDaemonSessions();
|
|
9542
|
+
const live = await api.listDaemonSessions();
|
|
9744
9543
|
const liveIds = new Set(live.map((child) => child.happySessionId).filter((id) => typeof id === "string"));
|
|
9745
9544
|
const now = Date.now();
|
|
9746
9545
|
const summaries = rows.filter((row) => typeof row?.id === "string").map((row) => summarizeAccountSession(row, persisted[row.id], liveIds, now)).filter((summary) => options.includeArchived || !summary.archived);
|
|
@@ -9774,7 +9573,7 @@ async function readSessionTranscript(sessionId, limit) {
|
|
|
9774
9573
|
const messages = Array.isArray(response.data?.messages) ? response.data.messages : [];
|
|
9775
9574
|
messages.reverse();
|
|
9776
9575
|
const key = persistence.decodeBase64(persisted.encryptionKey);
|
|
9777
|
-
const live = await listDaemonSessions();
|
|
9576
|
+
const live = await api.listDaemonSessions();
|
|
9778
9577
|
const bodies = messages.map((message) => {
|
|
9779
9578
|
if (message.content?.t !== "encrypted") return null;
|
|
9780
9579
|
try {
|
|
@@ -9790,7 +9589,7 @@ async function readSessionTranscript(sessionId, limit) {
|
|
|
9790
9589
|
};
|
|
9791
9590
|
}
|
|
9792
9591
|
async function stopSession(sessionId) {
|
|
9793
|
-
return await stopDaemonSession(sessionId);
|
|
9592
|
+
return await api.stopDaemonSession(sessionId);
|
|
9794
9593
|
}
|
|
9795
9594
|
async function archiveSession(sessionId) {
|
|
9796
9595
|
const token = await bearerToken();
|
|
@@ -10218,7 +10017,7 @@ async function startDaemon() {
|
|
|
10218
10017
|
});
|
|
10219
10018
|
persistence.logger.debug("[DAEMON RUN] Starting daemon process...");
|
|
10220
10019
|
persistence.logger.debugLargeJson("[DAEMON RUN] Environment", getEnvironmentInfo());
|
|
10221
|
-
const runningDaemonVersionMatches = await isDaemonRunningCurrentlyInstalledHappyVersion();
|
|
10020
|
+
const runningDaemonVersionMatches = await api.isDaemonRunningCurrentlyInstalledHappyVersion();
|
|
10222
10021
|
const runningDaemonState = await persistence.readDaemonState();
|
|
10223
10022
|
const runningDaemonEndpointsMatch = Boolean(runningDaemonState) && daemonEndpointsMatch(
|
|
10224
10023
|
runningDaemonState?.serverUrl,
|
|
@@ -10228,7 +10027,7 @@ async function startDaemon() {
|
|
|
10228
10027
|
);
|
|
10229
10028
|
if (!runningDaemonVersionMatches || !runningDaemonEndpointsMatch) {
|
|
10230
10029
|
persistence.logger.debug("[DAEMON RUN] Daemon version or endpoint mismatch detected, restarting daemon");
|
|
10231
|
-
await stopDaemon();
|
|
10030
|
+
await api.stopDaemon();
|
|
10232
10031
|
} else {
|
|
10233
10032
|
persistence.logger.debug("[DAEMON RUN] Daemon version matches, keeping existing daemon");
|
|
10234
10033
|
console.log("Daemon already running with matching version");
|
|
@@ -10247,6 +10046,7 @@ async function startDaemon() {
|
|
|
10247
10046
|
const { credentials, machineId } = await authAndSetupMachineIfNeeded();
|
|
10248
10047
|
persistence.logger.debug("[DAEMON RUN] Auth and machine setup complete");
|
|
10249
10048
|
const pidToTrackedSession = /* @__PURE__ */ new Map();
|
|
10049
|
+
const turnActivity = new api.TurnActivityTracker();
|
|
10250
10050
|
const sessionIdToFinishedSession = /* @__PURE__ */ new Map();
|
|
10251
10051
|
let teamWorker;
|
|
10252
10052
|
const persisted = persistence.readPersistedSessions();
|
|
@@ -10518,6 +10318,9 @@ async function startDaemon() {
|
|
|
10518
10318
|
if (options.resumeCodexThreadId) {
|
|
10519
10319
|
extraEnv.HAPPY_FORK_CODEX_THREAD_ID = options.resumeCodexThreadId;
|
|
10520
10320
|
}
|
|
10321
|
+
if (options.importCodexThreadId && UUID_RE.test(options.importCodexThreadId)) {
|
|
10322
|
+
extraEnv.HAPPY_IMPORT_CODEX_THREAD_ID = options.importCodexThreadId;
|
|
10323
|
+
}
|
|
10521
10324
|
if (options.variant === "assistant") {
|
|
10522
10325
|
extraEnv.HAPPY_SESSION_VARIANT = "assistant";
|
|
10523
10326
|
}
|
|
@@ -11082,6 +10885,7 @@ async function startDaemon() {
|
|
|
11082
10885
|
const onChildExited = (pid) => {
|
|
11083
10886
|
const session = pidToTrackedSession.get(pid);
|
|
11084
10887
|
if (session?.happySessionId && (session.spawnedBy === "teams" || teamWorker?.hasSession(session.happySessionId))) teamWorker?.report(session.happySessionId, "exited");
|
|
10888
|
+
if (session?.happySessionId) turnActivity.forget(session.happySessionId);
|
|
11085
10889
|
if (session?.happySessionId && session.encryption) {
|
|
11086
10890
|
sessionIdToFinishedSession.set(session.happySessionId, session);
|
|
11087
10891
|
persistence.logger.debug(`[DAEMON RUN] Process PID ${pid} exited, preserved session ${session.happySessionId} for resume`);
|
|
@@ -11163,6 +10967,7 @@ async function startDaemon() {
|
|
|
11163
10967
|
onHappySessionWebhook,
|
|
11164
10968
|
onSessionStateEvent,
|
|
11165
10969
|
onClaudeAuthFailed: (sessionId) => claudeAuthServiceRef?.signalAuthFailed(sessionId),
|
|
10970
|
+
onSessionTurnEvent: (sessionId, event) => turnActivity.apply(sessionId, event),
|
|
11166
10971
|
pushClipboard: (text) => {
|
|
11167
10972
|
if (!apiMachineRef) {
|
|
11168
10973
|
return { delivered: false, truncated: false, totalBytes: 0, error: "daemon is still starting up" };
|
|
@@ -11275,7 +11080,10 @@ async function startDaemon() {
|
|
|
11275
11080
|
const updateController = createUpdateController({
|
|
11276
11081
|
policy: () => api.fetchCliUpdateState(persistence.configuration.serverUrl, persistence.packageJson.version),
|
|
11277
11082
|
enabled: async () => ((await persistence.readSettings()).cliAutoUpdate ?? "idle") !== "off",
|
|
11278
|
-
|
|
11083
|
+
// B-466: "idle" = no agent turn in flight. Idle wrappers survive a
|
|
11084
|
+
// handover (they talk to the server themselves) and web terminals live
|
|
11085
|
+
// in tmux, so neither is a reason to hold an update.
|
|
11086
|
+
idle: () => !turnActivity.hasActiveTurn(),
|
|
11279
11087
|
install: installCliSafely,
|
|
11280
11088
|
publish: (state) => {
|
|
11281
11089
|
cliUpdateStateRef = state;
|
|
@@ -11330,7 +11138,7 @@ async function startDaemon() {
|
|
|
11330
11138
|
} catch {
|
|
11331
11139
|
}
|
|
11332
11140
|
}
|
|
11333
|
-
if (bundleReplaced && !teamWorker?.busy && !updateController.isRunning() &&
|
|
11141
|
+
if (bundleReplaced && !teamWorker?.busy && !updateController.isRunning() && !turnActivity.hasActiveTurn()) {
|
|
11334
11142
|
const preflight = await preflightNewBundle(bundlePath);
|
|
11335
11143
|
if (preflight.action === "hold") {
|
|
11336
11144
|
if (lastHandoverHold !== preflight.reason) {
|
|
@@ -11340,7 +11148,7 @@ async function startDaemon() {
|
|
|
11340
11148
|
updateController.holdHandover(preflight.reason);
|
|
11341
11149
|
return;
|
|
11342
11150
|
}
|
|
11343
|
-
if (teamWorker?.busy || updateController.isRunning() ||
|
|
11151
|
+
if (teamWorker?.busy || updateController.isRunning() || turnActivity.hasActiveTurn()) return;
|
|
11344
11152
|
lastHandoverHold = null;
|
|
11345
11153
|
persistence.logger.debug("[DAEMON RUN] Daemon bundle replaced on disk and verified, handing off to new daemon");
|
|
11346
11154
|
teamWorker?.stop();
|
|
@@ -11350,7 +11158,7 @@ async function startDaemon() {
|
|
|
11350
11158
|
claudeAuthService.stop();
|
|
11351
11159
|
apiMachine.shutdown();
|
|
11352
11160
|
await stopControlServer();
|
|
11353
|
-
await cleanupDaemonState();
|
|
11161
|
+
await api.cleanupDaemonState();
|
|
11354
11162
|
await persistence.releaseDaemonLock(daemonLockHandle);
|
|
11355
11163
|
await stopCaffeinate();
|
|
11356
11164
|
try {
|
|
@@ -11423,7 +11231,7 @@ async function startDaemon() {
|
|
|
11423
11231
|
}
|
|
11424
11232
|
apiMachine.shutdown();
|
|
11425
11233
|
await stopControlServer();
|
|
11426
|
-
await cleanupDaemonState();
|
|
11234
|
+
await api.cleanupDaemonState();
|
|
11427
11235
|
await stopCaffeinate();
|
|
11428
11236
|
await persistence.releaseDaemonLock(daemonLockHandle);
|
|
11429
11237
|
persistence.logger.debug("[DAEMON RUN] Cleanup completed, exiting process");
|
|
@@ -11731,7 +11539,7 @@ ${body}`);
|
|
|
11731
11539
|
if (!normalized.ok) return fail(normalized.error);
|
|
11732
11540
|
const directory = normalized.directory;
|
|
11733
11541
|
try {
|
|
11734
|
-
const result = await spawnDaemonSession(directory, void 0, { spawnedBy: "assistant" });
|
|
11542
|
+
const result = await api.spawnDaemonSession(directory, void 0, { spawnedBy: "assistant" });
|
|
11735
11543
|
if (result?.error || !result?.sessionId) {
|
|
11736
11544
|
return fail(`Failed to spawn session: ${result?.error ?? "daemon returned no session id"}`);
|
|
11737
11545
|
}
|
|
@@ -12498,7 +12306,7 @@ function registerSideQuestionHandler(rpc, deps) {
|
|
|
12498
12306
|
const retainMs = deps.retainMs ?? SIDE_QUESTION_RETAIN_MS;
|
|
12499
12307
|
const maxRunMs = deps.maxRunMs ?? SIDE_QUESTION_MAX_RUN_MS;
|
|
12500
12308
|
const run = deps.run ?? (async (input) => {
|
|
12501
|
-
const { query } = await Promise.resolve().then(function () { return require('./index-
|
|
12309
|
+
const { query } = await Promise.resolve().then(function () { return require('./index-gkFhwPXq.cjs'); });
|
|
12502
12310
|
return runSideQuestion(query, input);
|
|
12503
12311
|
});
|
|
12504
12312
|
const slots = /* @__PURE__ */ new Map();
|
|
@@ -12600,7 +12408,7 @@ const MAX_TITLE_CHARS = 60;
|
|
|
12600
12408
|
const GENERATION_TIMEOUT_MS = 3e4;
|
|
12601
12409
|
function resolveClaudeBinary() {
|
|
12602
12410
|
try {
|
|
12603
|
-
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-
|
|
12411
|
+
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-C3NtU4Ch.cjs', document.baseURI).href)));
|
|
12604
12412
|
const utilsPath = path.resolve(path.join(api.projectPath(), "scripts", "claude_version_utils.cjs"));
|
|
12605
12413
|
const { getClaudeCliPath } = require$1(utilsPath);
|
|
12606
12414
|
const path$1 = getClaudeCliPath();
|
|
@@ -13162,7 +12970,7 @@ async function runClaude(credentials, options = {}) {
|
|
|
13162
12970
|
}
|
|
13163
12971
|
try {
|
|
13164
12972
|
persistence.logger.debug(`[START] Reporting session ${response.id} to daemon`);
|
|
13165
|
-
const result = await notifyDaemonSessionStarted(response.id, metadata, {
|
|
12973
|
+
const result = await api.notifyDaemonSessionStarted(response.id, metadata, {
|
|
13166
12974
|
encryptionKey: persistence.encodeBase64(response.encryptionKey),
|
|
13167
12975
|
encryptionVariant: response.encryptionVariant,
|
|
13168
12976
|
seq: response.seq,
|
|
@@ -13890,7 +13698,7 @@ async function handleAuthLogin(args) {
|
|
|
13890
13698
|
console.log(chalk.gray(" \u2022 Re-authenticate and register machine\n"));
|
|
13891
13699
|
try {
|
|
13892
13700
|
persistence.logger.debug("Stopping daemon for force auth...");
|
|
13893
|
-
await stopDaemon();
|
|
13701
|
+
await api.stopDaemon();
|
|
13894
13702
|
console.log(chalk.gray("\u2713 Stopped daemon"));
|
|
13895
13703
|
} catch (error) {
|
|
13896
13704
|
persistence.logger.debug("Daemon was not running or failed to stop:", error);
|
|
@@ -13955,7 +13763,7 @@ async function handleAuthLogout() {
|
|
|
13955
13763
|
if (answer.toLowerCase() === "y" || answer.toLowerCase() === "yes") {
|
|
13956
13764
|
try {
|
|
13957
13765
|
try {
|
|
13958
|
-
await stopDaemon();
|
|
13766
|
+
await api.stopDaemon();
|
|
13959
13767
|
console.log(chalk.gray("Stopped daemon"));
|
|
13960
13768
|
} catch {
|
|
13961
13769
|
}
|
|
@@ -14000,7 +13808,7 @@ async function handleAuthStatus() {
|
|
|
14000
13808
|
console.log(chalk.gray(`
|
|
14001
13809
|
Data directory: ${persistence.configuration.happyHomeDir}`));
|
|
14002
13810
|
try {
|
|
14003
|
-
const running = await checkIfDaemonRunningAndCleanupStaleState();
|
|
13811
|
+
const running = await api.checkIfDaemonRunningAndCleanupStaleState();
|
|
14004
13812
|
if (running) {
|
|
14005
13813
|
console.log(chalk.green("\u2713 Daemon running"));
|
|
14006
13814
|
} else {
|
|
@@ -14826,9 +14634,9 @@ function resolveLocalSignupBootstrap(configuredMode, configuredInviteCodes, gene
|
|
|
14826
14634
|
};
|
|
14827
14635
|
}
|
|
14828
14636
|
|
|
14829
|
-
const __filename$1 = node_url.fileURLToPath((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index-
|
|
14637
|
+
const __filename$1 = node_url.fileURLToPath((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index-C3NtU4Ch.cjs', document.baseURI).href)));
|
|
14830
14638
|
const __dirname$1 = path.dirname(__filename$1);
|
|
14831
|
-
const require_ = node_module.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index-
|
|
14639
|
+
const require_ = node_module.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index-C3NtU4Ch.cjs', document.baseURI).href)));
|
|
14832
14640
|
const PRISMA_QUERY_ENGINE_FILES = {
|
|
14833
14641
|
"arm64-darwin": "libquery_engine-darwin-arm64.dylib.node",
|
|
14834
14642
|
"x64-darwin": "libquery_engine-darwin.dylib.node",
|
|
@@ -15217,7 +15025,7 @@ const DAEMON_READY_TIMEOUT_MS = 5e3;
|
|
|
15217
15025
|
const DAEMON_READY_POLL_INTERVAL_MS = 100;
|
|
15218
15026
|
async function ensureDaemonRunning() {
|
|
15219
15027
|
persistence.logger.debug("Ensuring Happy background service is running & matches our version...");
|
|
15220
|
-
const versionMatches = await isDaemonRunningCurrentlyInstalledHappyVersion();
|
|
15028
|
+
const versionMatches = await api.isDaemonRunningCurrentlyInstalledHappyVersion();
|
|
15221
15029
|
const state = await persistence.readDaemonState();
|
|
15222
15030
|
const endpointsMatch = Boolean(state) && daemonEndpointsMatch(
|
|
15223
15031
|
state?.serverUrl,
|
|
@@ -15228,9 +15036,9 @@ async function ensureDaemonRunning() {
|
|
|
15228
15036
|
if (versionMatches && endpointsMatch) {
|
|
15229
15037
|
return;
|
|
15230
15038
|
}
|
|
15231
|
-
if (await checkIfDaemonRunningAndCleanupStaleState()) {
|
|
15039
|
+
if (await api.checkIfDaemonRunningAndCleanupStaleState()) {
|
|
15232
15040
|
persistence.logger.debug("Stopping daemon whose version or configured relay no longer matches...");
|
|
15233
|
-
await stopDaemon();
|
|
15041
|
+
await api.stopDaemon();
|
|
15234
15042
|
}
|
|
15235
15043
|
persistence.logger.debug("Starting Happy background service...");
|
|
15236
15044
|
const daemonProcess = spawnHappyCLI(["daemon", "start-sync"], {
|
|
@@ -15241,7 +15049,7 @@ async function ensureDaemonRunning() {
|
|
|
15241
15049
|
daemonProcess.unref();
|
|
15242
15050
|
const deadline = Date.now() + DAEMON_READY_TIMEOUT_MS;
|
|
15243
15051
|
while (Date.now() < deadline) {
|
|
15244
|
-
if (await checkIfDaemonRunningAndCleanupStaleState()) {
|
|
15052
|
+
if (await api.checkIfDaemonRunningAndCleanupStaleState()) {
|
|
15245
15053
|
persistence.logger.debug("Happy background service is ready");
|
|
15246
15054
|
return;
|
|
15247
15055
|
}
|
|
@@ -16594,6 +16402,43 @@ async function resumeExistingThread(opts) {
|
|
|
16594
16402
|
}
|
|
16595
16403
|
}
|
|
16596
16404
|
|
|
16405
|
+
const IMPORT_CODEX_THREAD_ENV = "HAPPY_IMPORT_CODEX_THREAD_ID";
|
|
16406
|
+
async function importCodexThread(opts) {
|
|
16407
|
+
let forked;
|
|
16408
|
+
try {
|
|
16409
|
+
forked = await opts.client.forkThread({
|
|
16410
|
+
threadId: opts.threadId,
|
|
16411
|
+
cwd: opts.cwd,
|
|
16412
|
+
mcpServers: opts.mcpServers
|
|
16413
|
+
});
|
|
16414
|
+
} catch (error) {
|
|
16415
|
+
const reason = error instanceof Error ? error.message : String(error);
|
|
16416
|
+
throw new Error(`Failed to import Codex thread ${opts.threadId}: ${reason}`);
|
|
16417
|
+
}
|
|
16418
|
+
if (!forked.threadId || forked.threadId === opts.threadId) {
|
|
16419
|
+
throw new Error(`Failed to import Codex thread ${opts.threadId}: Codex did not create an independent copy`);
|
|
16420
|
+
}
|
|
16421
|
+
opts.session.updateMetadata((currentMetadata) => ({
|
|
16422
|
+
...currentMetadata,
|
|
16423
|
+
codexThreadId: forked.threadId,
|
|
16424
|
+
importedFromCodexThreadId: opts.threadId
|
|
16425
|
+
}));
|
|
16426
|
+
let thread = forked.thread;
|
|
16427
|
+
if (!Array.isArray(thread?.turns)) {
|
|
16428
|
+
thread = (await opts.client.readThread({ threadId: forked.threadId, includeTurns: true })).thread;
|
|
16429
|
+
}
|
|
16430
|
+
const envelopes = mapCodexThreadToSessionEnvelopes(thread);
|
|
16431
|
+
for (const envelope of envelopes) {
|
|
16432
|
+
opts.session.sendSessionProtocolMessage(envelope);
|
|
16433
|
+
}
|
|
16434
|
+
opts.messageBuffer.addMessage(`Imported thread ${agentGuidance.trimIdent(opts.threadId)} as ${agentGuidance.trimIdent(forked.threadId)}`, "status");
|
|
16435
|
+
opts.session.sendSessionEvent({
|
|
16436
|
+
type: "message",
|
|
16437
|
+
message: `Imported Codex thread ${opts.threadId} (continuing as ${forked.threadId})`
|
|
16438
|
+
});
|
|
16439
|
+
return { threadId: forked.threadId, model: forked.model, replayed: envelopes.length };
|
|
16440
|
+
}
|
|
16441
|
+
|
|
16597
16442
|
function emitReadyIfIdle({ pending, queueSize, shouldExit, sendReady, notify }) {
|
|
16598
16443
|
if (shouldExit) {
|
|
16599
16444
|
return false;
|
|
@@ -16609,6 +16454,72 @@ function emitReadyIfIdle({ pending, queueSize, shouldExit, sendReady, notify })
|
|
|
16609
16454
|
return true;
|
|
16610
16455
|
}
|
|
16611
16456
|
|
|
16457
|
+
const DEFAULT_CODEX_IDLE_RELEASE_MS = 5 * 60 * 1e3;
|
|
16458
|
+
const CODEX_IDLE_RELEASE_ENV = "HAPPY_CODEX_IDLE_RELEASE_MS";
|
|
16459
|
+
function resolveCodexIdleReleaseMs(raw) {
|
|
16460
|
+
if (raw === void 0 || raw.trim() === "") return DEFAULT_CODEX_IDLE_RELEASE_MS;
|
|
16461
|
+
const parsed = Number(raw);
|
|
16462
|
+
if (!Number.isFinite(parsed) || parsed < 0) return DEFAULT_CODEX_IDLE_RELEASE_MS;
|
|
16463
|
+
return Math.floor(parsed);
|
|
16464
|
+
}
|
|
16465
|
+
function shouldReleaseIdleCodex(state) {
|
|
16466
|
+
if (state.shouldExit) return false;
|
|
16467
|
+
if (state.turnActive) return false;
|
|
16468
|
+
if (state.abortInProgress) return false;
|
|
16469
|
+
if (state.queueSize > 0) return false;
|
|
16470
|
+
return true;
|
|
16471
|
+
}
|
|
16472
|
+
class CodexIdleReleaseTimer {
|
|
16473
|
+
constructor(opts) {
|
|
16474
|
+
this.opts = opts;
|
|
16475
|
+
}
|
|
16476
|
+
timer = null;
|
|
16477
|
+
releasing = null;
|
|
16478
|
+
get enabled() {
|
|
16479
|
+
return this.opts.delayMs > 0;
|
|
16480
|
+
}
|
|
16481
|
+
get armed() {
|
|
16482
|
+
return this.timer !== null;
|
|
16483
|
+
}
|
|
16484
|
+
arm() {
|
|
16485
|
+
this.cancel();
|
|
16486
|
+
if (!this.enabled) return;
|
|
16487
|
+
const timer = setTimeout(() => {
|
|
16488
|
+
if (this.timer !== timer) return;
|
|
16489
|
+
this.timer = null;
|
|
16490
|
+
void this.fire();
|
|
16491
|
+
}, this.opts.delayMs);
|
|
16492
|
+
timer.unref?.();
|
|
16493
|
+
this.timer = timer;
|
|
16494
|
+
}
|
|
16495
|
+
cancel() {
|
|
16496
|
+
if (this.timer) {
|
|
16497
|
+
clearTimeout(this.timer);
|
|
16498
|
+
this.timer = null;
|
|
16499
|
+
}
|
|
16500
|
+
}
|
|
16501
|
+
/** Resolves once an in-flight release (if any) has finished. Test hook. */
|
|
16502
|
+
async settle() {
|
|
16503
|
+
await this.releasing;
|
|
16504
|
+
}
|
|
16505
|
+
async fire() {
|
|
16506
|
+
if (!this.opts.isIdle()) return;
|
|
16507
|
+
const run = (async () => {
|
|
16508
|
+
try {
|
|
16509
|
+
await this.opts.release();
|
|
16510
|
+
} catch (error) {
|
|
16511
|
+
this.opts.onError?.(error);
|
|
16512
|
+
}
|
|
16513
|
+
})();
|
|
16514
|
+
this.releasing = run;
|
|
16515
|
+
try {
|
|
16516
|
+
await run;
|
|
16517
|
+
} finally {
|
|
16518
|
+
if (this.releasing === run) this.releasing = null;
|
|
16519
|
+
}
|
|
16520
|
+
}
|
|
16521
|
+
}
|
|
16522
|
+
|
|
16612
16523
|
function isCodexClearText(text) {
|
|
16613
16524
|
return parseSpecialCommand(text).type === "clear";
|
|
16614
16525
|
}
|
|
@@ -16742,6 +16653,12 @@ async function runCodex(opts) {
|
|
|
16742
16653
|
...forkedFromMessageId ? { forkedFromMessageId } : {}
|
|
16743
16654
|
});
|
|
16744
16655
|
metadata.attachmentKinds = [...CLAUDE_ATTACHMENT_KINDS];
|
|
16656
|
+
const importCodexThreadId = process.env[IMPORT_CODEX_THREAD_ENV];
|
|
16657
|
+
if (importCodexThreadId) {
|
|
16658
|
+
metadata.importedFromCodexThreadId = importCodexThreadId;
|
|
16659
|
+
const importTitle = process.env.HAPPY_IMPORT_TITLE;
|
|
16660
|
+
if (importTitle) metadata.summary = { text: importTitle, updatedAt: Date.now() };
|
|
16661
|
+
}
|
|
16745
16662
|
const reconnectSessionId = process.env.HAPPY_RECONNECT_SESSION_ID;
|
|
16746
16663
|
const reconnectKeyBase64 = process.env.HAPPY_RECONNECT_ENCRYPTION_KEY;
|
|
16747
16664
|
const reconnectVariant = process.env.HAPPY_RECONNECT_ENCRYPTION_VARIANT;
|
|
@@ -16787,6 +16704,7 @@ async function runCodex(opts) {
|
|
|
16787
16704
|
let client;
|
|
16788
16705
|
let reasoningProcessor;
|
|
16789
16706
|
let abortInProgress = null;
|
|
16707
|
+
let turnActive = false;
|
|
16790
16708
|
const { session: initialSession, reconnectionHandle } = setupOfflineReconnection({
|
|
16791
16709
|
api: api$1,
|
|
16792
16710
|
sessionTag,
|
|
@@ -16811,7 +16729,7 @@ async function runCodex(opts) {
|
|
|
16811
16729
|
if (response) {
|
|
16812
16730
|
try {
|
|
16813
16731
|
persistence.logger.debug(`[START] Reporting session ${response.id} to daemon`);
|
|
16814
|
-
const result = await notifyDaemonSessionStarted(response.id, metadata, {
|
|
16732
|
+
const result = await api.notifyDaemonSessionStarted(response.id, metadata, {
|
|
16815
16733
|
encryptionKey: persistence.encodeBase64(response.encryptionKey),
|
|
16816
16734
|
encryptionVariant: response.encryptionVariant,
|
|
16817
16735
|
seq: response.seq,
|
|
@@ -17075,6 +16993,22 @@ async function runCodex(opts) {
|
|
|
17075
16993
|
process.stdin.setEncoding("utf8");
|
|
17076
16994
|
}
|
|
17077
16995
|
client = new api.CodexAppServerClient(sandboxConfig);
|
|
16996
|
+
const idleRelease = new CodexIdleReleaseTimer({
|
|
16997
|
+
delayMs: resolveCodexIdleReleaseMs(process.env[CODEX_IDLE_RELEASE_ENV]),
|
|
16998
|
+
isIdle: () => shouldReleaseIdleCodex({
|
|
16999
|
+
turnActive,
|
|
17000
|
+
queueSize: messageQueue.size(),
|
|
17001
|
+
shouldExit,
|
|
17002
|
+
abortInProgress: abortInProgress !== null
|
|
17003
|
+
}),
|
|
17004
|
+
release: async () => {
|
|
17005
|
+
const released = await client.releaseIdleProcess();
|
|
17006
|
+
if (released) {
|
|
17007
|
+
persistence.logger.debug("[Codex] Released idle app-server; thread kept for resume on next message");
|
|
17008
|
+
}
|
|
17009
|
+
},
|
|
17010
|
+
onError: (error) => persistence.logger.debug("[Codex] Idle app-server release failed", safeCodexErrorMetadata(error))
|
|
17011
|
+
});
|
|
17078
17012
|
permissionHandler = new CodexPermissionHandler(session);
|
|
17079
17013
|
permissionHandler.reset("Previous CLI process exited before responding");
|
|
17080
17014
|
reasoningProcessor = new ReasoningProcessor((message) => {
|
|
@@ -17243,6 +17177,18 @@ async function runCodex(opts) {
|
|
|
17243
17177
|
first = false;
|
|
17244
17178
|
appendSystemPromptInjected = true;
|
|
17245
17179
|
}
|
|
17180
|
+
if (!reconnectSessionId && !opts.resumeThreadId && importCodexThreadId) {
|
|
17181
|
+
await importCodexThread({
|
|
17182
|
+
client,
|
|
17183
|
+
session,
|
|
17184
|
+
messageBuffer,
|
|
17185
|
+
threadId: importCodexThreadId,
|
|
17186
|
+
cwd: process.cwd(),
|
|
17187
|
+
mcpServers
|
|
17188
|
+
});
|
|
17189
|
+
first = false;
|
|
17190
|
+
appendSystemPromptInjected = true;
|
|
17191
|
+
}
|
|
17246
17192
|
const forkCodexThreadId = process.env.HAPPY_FORK_CODEX_THREAD_ID;
|
|
17247
17193
|
if (!reconnectSessionId && forkCodexThreadId) {
|
|
17248
17194
|
try {
|
|
@@ -17264,6 +17210,7 @@ async function runCodex(opts) {
|
|
|
17264
17210
|
}
|
|
17265
17211
|
}
|
|
17266
17212
|
let pending = null;
|
|
17213
|
+
idleRelease.arm();
|
|
17267
17214
|
while (!shouldExit) {
|
|
17268
17215
|
logActiveHandles("loop-top");
|
|
17269
17216
|
let message = pending;
|
|
@@ -17284,6 +17231,8 @@ async function runCodex(opts) {
|
|
|
17284
17231
|
if (!message) {
|
|
17285
17232
|
break;
|
|
17286
17233
|
}
|
|
17234
|
+
idleRelease.cancel();
|
|
17235
|
+
turnActive = true;
|
|
17287
17236
|
if (isCodexClearText(message.message)) {
|
|
17288
17237
|
persistence.logger.debug("[Codex] Handling /clear command - resetting Codex thread state");
|
|
17289
17238
|
client.clearThreadState();
|
|
@@ -17310,10 +17259,13 @@ async function runCodex(opts) {
|
|
|
17310
17259
|
shouldExit,
|
|
17311
17260
|
sendReady
|
|
17312
17261
|
});
|
|
17262
|
+
turnActive = false;
|
|
17263
|
+
idleRelease.arm();
|
|
17313
17264
|
continue;
|
|
17314
17265
|
}
|
|
17315
17266
|
messageBuffer.addMessage(message.message, "user");
|
|
17316
17267
|
try {
|
|
17268
|
+
await client.ensureConnected();
|
|
17317
17269
|
const sandboxManagedByHappy = client.sandboxEnabled;
|
|
17318
17270
|
const executionPolicy = resolveCodexExecutionPolicy(
|
|
17319
17271
|
message.mode.permissionMode,
|
|
@@ -17380,6 +17332,8 @@ async function runCodex(opts) {
|
|
|
17380
17332
|
shouldExit,
|
|
17381
17333
|
sendReady
|
|
17382
17334
|
});
|
|
17335
|
+
turnActive = false;
|
|
17336
|
+
idleRelease.arm();
|
|
17383
17337
|
logActiveHandles("after-turn");
|
|
17384
17338
|
}
|
|
17385
17339
|
}
|
|
@@ -17403,6 +17357,7 @@ async function runCodex(opts) {
|
|
|
17403
17357
|
} catch (e) {
|
|
17404
17358
|
persistence.logger.debug("[codex]: Error while closing session", safeCodexErrorMetadata(e));
|
|
17405
17359
|
}
|
|
17360
|
+
idleRelease.cancel();
|
|
17406
17361
|
persistence.logger.debug("[codex]: client.disconnect begin");
|
|
17407
17362
|
await client.disconnect();
|
|
17408
17363
|
persistence.logger.debug("[codex]: client.disconnect done");
|
|
@@ -17587,7 +17542,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
|
|
|
17587
17542
|
process.exit(0);
|
|
17588
17543
|
} else if (subcommand === "install-terminal-hooks") {
|
|
17589
17544
|
try {
|
|
17590
|
-
const { installTerminalHooks, parseTerminalHooksArgs, TERMINAL_HOOKS_HELP } = await Promise.resolve().then(function () { return require('./installTerminalHooks-
|
|
17545
|
+
const { installTerminalHooks, parseTerminalHooksArgs, TERMINAL_HOOKS_HELP } = await Promise.resolve().then(function () { return require('./installTerminalHooks-DZUBgnFh.cjs'); });
|
|
17591
17546
|
const command = parseTerminalHooksArgs(args.slice(1));
|
|
17592
17547
|
if (command.action === "help") {
|
|
17593
17548
|
console.log(TERMINAL_HOOKS_HELP);
|
|
@@ -17604,7 +17559,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
|
|
|
17604
17559
|
}
|
|
17605
17560
|
} else if (subcommand === "spawn") {
|
|
17606
17561
|
try {
|
|
17607
|
-
const { handleSpawnCommand } = await Promise.resolve().then(function () { return require('./spawn-
|
|
17562
|
+
const { handleSpawnCommand } = await Promise.resolve().then(function () { return require('./spawn-jWj3xFhX.cjs'); });
|
|
17608
17563
|
await handleSpawnCommand(args.slice(1));
|
|
17609
17564
|
} catch (error) {
|
|
17610
17565
|
console.error(chalk.red("Error:"), error instanceof Error ? error.message : "Unknown error");
|
|
@@ -17616,7 +17571,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
|
|
|
17616
17571
|
return;
|
|
17617
17572
|
} else if (subcommand === "sessions") {
|
|
17618
17573
|
try {
|
|
17619
|
-
const { handleSessionsCommand } = await Promise.resolve().then(function () { return require('./sessions-
|
|
17574
|
+
const { handleSessionsCommand } = await Promise.resolve().then(function () { return require('./sessions-CN2y0xBl.cjs'); });
|
|
17620
17575
|
await handleSessionsCommand(args.slice(1));
|
|
17621
17576
|
} catch (error) {
|
|
17622
17577
|
console.error(chalk.red("Error:"), error instanceof Error ? error.message : "Unknown error");
|
|
@@ -17628,7 +17583,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
|
|
|
17628
17583
|
return;
|
|
17629
17584
|
} else if (subcommand === "send") {
|
|
17630
17585
|
try {
|
|
17631
|
-
const { handleSendCommand } = await Promise.resolve().then(function () { return require('./send-
|
|
17586
|
+
const { handleSendCommand } = await Promise.resolve().then(function () { return require('./send-B4Qo-87h.cjs'); });
|
|
17632
17587
|
await handleSendCommand(args.slice(1));
|
|
17633
17588
|
} catch (error) {
|
|
17634
17589
|
console.error(chalk.red("Error:"), error instanceof Error ? error.message : "Unknown error");
|
|
@@ -17734,9 +17689,9 @@ Conversation history is preserved on the server, but in-flight tool calls are in
|
|
|
17734
17689
|
if (geminiSubcommand === "project" && args[2] === "set" && args[3]) {
|
|
17735
17690
|
const projectId = args[3];
|
|
17736
17691
|
try {
|
|
17737
|
-
const { saveGoogleCloudProjectToConfig } = await Promise.resolve().then(function () { return require('./config-
|
|
17738
|
-
const { readCredentialsForConfiguredRelay: readCredentialsForConfiguredRelay2 } = await Promise.resolve().then(function () { return require('./limits-
|
|
17739
|
-
const { ApiClient: ApiClient2 } = await Promise.resolve().then(function () { return require('./types-
|
|
17692
|
+
const { saveGoogleCloudProjectToConfig } = await Promise.resolve().then(function () { return require('./config-nyMHCx-i.cjs'); });
|
|
17693
|
+
const { readCredentialsForConfiguredRelay: readCredentialsForConfiguredRelay2 } = await Promise.resolve().then(function () { return require('./limits-C_RGzva6.cjs'); }).then(function (n) { return n.persistence; });
|
|
17694
|
+
const { ApiClient: ApiClient2 } = await Promise.resolve().then(function () { return require('./types-CxGm_YJ-.cjs'); }).then(function (n) { return n.api; });
|
|
17740
17695
|
let userEmail = void 0;
|
|
17741
17696
|
try {
|
|
17742
17697
|
const credentials = await readCredentialsForConfiguredRelay2();
|
|
@@ -17767,7 +17722,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
|
|
|
17767
17722
|
}
|
|
17768
17723
|
if (geminiSubcommand === "project" && args[2] === "get") {
|
|
17769
17724
|
try {
|
|
17770
|
-
const { readGeminiLocalConfig } = await Promise.resolve().then(function () { return require('./config-
|
|
17725
|
+
const { readGeminiLocalConfig } = await Promise.resolve().then(function () { return require('./config-nyMHCx-i.cjs'); });
|
|
17771
17726
|
const config = readGeminiLocalConfig();
|
|
17772
17727
|
if (config.googleCloudProject) {
|
|
17773
17728
|
console.log(`Current Google Cloud Project: ${config.googleCloudProject}`);
|
|
@@ -17807,7 +17762,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
|
|
|
17807
17762
|
process.exit(0);
|
|
17808
17763
|
}
|
|
17809
17764
|
try {
|
|
17810
|
-
const { runGemini } = await Promise.resolve().then(function () { return require('./runGemini-
|
|
17765
|
+
const { runGemini } = await Promise.resolve().then(function () { return require('./runGemini-Dy3y-lD9.cjs'); });
|
|
17811
17766
|
let startedBy = void 0;
|
|
17812
17767
|
for (let i = 1; i < args.length; i++) {
|
|
17813
17768
|
if (args[i] === "--started-by") {
|
|
@@ -17837,7 +17792,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
|
|
|
17837
17792
|
}
|
|
17838
17793
|
};
|
|
17839
17794
|
try {
|
|
17840
|
-
const { runAcp, resolveAcpAgentConfig } = await Promise.resolve().then(function () { return require('./index-
|
|
17795
|
+
const { runAcp, resolveAcpAgentConfig } = await Promise.resolve().then(function () { return require('./index-klhxcpC8.cjs'); });
|
|
17841
17796
|
const parsed = parsePiRunnerArgs(args.slice(1));
|
|
17842
17797
|
const resolved = resolveAcpAgentConfig(["pi", ...parsed.passthrough]);
|
|
17843
17798
|
const { credentials } = await authAndSetupMachineIfNeeded();
|
|
@@ -17865,7 +17820,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
|
|
|
17865
17820
|
return;
|
|
17866
17821
|
} else if (subcommand === "acp") {
|
|
17867
17822
|
try {
|
|
17868
|
-
const { runAcp, resolveAcpAgentConfig } = await Promise.resolve().then(function () { return require('./index-
|
|
17823
|
+
const { runAcp, resolveAcpAgentConfig } = await Promise.resolve().then(function () { return require('./index-klhxcpC8.cjs'); });
|
|
17869
17824
|
let startedBy = void 0;
|
|
17870
17825
|
let verbose = false;
|
|
17871
17826
|
const acpArgs = [];
|
|
@@ -17905,7 +17860,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
|
|
|
17905
17860
|
return;
|
|
17906
17861
|
} else if (subcommand === "openclaw") {
|
|
17907
17862
|
try {
|
|
17908
|
-
const { runOpenClaw } = await Promise.resolve().then(function () { return require('./runOpenClaw-
|
|
17863
|
+
const { runOpenClaw } = await Promise.resolve().then(function () { return require('./runOpenClaw-CJusckVM.cjs'); });
|
|
17909
17864
|
let startedBy = void 0;
|
|
17910
17865
|
let verbose = false;
|
|
17911
17866
|
let gatewayUrl;
|
|
@@ -17956,7 +17911,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
|
|
|
17956
17911
|
return;
|
|
17957
17912
|
} else if (subcommand === "todo") {
|
|
17958
17913
|
try {
|
|
17959
|
-
const { handleTodoCommand } = await Promise.resolve().then(function () { return require('./todo-
|
|
17914
|
+
const { handleTodoCommand } = await Promise.resolve().then(function () { return require('./todo-B0kvqUTQ.cjs'); });
|
|
17960
17915
|
await handleTodoCommand(args.slice(1));
|
|
17961
17916
|
} catch (error) {
|
|
17962
17917
|
console.error(JSON.stringify({ error: error instanceof Error ? error.message : "Todo command failed" }));
|
|
@@ -17965,7 +17920,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
|
|
|
17965
17920
|
return;
|
|
17966
17921
|
} else if (subcommand === "teams") {
|
|
17967
17922
|
try {
|
|
17968
|
-
const { handleTeamsCommand } = await Promise.resolve().then(function () { return require('./teams-
|
|
17923
|
+
const { handleTeamsCommand } = await Promise.resolve().then(function () { return require('./teams-BhFspeAY.cjs'); });
|
|
17969
17924
|
await handleTeamsCommand(args.slice(1));
|
|
17970
17925
|
} catch (error) {
|
|
17971
17926
|
console.error(error instanceof Error ? error.message : "Teams command failed");
|
|
@@ -17974,7 +17929,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
|
|
|
17974
17929
|
return;
|
|
17975
17930
|
} else if (subcommand === "mcp" && args.length === 1) {
|
|
17976
17931
|
try {
|
|
17977
|
-
const { handleMcpCommand } = await Promise.resolve().then(function () { return require('./mcp-
|
|
17932
|
+
const { handleMcpCommand } = await Promise.resolve().then(function () { return require('./mcp-czNIfD59.cjs'); });
|
|
17978
17933
|
await handleMcpCommand();
|
|
17979
17934
|
} catch (error) {
|
|
17980
17935
|
process.stderr.write(`[very-happy mcp] Fatal: ${error instanceof Error ? error.message : String(error)}
|
|
@@ -17997,7 +17952,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
|
|
|
17997
17952
|
const daemonSubcommand = args[1];
|
|
17998
17953
|
if (daemonSubcommand === "list") {
|
|
17999
17954
|
try {
|
|
18000
|
-
const sessions = await listDaemonSessions();
|
|
17955
|
+
const sessions = await api.listDaemonSessions();
|
|
18001
17956
|
if (sessions.length === 0) {
|
|
18002
17957
|
console.log("No active sessions this daemon is aware of (they might have been started by a previous version of the daemon)");
|
|
18003
17958
|
} else {
|
|
@@ -18015,7 +17970,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
|
|
|
18015
17970
|
process.exit(1);
|
|
18016
17971
|
}
|
|
18017
17972
|
try {
|
|
18018
|
-
const success = await stopDaemonSession(sessionId);
|
|
17973
|
+
const success = await api.stopDaemonSession(sessionId);
|
|
18019
17974
|
console.log(success ? "Session stopped" : "Failed to stop session");
|
|
18020
17975
|
} catch (error) {
|
|
18021
17976
|
console.log("No daemon running");
|
|
@@ -18023,7 +17978,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
|
|
|
18023
17978
|
return;
|
|
18024
17979
|
} else if (daemonSubcommand === "start") {
|
|
18025
17980
|
const currentState = await persistence.readDaemonState();
|
|
18026
|
-
const running = await checkIfDaemonRunningAndCleanupStaleState();
|
|
17981
|
+
const running = await api.checkIfDaemonRunningAndCleanupStaleState();
|
|
18027
17982
|
const currentDaemonMatches = currentState && currentState.startedWithCliVersion === persistence.configuration.currentCliVersion && daemonEndpointsMatch(
|
|
18028
17983
|
currentState.serverUrl,
|
|
18029
17984
|
currentState.webappUrl,
|
|
@@ -18032,7 +17987,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
|
|
|
18032
17987
|
);
|
|
18033
17988
|
if (running && !currentDaemonMatches) {
|
|
18034
17989
|
console.log("Configured relay or CLI version changed; restarting the existing daemon");
|
|
18035
|
-
await stopDaemon();
|
|
17990
|
+
await api.stopDaemon();
|
|
18036
17991
|
}
|
|
18037
17992
|
const child = spawnHappyCLI(["daemon", "start-sync"], {
|
|
18038
17993
|
detached: true,
|
|
@@ -18042,7 +17997,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
|
|
|
18042
17997
|
child.unref();
|
|
18043
17998
|
let started = false;
|
|
18044
17999
|
for (let i = 0; i < 50; i++) {
|
|
18045
|
-
if (await checkIfDaemonRunningAndCleanupStaleState()) {
|
|
18000
|
+
if (await api.checkIfDaemonRunningAndCleanupStaleState()) {
|
|
18046
18001
|
started = true;
|
|
18047
18002
|
break;
|
|
18048
18003
|
}
|
|
@@ -18059,7 +18014,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
|
|
|
18059
18014
|
await startDaemon();
|
|
18060
18015
|
process.exit(0);
|
|
18061
18016
|
} else if (daemonSubcommand === "stop") {
|
|
18062
|
-
await stopDaemon();
|
|
18017
|
+
await api.stopDaemon();
|
|
18063
18018
|
process.exit(0);
|
|
18064
18019
|
} else if (daemonSubcommand === "status") {
|
|
18065
18020
|
await runDoctorDaemon();
|
|
@@ -18356,7 +18311,6 @@ exports.TEAM_SKILL = TEAM_SKILL;
|
|
|
18356
18311
|
exports.TitleGenerator = TitleGenerator;
|
|
18357
18312
|
exports.appendStagedAttachmentsToPrompt = appendStagedAttachmentsToPrompt;
|
|
18358
18313
|
exports.archiveSession = archiveSession;
|
|
18359
|
-
exports.checkIfDaemonRunningAndCleanupStaleState = checkIfDaemonRunningAndCleanupStaleState;
|
|
18360
18314
|
exports.createSessionMetadata = createSessionMetadata;
|
|
18361
18315
|
exports.hashObject = hashObject;
|
|
18362
18316
|
exports.initialMachineMetadata = initialMachineMetadata;
|
|
@@ -18364,8 +18318,6 @@ exports.isValidSpawnOrigin = isValidSpawnOrigin;
|
|
|
18364
18318
|
exports.listAccountSessions = listAccountSessions;
|
|
18365
18319
|
exports.listSessions = listSessions;
|
|
18366
18320
|
exports.normalizeAcpPermissionMode = normalizeAcpPermissionMode;
|
|
18367
|
-
exports.notifyDaemonSessionStarted = notifyDaemonSessionStarted;
|
|
18368
|
-
exports.pushClipboardViaDaemon = pushClipboardViaDaemon;
|
|
18369
18321
|
exports.query = query;
|
|
18370
18322
|
exports.readSessionTranscript = readSessionTranscript;
|
|
18371
18323
|
exports.registerAgentAttachmentDownloads = registerAgentAttachmentDownloads;
|
|
@@ -18376,9 +18328,7 @@ exports.resolvePermissionRequest = resolvePermissionRequest;
|
|
|
18376
18328
|
exports.sanitizeSpawnPermissionMode = sanitizeSpawnPermissionMode;
|
|
18377
18329
|
exports.sendUserMessage = sendUserMessage;
|
|
18378
18330
|
exports.sessionWebUrl = sessionWebUrl;
|
|
18379
|
-
exports.setTerminalTitleViaDaemon = setTerminalTitleViaDaemon;
|
|
18380
18331
|
exports.setupOfflineReconnection = setupOfflineReconnection;
|
|
18381
|
-
exports.spawnDaemonSession = spawnDaemonSession;
|
|
18382
18332
|
exports.stageClaudeAttachments = stageClaudeAttachments;
|
|
18383
18333
|
exports.startHappyServer = startHappyServer;
|
|
18384
18334
|
exports.stopSession = stopSession;
|