very-happy-cli 0.2.138 → 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.
Files changed (45) hide show
  1. package/dist/{AcpBackend-bqVGMkPh.mjs → AcpBackend-BwTEBAyP.mjs} +2 -2
  2. package/dist/{AcpBackend-BUoDXZnv.cjs → AcpBackend-ioCPQLt4.cjs} +2 -2
  3. package/dist/{AcpSessionManager-BBAQ8EQf.mjs → AcpSessionManager-Bh3KETfz.mjs} +1 -1
  4. package/dist/{AcpSessionManager-DmmA52Ep.cjs → AcpSessionManager-o9T6W69-.cjs} +1 -1
  5. package/dist/{agentGuidance-WHZsBKpm.mjs → agentGuidance-DRnXdFAY.mjs} +1 -1
  6. package/dist/{agentGuidance-4HV-BOge.cjs → agentGuidance-Dxt2uz3R.cjs} +1 -1
  7. package/dist/codex/happyMcpStdioBridge.cjs +2 -2
  8. package/dist/codex/happyMcpStdioBridge.mjs +2 -2
  9. package/dist/{config-DpuZN2Rs.cjs → config-nyMHCx-i.cjs} +4 -4
  10. package/dist/{config-BRXqgJJj.mjs → config-o9NFsj8x.mjs} +4 -4
  11. package/dist/{index-Dbl5U_N0.mjs → index-BZr5l8TH.mjs} +93 -230
  12. package/dist/{index-DQe7ljLR.mjs → index-BkmfJyCf.mjs} +7 -7
  13. package/dist/{index-CRRK5P1r.cjs → index-C3NtU4Ch.cjs} +124 -266
  14. package/dist/{index-D8Q3OhdR.mjs → index-CTemcNko.mjs} +4 -4
  15. package/dist/{index-CHP265gs.cjs → index-gkFhwPXq.cjs} +4 -4
  16. package/dist/{index-3N-qu-RG.cjs → index-klhxcpC8.cjs} +7 -7
  17. package/dist/index.cjs +4 -4
  18. package/dist/index.mjs +4 -4
  19. package/dist/{installTerminalHooks-DfUGgeyb.mjs → installTerminalHooks-8CHTgUC-.mjs} +4 -4
  20. package/dist/{installTerminalHooks-CWGkoWDD.cjs → installTerminalHooks-DZUBgnFh.cjs} +4 -4
  21. package/dist/lib.cjs +2 -2
  22. package/dist/lib.d.cts +21 -0
  23. package/dist/lib.d.mts +21 -0
  24. package/dist/lib.mjs +2 -2
  25. package/dist/{limits-CfzVummd.cjs → limits-C_RGzva6.cjs} +26 -7
  26. package/dist/{limits-DEsg_gHi.mjs → limits-DefXc1TL.mjs} +26 -8
  27. package/dist/{mcp-UnjB3I8_.mjs → mcp-8DcunR0J.mjs} +19 -19
  28. package/dist/{mcp-CN2UVfut.cjs → mcp-czNIfD59.cjs} +21 -21
  29. package/dist/{runGemini-BZ0xXRj-.mjs → runGemini-CDUObQTD.mjs} +6 -6
  30. package/dist/{runGemini-BUVjTJKn.cjs → runGemini-Dy3y-lD9.cjs} +7 -7
  31. package/dist/{runOpenClaw-BcUmnBpW.mjs → runOpenClaw-B6KMCsVB.mjs} +5 -5
  32. package/dist/{runOpenClaw-Bj2EgRHB.cjs → runOpenClaw-CJusckVM.cjs} +6 -6
  33. package/dist/{send-BkypdBpK.cjs → send-B4Qo-87h.cjs} +4 -4
  34. package/dist/{send-snK_NGAA.mjs → send-BT32Jiel.mjs} +4 -4
  35. package/dist/{sessions-9A-uoJL_.cjs → sessions-CN2y0xBl.cjs} +4 -4
  36. package/dist/{sessions-DxlC4C4g.mjs → sessions-Dh0Lg-5z.mjs} +4 -4
  37. package/dist/{spawn-DFfHCafP.mjs → spawn-DFIyobCt.mjs} +6 -6
  38. package/dist/{spawn-BORLpj60.cjs → spawn-jWj3xFhX.cjs} +8 -8
  39. package/dist/{teams-9x2FO9RW.cjs → teams-BhFspeAY.cjs} +4 -4
  40. package/dist/{teams-Cfr-2Yd-.mjs → teams-CZ9ICWeB.mjs} +4 -4
  41. package/dist/{todo-DydKcknX.cjs → todo-B0kvqUTQ.cjs} +3 -3
  42. package/dist/{todo-CU5cjQZU.mjs → todo-jL3ttna3.mjs} +3 -3
  43. package/dist/{types-D5EsIAOe.mjs → types-CrKeJuyF.mjs} +558 -13
  44. package/dist/{types-CRxf_3n8.cjs → types-CxGm_YJ-.cjs} +571 -13
  45. 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-CRxf_3n8.cjs');
7
- var persistence = require('./limits-CfzVummd.cjs');
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-4HV-BOge.cjs');
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-CRRK5P1r.cjs', document.baseURI).href))).resolve(s)) {
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
- idle: () => pidToTrackedSession.size === 0 && !apiMachine.hasLiveTerminals(),
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() && pidToTrackedSession.size === 0 && !apiMachine.hasLiveTerminals()) {
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() || pidToTrackedSession.size > 0 || apiMachine.hasLiveTerminals()) return;
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-CHP265gs.cjs'); });
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-CRRK5P1r.cjs', document.baseURI).href)));
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-CRRK5P1r.cjs', document.baseURI).href)));
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-CRRK5P1r.cjs', document.baseURI).href)));
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;
@@ -16808,6 +16653,12 @@ async function runCodex(opts) {
16808
16653
  ...forkedFromMessageId ? { forkedFromMessageId } : {}
16809
16654
  });
16810
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
+ }
16811
16662
  const reconnectSessionId = process.env.HAPPY_RECONNECT_SESSION_ID;
16812
16663
  const reconnectKeyBase64 = process.env.HAPPY_RECONNECT_ENCRYPTION_KEY;
16813
16664
  const reconnectVariant = process.env.HAPPY_RECONNECT_ENCRYPTION_VARIANT;
@@ -16878,7 +16729,7 @@ async function runCodex(opts) {
16878
16729
  if (response) {
16879
16730
  try {
16880
16731
  persistence.logger.debug(`[START] Reporting session ${response.id} to daemon`);
16881
- const result = await notifyDaemonSessionStarted(response.id, metadata, {
16732
+ const result = await api.notifyDaemonSessionStarted(response.id, metadata, {
16882
16733
  encryptionKey: persistence.encodeBase64(response.encryptionKey),
16883
16734
  encryptionVariant: response.encryptionVariant,
16884
16735
  seq: response.seq,
@@ -17326,6 +17177,18 @@ async function runCodex(opts) {
17326
17177
  first = false;
17327
17178
  appendSystemPromptInjected = true;
17328
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
+ }
17329
17192
  const forkCodexThreadId = process.env.HAPPY_FORK_CODEX_THREAD_ID;
17330
17193
  if (!reconnectSessionId && forkCodexThreadId) {
17331
17194
  try {
@@ -17679,7 +17542,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
17679
17542
  process.exit(0);
17680
17543
  } else if (subcommand === "install-terminal-hooks") {
17681
17544
  try {
17682
- const { installTerminalHooks, parseTerminalHooksArgs, TERMINAL_HOOKS_HELP } = await Promise.resolve().then(function () { return require('./installTerminalHooks-CWGkoWDD.cjs'); });
17545
+ const { installTerminalHooks, parseTerminalHooksArgs, TERMINAL_HOOKS_HELP } = await Promise.resolve().then(function () { return require('./installTerminalHooks-DZUBgnFh.cjs'); });
17683
17546
  const command = parseTerminalHooksArgs(args.slice(1));
17684
17547
  if (command.action === "help") {
17685
17548
  console.log(TERMINAL_HOOKS_HELP);
@@ -17696,7 +17559,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
17696
17559
  }
17697
17560
  } else if (subcommand === "spawn") {
17698
17561
  try {
17699
- const { handleSpawnCommand } = await Promise.resolve().then(function () { return require('./spawn-BORLpj60.cjs'); });
17562
+ const { handleSpawnCommand } = await Promise.resolve().then(function () { return require('./spawn-jWj3xFhX.cjs'); });
17700
17563
  await handleSpawnCommand(args.slice(1));
17701
17564
  } catch (error) {
17702
17565
  console.error(chalk.red("Error:"), error instanceof Error ? error.message : "Unknown error");
@@ -17708,7 +17571,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
17708
17571
  return;
17709
17572
  } else if (subcommand === "sessions") {
17710
17573
  try {
17711
- const { handleSessionsCommand } = await Promise.resolve().then(function () { return require('./sessions-9A-uoJL_.cjs'); });
17574
+ const { handleSessionsCommand } = await Promise.resolve().then(function () { return require('./sessions-CN2y0xBl.cjs'); });
17712
17575
  await handleSessionsCommand(args.slice(1));
17713
17576
  } catch (error) {
17714
17577
  console.error(chalk.red("Error:"), error instanceof Error ? error.message : "Unknown error");
@@ -17720,7 +17583,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
17720
17583
  return;
17721
17584
  } else if (subcommand === "send") {
17722
17585
  try {
17723
- const { handleSendCommand } = await Promise.resolve().then(function () { return require('./send-BkypdBpK.cjs'); });
17586
+ const { handleSendCommand } = await Promise.resolve().then(function () { return require('./send-B4Qo-87h.cjs'); });
17724
17587
  await handleSendCommand(args.slice(1));
17725
17588
  } catch (error) {
17726
17589
  console.error(chalk.red("Error:"), error instanceof Error ? error.message : "Unknown error");
@@ -17826,9 +17689,9 @@ Conversation history is preserved on the server, but in-flight tool calls are in
17826
17689
  if (geminiSubcommand === "project" && args[2] === "set" && args[3]) {
17827
17690
  const projectId = args[3];
17828
17691
  try {
17829
- const { saveGoogleCloudProjectToConfig } = await Promise.resolve().then(function () { return require('./config-DpuZN2Rs.cjs'); });
17830
- const { readCredentialsForConfiguredRelay: readCredentialsForConfiguredRelay2 } = await Promise.resolve().then(function () { return require('./limits-CfzVummd.cjs'); }).then(function (n) { return n.persistence; });
17831
- const { ApiClient: ApiClient2 } = await Promise.resolve().then(function () { return require('./types-CRxf_3n8.cjs'); }).then(function (n) { return n.api; });
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; });
17832
17695
  let userEmail = void 0;
17833
17696
  try {
17834
17697
  const credentials = await readCredentialsForConfiguredRelay2();
@@ -17859,7 +17722,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
17859
17722
  }
17860
17723
  if (geminiSubcommand === "project" && args[2] === "get") {
17861
17724
  try {
17862
- const { readGeminiLocalConfig } = await Promise.resolve().then(function () { return require('./config-DpuZN2Rs.cjs'); });
17725
+ const { readGeminiLocalConfig } = await Promise.resolve().then(function () { return require('./config-nyMHCx-i.cjs'); });
17863
17726
  const config = readGeminiLocalConfig();
17864
17727
  if (config.googleCloudProject) {
17865
17728
  console.log(`Current Google Cloud Project: ${config.googleCloudProject}`);
@@ -17899,7 +17762,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
17899
17762
  process.exit(0);
17900
17763
  }
17901
17764
  try {
17902
- const { runGemini } = await Promise.resolve().then(function () { return require('./runGemini-BUVjTJKn.cjs'); });
17765
+ const { runGemini } = await Promise.resolve().then(function () { return require('./runGemini-Dy3y-lD9.cjs'); });
17903
17766
  let startedBy = void 0;
17904
17767
  for (let i = 1; i < args.length; i++) {
17905
17768
  if (args[i] === "--started-by") {
@@ -17929,7 +17792,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
17929
17792
  }
17930
17793
  };
17931
17794
  try {
17932
- const { runAcp, resolveAcpAgentConfig } = await Promise.resolve().then(function () { return require('./index-3N-qu-RG.cjs'); });
17795
+ const { runAcp, resolveAcpAgentConfig } = await Promise.resolve().then(function () { return require('./index-klhxcpC8.cjs'); });
17933
17796
  const parsed = parsePiRunnerArgs(args.slice(1));
17934
17797
  const resolved = resolveAcpAgentConfig(["pi", ...parsed.passthrough]);
17935
17798
  const { credentials } = await authAndSetupMachineIfNeeded();
@@ -17957,7 +17820,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
17957
17820
  return;
17958
17821
  } else if (subcommand === "acp") {
17959
17822
  try {
17960
- const { runAcp, resolveAcpAgentConfig } = await Promise.resolve().then(function () { return require('./index-3N-qu-RG.cjs'); });
17823
+ const { runAcp, resolveAcpAgentConfig } = await Promise.resolve().then(function () { return require('./index-klhxcpC8.cjs'); });
17961
17824
  let startedBy = void 0;
17962
17825
  let verbose = false;
17963
17826
  const acpArgs = [];
@@ -17997,7 +17860,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
17997
17860
  return;
17998
17861
  } else if (subcommand === "openclaw") {
17999
17862
  try {
18000
- const { runOpenClaw } = await Promise.resolve().then(function () { return require('./runOpenClaw-Bj2EgRHB.cjs'); });
17863
+ const { runOpenClaw } = await Promise.resolve().then(function () { return require('./runOpenClaw-CJusckVM.cjs'); });
18001
17864
  let startedBy = void 0;
18002
17865
  let verbose = false;
18003
17866
  let gatewayUrl;
@@ -18048,7 +17911,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
18048
17911
  return;
18049
17912
  } else if (subcommand === "todo") {
18050
17913
  try {
18051
- const { handleTodoCommand } = await Promise.resolve().then(function () { return require('./todo-DydKcknX.cjs'); });
17914
+ const { handleTodoCommand } = await Promise.resolve().then(function () { return require('./todo-B0kvqUTQ.cjs'); });
18052
17915
  await handleTodoCommand(args.slice(1));
18053
17916
  } catch (error) {
18054
17917
  console.error(JSON.stringify({ error: error instanceof Error ? error.message : "Todo command failed" }));
@@ -18057,7 +17920,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
18057
17920
  return;
18058
17921
  } else if (subcommand === "teams") {
18059
17922
  try {
18060
- const { handleTeamsCommand } = await Promise.resolve().then(function () { return require('./teams-9x2FO9RW.cjs'); });
17923
+ const { handleTeamsCommand } = await Promise.resolve().then(function () { return require('./teams-BhFspeAY.cjs'); });
18061
17924
  await handleTeamsCommand(args.slice(1));
18062
17925
  } catch (error) {
18063
17926
  console.error(error instanceof Error ? error.message : "Teams command failed");
@@ -18066,7 +17929,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
18066
17929
  return;
18067
17930
  } else if (subcommand === "mcp" && args.length === 1) {
18068
17931
  try {
18069
- const { handleMcpCommand } = await Promise.resolve().then(function () { return require('./mcp-CN2UVfut.cjs'); });
17932
+ const { handleMcpCommand } = await Promise.resolve().then(function () { return require('./mcp-czNIfD59.cjs'); });
18070
17933
  await handleMcpCommand();
18071
17934
  } catch (error) {
18072
17935
  process.stderr.write(`[very-happy mcp] Fatal: ${error instanceof Error ? error.message : String(error)}
@@ -18089,7 +17952,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
18089
17952
  const daemonSubcommand = args[1];
18090
17953
  if (daemonSubcommand === "list") {
18091
17954
  try {
18092
- const sessions = await listDaemonSessions();
17955
+ const sessions = await api.listDaemonSessions();
18093
17956
  if (sessions.length === 0) {
18094
17957
  console.log("No active sessions this daemon is aware of (they might have been started by a previous version of the daemon)");
18095
17958
  } else {
@@ -18107,7 +17970,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
18107
17970
  process.exit(1);
18108
17971
  }
18109
17972
  try {
18110
- const success = await stopDaemonSession(sessionId);
17973
+ const success = await api.stopDaemonSession(sessionId);
18111
17974
  console.log(success ? "Session stopped" : "Failed to stop session");
18112
17975
  } catch (error) {
18113
17976
  console.log("No daemon running");
@@ -18115,7 +17978,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
18115
17978
  return;
18116
17979
  } else if (daemonSubcommand === "start") {
18117
17980
  const currentState = await persistence.readDaemonState();
18118
- const running = await checkIfDaemonRunningAndCleanupStaleState();
17981
+ const running = await api.checkIfDaemonRunningAndCleanupStaleState();
18119
17982
  const currentDaemonMatches = currentState && currentState.startedWithCliVersion === persistence.configuration.currentCliVersion && daemonEndpointsMatch(
18120
17983
  currentState.serverUrl,
18121
17984
  currentState.webappUrl,
@@ -18124,7 +17987,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
18124
17987
  );
18125
17988
  if (running && !currentDaemonMatches) {
18126
17989
  console.log("Configured relay or CLI version changed; restarting the existing daemon");
18127
- await stopDaemon();
17990
+ await api.stopDaemon();
18128
17991
  }
18129
17992
  const child = spawnHappyCLI(["daemon", "start-sync"], {
18130
17993
  detached: true,
@@ -18134,7 +17997,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
18134
17997
  child.unref();
18135
17998
  let started = false;
18136
17999
  for (let i = 0; i < 50; i++) {
18137
- if (await checkIfDaemonRunningAndCleanupStaleState()) {
18000
+ if (await api.checkIfDaemonRunningAndCleanupStaleState()) {
18138
18001
  started = true;
18139
18002
  break;
18140
18003
  }
@@ -18151,7 +18014,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
18151
18014
  await startDaemon();
18152
18015
  process.exit(0);
18153
18016
  } else if (daemonSubcommand === "stop") {
18154
- await stopDaemon();
18017
+ await api.stopDaemon();
18155
18018
  process.exit(0);
18156
18019
  } else if (daemonSubcommand === "status") {
18157
18020
  await runDoctorDaemon();
@@ -18448,7 +18311,6 @@ exports.TEAM_SKILL = TEAM_SKILL;
18448
18311
  exports.TitleGenerator = TitleGenerator;
18449
18312
  exports.appendStagedAttachmentsToPrompt = appendStagedAttachmentsToPrompt;
18450
18313
  exports.archiveSession = archiveSession;
18451
- exports.checkIfDaemonRunningAndCleanupStaleState = checkIfDaemonRunningAndCleanupStaleState;
18452
18314
  exports.createSessionMetadata = createSessionMetadata;
18453
18315
  exports.hashObject = hashObject;
18454
18316
  exports.initialMachineMetadata = initialMachineMetadata;
@@ -18456,8 +18318,6 @@ exports.isValidSpawnOrigin = isValidSpawnOrigin;
18456
18318
  exports.listAccountSessions = listAccountSessions;
18457
18319
  exports.listSessions = listSessions;
18458
18320
  exports.normalizeAcpPermissionMode = normalizeAcpPermissionMode;
18459
- exports.notifyDaemonSessionStarted = notifyDaemonSessionStarted;
18460
- exports.pushClipboardViaDaemon = pushClipboardViaDaemon;
18461
18321
  exports.query = query;
18462
18322
  exports.readSessionTranscript = readSessionTranscript;
18463
18323
  exports.registerAgentAttachmentDownloads = registerAgentAttachmentDownloads;
@@ -18468,9 +18328,7 @@ exports.resolvePermissionRequest = resolvePermissionRequest;
18468
18328
  exports.sanitizeSpawnPermissionMode = sanitizeSpawnPermissionMode;
18469
18329
  exports.sendUserMessage = sendUserMessage;
18470
18330
  exports.sessionWebUrl = sessionWebUrl;
18471
- exports.setTerminalTitleViaDaemon = setTerminalTitleViaDaemon;
18472
18331
  exports.setupOfflineReconnection = setupOfflineReconnection;
18473
- exports.spawnDaemonSession = spawnDaemonSession;
18474
18332
  exports.stageClaudeAttachments = stageClaudeAttachments;
18475
18333
  exports.startHappyServer = startHappyServer;
18476
18334
  exports.stopSession = stopSession;