very-happy-cli 0.2.156 → 0.2.157

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 (55) hide show
  1. package/dist/{AcpBackend-BHe1_F1h.cjs → AcpBackend-BymWX-LI.cjs} +2 -2
  2. package/dist/{AcpBackend-C3nc1u-s.mjs → AcpBackend-Cy18U7yw.mjs} +2 -2
  3. package/dist/{AcpSessionManager-BVxkQnNf.cjs → AcpSessionManager-BF7zBGAi.cjs} +1 -1
  4. package/dist/{AcpSessionManager-dN3k1LbI.mjs → AcpSessionManager-Ds8rcp95.mjs} +1 -1
  5. package/dist/{agentGuidance-C604n0Zq.mjs → agentGuidance-CU6YD_Ms.mjs} +560 -29
  6. package/dist/{agentGuidance-C-CmV03f.cjs → agentGuidance-Db76O1kw.cjs} +579 -28
  7. package/dist/{agentHome-CmIJNV7f.cjs → agentHome-B0CLy0Qx.cjs} +2 -2
  8. package/dist/{agentHome-D2XGsoqs.mjs → agentHome-BaJ9xtxB.mjs} +2 -2
  9. package/dist/{auto-B1I6G_Nf.mjs → auto-B1YAwaeU.mjs} +6 -6
  10. package/dist/{auto-CMDq4oIu.cjs → auto-DqKGFq8U.cjs} +6 -6
  11. package/dist/codex/happyMcpStdioBridge.cjs +2 -2
  12. package/dist/codex/happyMcpStdioBridge.mjs +2 -2
  13. package/dist/{config-BYHSRY2E.cjs → config-CzkBjZnV.cjs} +4 -4
  14. package/dist/{config-BkTu25bH.mjs → config-aAbhJllb.mjs} +4 -4
  15. package/dist/{index-B5QbzEga.mjs → index-BVu8Cufk.mjs} +8 -8
  16. package/dist/{index-DAAreiRF.mjs → index-BYU1e81k.mjs} +288 -44
  17. package/dist/{index-BbtR-Qto.cjs → index-C9QzZsUQ.cjs} +291 -47
  18. package/dist/{index-B_-7NpGZ.cjs → index-CTbGqVFY.cjs} +7 -7
  19. package/dist/{index-CB8QnjvS.cjs → index-Cz-uqnJk.cjs} +4 -4
  20. package/dist/{index-PYO8Mdz4.mjs → index-DQcRkI9r.mjs} +4 -4
  21. package/dist/index.cjs +4 -4
  22. package/dist/index.mjs +4 -4
  23. package/dist/{install-CO1ps6Wt.cjs → install-BMlV0Tnr.cjs} +1 -1
  24. package/dist/{install-CNtXzwT_.mjs → install-BuYnqtVa.mjs} +1 -1
  25. package/dist/{installTerminalHooks-BOAnQ1Qe.cjs → installTerminalHooks-BVVOEGhG.cjs} +4 -4
  26. package/dist/{installTerminalHooks-CMpOV3RU.mjs → installTerminalHooks-ELDoqh0A.mjs} +4 -4
  27. package/dist/lib.cjs +2 -2
  28. package/dist/lib.d.cts +77 -1
  29. package/dist/lib.d.mts +77 -1
  30. package/dist/lib.mjs +2 -2
  31. package/dist/{limits-DmMdchTz.mjs → limits-A2c-3M-_.mjs} +162 -11
  32. package/dist/{limits-o29KXBgj.cjs → limits-CyuIt-Vl.cjs} +169 -10
  33. package/dist/{mcp-C_uejotl.mjs → mcp-Bo934Kpy.mjs} +4 -4
  34. package/dist/{mcp-CwK1nI7Y.cjs → mcp-CXkvnztT.cjs} +4 -4
  35. package/dist/{piRuntime-Dj5WnqzJ.cjs → piRuntime-CJjA26oD.cjs} +2 -2
  36. package/dist/{piRuntime-Cu2-8nOT.mjs → piRuntime-DdEY2mE9.mjs} +2 -2
  37. package/dist/{piTerminal-D-BIbov9.cjs → piTerminal-CpU3hzrX.cjs} +6 -6
  38. package/dist/{piTerminal-DanZeBrO.mjs → piTerminal-DwWmgumi.mjs} +6 -6
  39. package/dist/{runGemini-CZ_lhMWY.mjs → runGemini-Cj6oJQ-I.mjs} +6 -6
  40. package/dist/{runGemini--QqK-Ap5.cjs → runGemini-DS-0qm0L.cjs} +6 -6
  41. package/dist/{runOpenClaw-C0xLhTvk.cjs → runOpenClaw-CvSm8oTc.cjs} +5 -5
  42. package/dist/{runOpenClaw-CxgLpm38.mjs → runOpenClaw-DUCQxkI-.mjs} +5 -5
  43. package/dist/{send-CTcGMVuG.cjs → send-CHxobaoI.cjs} +43 -31
  44. package/dist/{send-BaOkDgH0.mjs → send-D5CyRyZ_.mjs} +43 -31
  45. package/dist/{sessions-OmvyJb0n.cjs → sessions-BFlIrKCY.cjs} +133 -49
  46. package/dist/{sessions-Bn304xF1.mjs → sessions-DsE01xKc.mjs} +133 -49
  47. package/dist/{spawn-BKNabutV.mjs → spawn-CdihhwHs.mjs} +4 -4
  48. package/dist/{spawn-CC6V2KiA.cjs → spawn-HV345RN-.cjs} +4 -4
  49. package/dist/{teams-CLbS2_4Q.mjs → teams-BE8nMB6O.mjs} +5 -5
  50. package/dist/{teams-XtrH3_h3.cjs → teams-BahinMnH.cjs} +5 -5
  51. package/dist/{todo-CEDvKNXK.cjs → todo-CMMQ6yhU.cjs} +2 -2
  52. package/dist/{todo-BcPbNKt2.mjs → todo-CuQAkSp2.mjs} +2 -2
  53. package/dist/{types-CphWjqHc.cjs → types-B0sSi6eM.cjs} +77 -4
  54. package/dist/{types-BEVzYSoV.mjs → types-BrGJ7PJz.mjs} +77 -4
  55. package/package.json +7 -7
@@ -3,14 +3,14 @@
3
3
  var chalk = require('chalk');
4
4
  var os = require('node:os');
5
5
  var node_crypto = require('node:crypto');
6
- var index = require('./types-CphWjqHc.cjs');
7
- var persistence = require('./limits-o29KXBgj.cjs');
6
+ var index = require('./types-B0sSi6eM.cjs');
7
+ var persistence = require('./limits-CyuIt-Vl.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
12
  var terminalTitleSuggest = require('./terminalTitleSuggest-Dji8I0Jy.cjs');
13
- var agentGuidance = require('./agentGuidance-C-CmV03f.cjs');
13
+ var agentGuidance = require('./agentGuidance-Db76O1kw.cjs');
14
14
  var promises = require('node:fs/promises');
15
15
  var fs = require('fs/promises');
16
16
  var ink = require('ink');
@@ -137,6 +137,11 @@ class Session {
137
137
  sessionId;
138
138
  mode = "local";
139
139
  thinking = false;
140
+ /** B-507: background tasks still in flight (async sub-agents, backgrounded
141
+ * commands, monitors) — published with every keepAlive. Always an array
142
+ * for the Claude runner: an empty one says "nothing running", which is a
143
+ * different statement from a runner that has no such notion (undefined). */
144
+ backgroundTasks = [];
140
145
  /**
141
146
  * Window after a user-initiated abort during which stray promise rejections
142
147
  * from tearing down the SDK query (MCP transports, in-flight tool calls,
@@ -198,11 +203,21 @@ class Session {
198
203
  persistence.logger.debug("[Session] Failed to create notification producer:", err);
199
204
  this.notificationProducer = null;
200
205
  }
201
- this.client.keepAlive(this.thinking, this.mode);
206
+ this.client.keepAlive(this.thinking, this.mode, this.backgroundTasks);
202
207
  this.keepAliveInterval = setInterval(() => {
203
- this.client.keepAlive(this.thinking, this.mode);
208
+ this.client.keepAlive(this.thinking, this.mode, this.backgroundTasks);
204
209
  }, 2e3);
205
210
  }
211
+ /**
212
+ * B-507: the tracker's current set (`claude/backgroundTasks.ts`). A change
213
+ * beats at once so the daemon, agentState and the web see the edge without
214
+ * waiting for the 2s tick; an unchanged set is left to the interval.
215
+ */
216
+ setBackgroundTasks = (tasks) => {
217
+ if (persistence.sameBackgroundTasks(this.backgroundTasks, tasks)) return;
218
+ this.backgroundTasks = tasks;
219
+ this.client.keepAlive(this.thinking, this.mode, this.backgroundTasks);
220
+ };
206
221
  /**
207
222
  * Cleanup resources (call when session is no longer needed)
208
223
  */
@@ -237,7 +252,7 @@ class Session {
237
252
  this.lastAssistantSnippet = void 0;
238
253
  }
239
254
  this.thinking = thinking;
240
- this.client.keepAlive(thinking, this.mode);
255
+ this.client.keepAlive(thinking, this.mode, this.backgroundTasks);
241
256
  };
242
257
  /**
243
258
  * Record that Claude emitted an assistant text reply during this turn.
@@ -304,7 +319,7 @@ class Session {
304
319
  };
305
320
  onModeChange = (mode) => {
306
321
  this.mode = mode;
307
- this.client.keepAlive(this.thinking, mode);
322
+ this.client.keepAlive(this.thinking, mode, this.backgroundTasks);
308
323
  this._onModeChange(mode);
309
324
  };
310
325
  onAbort = () => {
@@ -3948,6 +3963,7 @@ async function claudeRemoteLauncher(session, onPermissionModeChange, onEffective
3948
3963
  const turnSteering = createTurnSteeringController();
3949
3964
  const runtimeControls = createRuntimeControls(() => session.thinking);
3950
3965
  session.client.rpcHandlerManager.registerHandler("claude-runtime-control", async (input) => runtimeControls.request(input));
3966
+ const backgroundTasks = persistence.createBackgroundTaskTracker();
3951
3967
  async function abort() {
3952
3968
  if (abortController && !abortController.signal.aborted) {
3953
3969
  abortController.abort();
@@ -4033,6 +4049,8 @@ async function claudeRemoteLauncher(session, onPermissionModeChange, onEffective
4033
4049
  let notifiedQuestionToolCalls = /* @__PURE__ */ new Set();
4034
4050
  function onMessage(message) {
4035
4051
  runtimeControls.observe(message);
4052
+ backgroundTasks.observe(message);
4053
+ session.setBackgroundTasks(backgroundTasks.list());
4036
4054
  if (isRuntimeCheckpointReplay(message)) return;
4037
4055
  if (message.type === "user" && isClaudeInterruptSentinelContent(message.message.content)) {
4038
4056
  sdkToLogConverter.convert(message);
@@ -4257,6 +4275,8 @@ async function claudeRemoteLauncher(session, onPermissionModeChange, onEffective
4257
4275
  },
4258
4276
  onQueryReady: (q) => {
4259
4277
  runtimeControls.setQuery(q);
4278
+ backgroundTasks.reset();
4279
+ session.setBackgroundTasks([]);
4260
4280
  turnSteering.setInterrupt(q.interrupt);
4261
4281
  session.setSideQuestionLive({ ask: q.sideQuestion, canControl: q.canControl });
4262
4282
  session.setSteerHandler(async (input) => {
@@ -4353,6 +4373,8 @@ async function claudeRemoteLauncher(session, onPermissionModeChange, onEffective
4353
4373
  }
4354
4374
  } finally {
4355
4375
  runtimeControls.setQuery(null);
4376
+ backgroundTasks.reset();
4377
+ session.setBackgroundTasks([]);
4356
4378
  turnSteering.reset();
4357
4379
  session.setSteerHandler(null);
4358
4380
  session.setSideQuestionLive(null);
@@ -5402,8 +5424,8 @@ ${typeLabels[type] || type}:`));
5402
5424
  }
5403
5425
  console.log(chalk.gray(" An external claude command is only needed for native terminal/mirror use."));
5404
5426
  try {
5405
- const { resolveAgentHomesForCli } = await Promise.resolve().then(function () { return require('./agentHome-CmIJNV7f.cjs'); });
5406
- const { describeAgentHome } = await Promise.resolve().then(function () { return require('./types-CphWjqHc.cjs'); }).then(function (n) { return n.index; });
5427
+ const { resolveAgentHomesForCli } = await Promise.resolve().then(function () { return require('./agentHome-B0CLy0Qx.cjs'); });
5428
+ const { describeAgentHome } = await Promise.resolve().then(function () { return require('./types-B0sSi6eM.cjs'); }).then(function (n) { return n.index; });
5407
5429
  const homes = await resolveAgentHomesForCli();
5408
5430
  console.log(chalk.green(`\u2713 Claude config dir: ${describeAgentHome(homes.claudeConfigDir)}`));
5409
5431
  console.log(chalk.green(`\u2713 Codex home: ${describeAgentHome(homes.codexHome)}`));
@@ -6226,6 +6248,18 @@ function checkPreviewPath(input, opts) {
6226
6248
  return { resolved, deniedReason: null };
6227
6249
  }
6228
6250
 
6251
+ const BackgroundTaskInfoSchema = z.z.object({
6252
+ id: z.z.string().min(1).max(200),
6253
+ type: z.z.string().max(64),
6254
+ description: z.z.string().max(persistence.BACKGROUND_TASK_DESCRIPTION_MAX + 1),
6255
+ startedAt: z.z.number()
6256
+ });
6257
+ const BackgroundTasksReportSchema = z.z.object({
6258
+ count: z.z.number().int().nonnegative(),
6259
+ tasks: z.z.array(BackgroundTaskInfoSchema),
6260
+ reportedAt: z.z.number().optional(),
6261
+ stale: z.z.boolean().optional()
6262
+ });
6229
6263
  function startDaemonControlServer({
6230
6264
  controlToken,
6231
6265
  getChildren,
@@ -6237,6 +6271,8 @@ function startDaemonControlServer({
6237
6271
  onSessionStateEvent,
6238
6272
  onClaudeAuthFailed,
6239
6273
  onSessionTurnEvent,
6274
+ onSessionBackgroundTasks,
6275
+ getBackgroundTasks,
6240
6276
  pushClipboard,
6241
6277
  pushFilePreview,
6242
6278
  onTerminalHook,
@@ -6297,8 +6333,10 @@ function startDaemonControlServer({
6297
6333
  schema: {
6298
6334
  body: z.z.object({
6299
6335
  sessionId: z.z.string(),
6300
- event: z.z.enum(["completed", "needs_input", "auth_failed", "turn_started", "turn_ended"]),
6301
- spawnedBy: z.z.string().optional()
6336
+ event: z.z.enum(["completed", "needs_input", "auth_failed", "turn_started", "turn_ended", "background_tasks"]),
6337
+ spawnedBy: z.z.string().optional(),
6338
+ // B-507: only with event 'background_tasks' — the wrapper's full set.
6339
+ backgroundTasks: z.z.array(BackgroundTaskInfoSchema).max(persistence.BACKGROUND_TASKS_MAX).optional()
6302
6340
  }),
6303
6341
  response: {
6304
6342
  200: z.z.object({
@@ -6309,6 +6347,10 @@ function startDaemonControlServer({
6309
6347
  }, async (request) => {
6310
6348
  const { sessionId, event, spawnedBy } = request.body;
6311
6349
  persistence.logger.debug(`[CONTROL SERVER] Session event: ${sessionId} ${event} (spawnedBy=${spawnedBy ?? "unset"})`);
6350
+ if (event === "background_tasks") {
6351
+ onSessionBackgroundTasks?.(sessionId, request.body.backgroundTasks ?? []);
6352
+ return { status: "ok" };
6353
+ }
6312
6354
  if (event === "auth_failed") {
6313
6355
  onClaudeAuthFailed?.(sessionId);
6314
6356
  return { status: "ok" };
@@ -6328,7 +6370,9 @@ function startDaemonControlServer({
6328
6370
  startedBy: z.z.string(),
6329
6371
  happySessionId: z.z.string(),
6330
6372
  pid: z.z.number(),
6331
- turnActive: z.z.boolean()
6373
+ turnActive: z.z.boolean(),
6374
+ // B-507: in-flight background tasks per the wrapper's last report (lease-expired = count 0).
6375
+ backgroundTasks: BackgroundTasksReportSchema.optional()
6332
6376
  }))
6333
6377
  })
6334
6378
  }
@@ -6341,7 +6385,8 @@ function startDaemonControlServer({
6341
6385
  startedBy: child.startedBy,
6342
6386
  happySessionId: child.happySessionId,
6343
6387
  pid: child.pid,
6344
- turnActive: isTurnActive ? isTurnActive(child.happySessionId) : false
6388
+ turnActive: isTurnActive ? isTurnActive(child.happySessionId) : false,
6389
+ ...getBackgroundTasks ? { backgroundTasks: getBackgroundTasks(child.happySessionId) } : {}
6345
6390
  }))
6346
6391
  };
6347
6392
  });
@@ -6909,6 +6954,170 @@ function createPeerCoordinator(deps) {
6909
6954
  };
6910
6955
  }
6911
6956
 
6957
+ const WRITE_METHODS = /* @__PURE__ */ new Set(["sessions.send", "sessions.message"]);
6958
+ const REMOTE_CLIENT_TAG = "cli-send-remote";
6959
+ function defaultDeps(machineId) {
6960
+ return {
6961
+ machineId,
6962
+ host: os.hostname(),
6963
+ enabled: async () => (await persistence.readSettings()).remoteSessionOps !== "off",
6964
+ readPersisted: persistence.readPersistedSessions,
6965
+ listLocal: (options) => agentGuidance.listSessions(options),
6966
+ listAccount: (options) => agentGuidance.listAccountSessions(options),
6967
+ readTranscript: (sessionId, limit, options) => agentGuidance.readSessionTranscript(sessionId, limit, options),
6968
+ deliver: (sessionId, persisted, text, client, options, deps) => agentGuidance.deliverToSession(sessionId, persisted, text, client, options, deps),
6969
+ listPeers: (context, scope) => agentGuidance.listPeerSessions(context, scope),
6970
+ sendPeer: (context, args) => agentGuidance.sendPeerMessage(context, args),
6971
+ log: (line) => persistence.logger.info(line),
6972
+ now: () => Date.now()
6973
+ };
6974
+ }
6975
+ function createRemoteSessionOpsHandlers(machineId, overrides = {}) {
6976
+ const deps = { ...defaultDeps(machineId), ...overrides };
6977
+ const readBudget = deps.budget ?? new agentGuidance.RemoteCallBudget(void 0, deps.now);
6978
+ const writeBudget = deps.writeBudget ?? new agentGuidance.RemoteCallBudget(agentGuidance.REMOTE_WRITE_CALLS_PER_MINUTE, deps.now);
6979
+ const deadlineMs = deps.deadlineMs ?? agentGuidance.REMOTE_OP_DEADLINE_MS;
6980
+ const sendCommitDeadlineMs = deps.sendCommitDeadlineMs ?? agentGuidance.REMOTE_SEND_COMMIT_DEADLINE_MS;
6981
+ const resumeWaitMs = deps.resumeWaitMs ?? agentGuidance.REMOTE_RESUME_WAIT_MS;
6982
+ const run = (method, op, targetOf) => async (params) => {
6983
+ const started = deps.now();
6984
+ let from = null;
6985
+ let sessionId;
6986
+ const finish = (response) => {
6987
+ const outcome = response.ok ? "ok" : response.error.code;
6988
+ deps.log(agentGuidance.formatRemoteAuditLine({ method, from, sessionId, outcome, durationMs: deps.now() - started }));
6989
+ return response;
6990
+ };
6991
+ let enabled = false;
6992
+ try {
6993
+ enabled = await deps.enabled();
6994
+ } catch {
6995
+ enabled = false;
6996
+ }
6997
+ const guard = agentGuidance.guardRemoteSessionOpsRequest(method, params, { enabled });
6998
+ if (!guard.ok) return finish(guard);
6999
+ from = guard.request.from;
7000
+ sessionId = targetOf(guard.request.args);
7001
+ const budget = WRITE_METHODS.has(method) ? writeBudget : readBudget;
7002
+ const token = budget.take();
7003
+ if (!token.ok) {
7004
+ return finish(agentGuidance.remoteError("rate_limited", `This machine accepts at most ${budget.perMinute} remote ${WRITE_METHODS.has(method) ? "send/message" : "list/read/peers"} calls per minute; retry in ${Math.ceil(token.retryAfterMs / 1e3)}s`));
7005
+ }
7006
+ let timer;
7007
+ const deadline = new Promise((_, reject) => {
7008
+ timer = setTimeout(() => reject(new RemoteOpFailure("timeout", `${method} did not finish within ${Math.round(deadlineMs / 1e3)}s on ${deps.host}`)), deadlineMs);
7009
+ timer.unref?.();
7010
+ });
7011
+ try {
7012
+ return finish({ ok: true, result: await Promise.race([op(guard.request.args, from, started), deadline]) });
7013
+ } catch (error) {
7014
+ const message = error instanceof Error ? error.message : "Remote session operation failed";
7015
+ if (error instanceof RemoteOpFailure) return finish(agentGuidance.remoteError(error.code, message));
7016
+ return finish(agentGuidance.remoteError("internal", message));
7017
+ } finally {
7018
+ if (timer) clearTimeout(timer);
7019
+ }
7020
+ };
7021
+ const requirePersisted = (id) => {
7022
+ const persisted = deps.readPersisted()[id];
7023
+ if (!persisted) throw new RemoteOpFailure("no_local_key", `Session ${id} is not on ${deps.host} (no local key there either)`);
7024
+ return persisted;
7025
+ };
7026
+ return {
7027
+ "sessions.list": run("sessions.list", async (args) => {
7028
+ const wanted = args.ids ? new Set(args.ids) : null;
7029
+ let sessions;
7030
+ if (args.all) {
7031
+ sessions = (await deps.listAccount({ tag: args.tag, recentLimit: wanted ? 1e4 : args.limit, includeArchived: true })).filter((row) => row.decryptable);
7032
+ } else if (wanted) {
7033
+ const persisted = deps.readPersisted();
7034
+ const live = await deps.listLocal({ recentLimit: 1e4 });
7035
+ const liveById = new Map(live.map((row) => [row.id, row]));
7036
+ sessions = [...wanted].filter((id) => persisted[id] !== void 0 || liveById.has(id)).map((id) => liveById.get(id) ?? summaryFromPersisted(id, persisted[id]));
7037
+ } else {
7038
+ sessions = await deps.listLocal({ tag: args.tag, recentLimit: args.limit });
7039
+ }
7040
+ if (wanted) sessions = sessions.filter((row) => wanted.has(row.id));
7041
+ const result = { machineId: deps.machineId, host: deps.host, sessions };
7042
+ return result;
7043
+ }, () => void 0),
7044
+ "sessions.read": run("sessions.read", async (args) => {
7045
+ requirePersisted(args.sessionId);
7046
+ const limit = Math.max(1, Math.min(agentGuidance.MAX_READ_LIMIT, args.limit ?? 20));
7047
+ const transcript = await deps.readTranscript(args.sessionId, limit, { full: args.full === true });
7048
+ const capped = agentGuidance.capRemoteTranscript(transcript.transcript);
7049
+ const result = {
7050
+ ...transcript,
7051
+ summary: {
7052
+ ...transcript.summary,
7053
+ ...transcript.summary.title !== void 0 ? { title: agentGuidance.capRemoteText(transcript.summary.title, agentGuidance.REMOTE_TITLE_MAX_BYTES) } : {}
7054
+ },
7055
+ turn: { ...transcript.turn, answer: agentGuidance.capRemoteText(transcript.turn.answer, agentGuidance.REMOTE_ANSWER_MAX_BYTES, "tail") },
7056
+ transcript: capped.transcript,
7057
+ ...capped.truncated ? { truncated: true } : {},
7058
+ machineId: deps.machineId,
7059
+ host: deps.host
7060
+ };
7061
+ return result;
7062
+ }, (args) => args.sessionId),
7063
+ "sessions.send": run("sessions.send", async (args, _from, started) => {
7064
+ const persisted = requirePersisted(args.sessionId);
7065
+ const send = (sessionId, key, text, client, options) => {
7066
+ if (deps.now() - started > sendCommitDeadlineMs) {
7067
+ throw new RemoteOpFailure("timeout", `Session ${sessionId} was not live within ${Math.round(sendCommitDeadlineMs / 1e3)}s on ${deps.host}; nothing was sent \u2014 retry (the same localId cannot double-deliver)`);
7068
+ }
7069
+ return agentGuidance.sendUserMessage(sessionId, key, text, client, { ...options, ...args.localId ? { localId: args.localId } : {} });
7070
+ };
7071
+ return deps.deliver(args.sessionId, persisted, args.text, REMOTE_CLIENT_TAG, {
7072
+ resume: args.resume === true,
7073
+ waitMs: resumeWaitMs,
7074
+ pollMs: 1e3,
7075
+ ...args.model !== void 0 ? { model: args.model } : {},
7076
+ ...args.sentFrom !== void 0 ? { sentFrom: args.sentFrom } : {}
7077
+ }, { send });
7078
+ }, (args) => args.sessionId),
7079
+ "sessions.peers": run("sessions.peers", async (args, from) => {
7080
+ const scope = args.cwd ? args.scope ?? "machine" : "machine";
7081
+ const context = {
7082
+ self: () => ({ sessionId: from.sessionId ?? agentGuidance.CLI_PEER_SENDER_ID, cwd: args.cwd ?? "/", machine: from.host }),
7083
+ readPersisted: deps.readPersisted
7084
+ };
7085
+ const listing = await deps.listPeers(context, scope);
7086
+ return { ...listing, machineId: deps.machineId, host: deps.host };
7087
+ }, () => void 0),
7088
+ "sessions.message": run("sessions.message", async (args) => {
7089
+ requirePersisted(args.to);
7090
+ const context = {
7091
+ self: () => ({ ...args.from, cwd: args.from.cwd ?? "/" }),
7092
+ readPersisted: deps.readPersisted,
7093
+ // The target must be HERE; never bounce a remote request onward.
7094
+ remoteMessage: null
7095
+ };
7096
+ return deps.sendPeer(context, { to: args.to, body: args.body, ...args.replyTo ? { replyTo: args.replyTo } : {} });
7097
+ }, (args) => args.to)
7098
+ };
7099
+ }
7100
+ class RemoteOpFailure extends Error {
7101
+ constructor(code, message) {
7102
+ super(message);
7103
+ this.code = code;
7104
+ }
7105
+ }
7106
+ function summaryFromPersisted(id, persisted) {
7107
+ const meta = persisted?.metadata;
7108
+ return {
7109
+ id,
7110
+ live: false,
7111
+ ...meta?.summary?.text ? { title: meta.summary.text } : {},
7112
+ ...meta?.path ? { cwd: meta.path } : {},
7113
+ ...meta?.flavor ? { flavor: meta.flavor } : {},
7114
+ ...meta?.tags?.length ? { tags: [...meta.tags] } : {},
7115
+ ...meta?.variant ? { variant: meta.variant } : {},
7116
+ ...persisted?.savedAt !== void 0 ? { savedAt: persisted.savedAt } : {},
7117
+ url: agentGuidance.sessionWebUrl(id)
7118
+ };
7119
+ }
7120
+
6912
7121
  const ASSISTANT_CLAUDE_MD = `# very-happy \u8C03\u5EA6\u4E2D\u5FC3\uFF08\u8BED\u97F3\u52A9\u624B\uFF09
6913
7122
 
6914
7123
  \u4F60\u662F very-happy \u7684\u8C03\u5EA6\u4E2D\u5FC3\uFF0C\u8DD1\u5728\u7528\u6237\u81EA\u5DF1\u7684\u673A\u5668\u4E0A\u3002\u7528\u6237\u4E3B\u8981\u901A\u8FC7\u8BED\u97F3\u8DDF\u4F60\u8BF4\u8BDD\uFF0C
@@ -8445,7 +8654,7 @@ function parseJsonObject(text) {
8445
8654
  return null;
8446
8655
  }
8447
8656
  }
8448
- 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-BbtR-Qto.cjs', document.baseURI).href))).resolve(s)) {
8657
+ 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-C9QzZsUQ.cjs', document.baseURI).href))).resolve(s)) {
8449
8658
  const platformArch = `${platform}-${arch}`;
8450
8659
  const candidates = [
8451
8660
  `@anthropic-ai/claude-agent-sdk-${platformArch}/claude`,
@@ -10617,6 +10826,13 @@ ${action.prompt}`, { localId: `automation-${run.id}`, ...meta });
10617
10826
  if (edgeFell) item.sawTurn = false;
10618
10827
  const turn = await readTurn(sessionId, item.runId).catch(() => null);
10619
10828
  if (!turn?.ended) continue;
10829
+ const background = deps.backgroundTasks?.(sessionId) ?? 0;
10830
+ if (background > 0 && turn.status !== "failed" && turn.status !== "cancelled") {
10831
+ if (!item.waitingOnBackground) deps.log(`Automation run ${item.runId}: turn ended but ${background} background task(s) still running; not done yet`);
10832
+ item.waitingOnBackground = true;
10833
+ continue;
10834
+ }
10835
+ item.waitingOnBackground = false;
10620
10836
  if (turn.status === "failed" || turn.status === "cancelled") await finish(item, { claimId: item.claimId, status: "failed", sessionId, error: turn.error ?? `Turn ${turn.status}`, needsAttention: true, attentionReason: `turn_${turn.status}` });
10621
10837
  else await finish(item, { claimId: item.claimId, status: "done", sessionId, summary: clipText(turn.answer, persistence.AUTOMATION_SUMMARY_MAX_CHARS) });
10622
10838
  }
@@ -10911,6 +11127,7 @@ async function startDaemon() {
10911
11127
  persistence.logger.debug("[DAEMON RUN] Auth and machine setup complete");
10912
11128
  const pidToTrackedSession = /* @__PURE__ */ new Map();
10913
11129
  const turnActivity = new index.TurnActivityTracker();
11130
+ const backgroundTasks = new persistence.BackgroundTaskTracker();
10914
11131
  const peerCoordinator = createPeerCoordinator({ getChildren: () => Array.from(pidToTrackedSession.values()) });
10915
11132
  const sessionIdToFinishedSession = /* @__PURE__ */ new Map();
10916
11133
  let teamWorker;
@@ -11771,6 +11988,7 @@ async function startDaemon() {
11771
11988
  if (session?.happySessionId && (session.spawnedBy === "teams" || teamWorker?.hasSession(session.happySessionId))) teamWorker?.report(session.happySessionId, "exited");
11772
11989
  if (session?.happySessionId && automationRunner?.hasSession(session.happySessionId)) automationRunner.report(session.happySessionId, "exited");
11773
11990
  if (session?.happySessionId) turnActivity.forget(session.happySessionId);
11991
+ if (session?.happySessionId) backgroundTasks.forget(session.happySessionId);
11774
11992
  if (session?.happySessionId) peerCoordinator.forget(session.happySessionId);
11775
11993
  if (session?.happySessionId && session.encryption) {
11776
11994
  sessionIdToFinishedSession.set(session.happySessionId, session);
@@ -11857,6 +12075,8 @@ async function startDaemon() {
11857
12075
  onSessionStateEvent,
11858
12076
  onClaudeAuthFailed: (sessionId) => claudeAuthServiceRef?.signalAuthFailed(sessionId),
11859
12077
  onSessionTurnEvent: (sessionId, event) => turnActivity.apply(sessionId, event),
12078
+ onSessionBackgroundTasks: (sessionId, tasks) => backgroundTasks.apply(sessionId, tasks),
12079
+ getBackgroundTasks: (sessionId) => backgroundTasks.report(sessionId),
11860
12080
  onSessionEdit: (edit) => {
11861
12081
  peerCoordinator.onEdit(edit);
11862
12082
  },
@@ -11956,6 +12176,7 @@ async function startDaemon() {
11956
12176
  listTrackedSessionIds: () => [...pidToTrackedSession.values()].map((session) => session.happySessionId).filter((sessionId) => typeof sessionId === "string"),
11957
12177
  requestShutdown: () => requestShutdown("happy-app")
11958
12178
  });
12179
+ apiMachine.setRemoteSessionOpsHandlers(createRemoteSessionOpsHandlers(machineId));
11959
12180
  const claudeAuthService = new ClaudeAuthService({
11960
12181
  happyHomeDir: persistence.configuration.happyHomeDir,
11961
12182
  happyLibDir: terminalTitleSuggest.projectPath(),
@@ -11988,8 +12209,9 @@ async function startDaemon() {
11988
12209
  enabled: async () => ((await persistence.readSettings()).cliAutoUpdate ?? "idle") !== "off",
11989
12210
  // B-466: "idle" = no agent turn in flight. Idle wrappers survive a
11990
12211
  // handover (they talk to the server themselves) and web terminals live
11991
- // in tmux, so neither is a reason to hold an update.
11992
- idle: () => !turnActivity.hasActiveTurn(),
12212
+ // in tmux, so neither is a reason to hold an update. B-507: a session
12213
+ // whose turn ended but still has background tasks is busy too.
12214
+ idle: () => !turnActivity.hasActiveTurn() && !backgroundTasks.hasAny(),
11993
12215
  install: installCliSafely,
11994
12216
  publish: (state) => {
11995
12217
  cliUpdateStateRef = state;
@@ -12044,7 +12266,7 @@ async function startDaemon() {
12044
12266
  } catch {
12045
12267
  }
12046
12268
  }
12047
- if (bundleReplaced && !teamWorker?.busy && !automationRunner?.busy && !updateController.isRunning() && !turnActivity.hasActiveTurn()) {
12269
+ if (bundleReplaced && !teamWorker?.busy && !automationRunner?.busy && !updateController.isRunning() && !turnActivity.hasActiveTurn() && !backgroundTasks.hasAny()) {
12048
12270
  const preflight = await preflightNewBundle(bundlePath);
12049
12271
  if (preflight.action === "hold") {
12050
12272
  if (lastHandoverHold !== preflight.reason) {
@@ -12054,7 +12276,7 @@ async function startDaemon() {
12054
12276
  updateController.holdHandover(preflight.reason);
12055
12277
  return;
12056
12278
  }
12057
- if (teamWorker?.busy || automationRunner?.busy || updateController.isRunning() || turnActivity.hasActiveTurn()) return;
12279
+ if (teamWorker?.busy || automationRunner?.busy || updateController.isRunning() || turnActivity.hasActiveTurn() || backgroundTasks.hasAny()) return;
12058
12280
  lastHandoverHold = null;
12059
12281
  persistence.logger.debug("[DAEMON RUN] Daemon bundle replaced on disk and verified, handing off to new daemon");
12060
12282
  teamWorker?.stop();
@@ -12120,6 +12342,7 @@ async function startDaemon() {
12120
12342
  spawn: spawnSession,
12121
12343
  live: (id) => [...pidToTrackedSession.values()].some((s) => s.happySessionId === id && isPidAlive(s.pid)),
12122
12344
  turnActive: (id) => turnActivity.activeSessions().includes(id),
12345
+ backgroundTasks: (id) => backgroundTasks.count(id),
12123
12346
  log: (message) => persistence.logger.debug(`[DAEMON RUN] ${message}`)
12124
12347
  });
12125
12348
  void apiMachine.updateMachineMetadata((current) => ({
@@ -12413,36 +12636,54 @@ ${sessions.map(describeSummary).join("\n")}`);
12413
12636
  }
12414
12637
  });
12415
12638
  mcp.registerTool("session_read", {
12416
- description: "Read the latest messages of a session as a compact role-tagged transcript (user / assistant / tool summaries; large payloads truncated). Only works for sessions spawned by this machine (their keys live in ~/.happy/sessions.json).",
12639
+ description: "Read the latest messages of a session as a compact role-tagged transcript (user / assistant / tool summaries; large payloads truncated). Sessions spawned by this machine are read directly; a session spawned by another machine of this account is read through that machine's daemon (it must be online).",
12417
12640
  title: "Read Session Transcript",
12418
12641
  inputSchema: {
12419
12642
  sessionId: z.z.string().describe("The Happy session id to read"),
12420
- limit: z.z.number().optional().describe("How many recent messages to fetch (default 20, max 100)")
12643
+ limit: z.z.number().optional().describe("How many recent messages to fetch (default 20, max 100)"),
12644
+ machineId: z.z.string().optional().describe("Machine id the session runs on, when known (skips the lookup across the account's machines)")
12421
12645
  }
12422
12646
  }, async (args) => {
12423
12647
  if (!persistence.isValidSessionId(args.sessionId)) return fail("Invalid sessionId");
12424
12648
  try {
12425
- const result = await agentGuidance.readSessionTranscript(args.sessionId, args.limit ?? 20);
12649
+ const local = persistence.readPersistedSessions()[args.sessionId];
12650
+ if (local && !args.machineId) {
12651
+ const result2 = await agentGuidance.readSessionTranscript(args.sessionId, args.limit ?? 20);
12652
+ const body2 = result2.transcript.length > 0 ? result2.transcript : "(no readable conversation content in this range)";
12653
+ return ok(`${describeSummary(result2.summary)}
12654
+ --- last ${result2.messageCount} message(s) ---
12655
+ ${body2}`);
12656
+ }
12657
+ const result = await agentGuidance.readRemoteTranscript(args.sessionId, { limit: args.limit ?? 20, ...args.machineId ? { machineId: args.machineId } : {} });
12426
12658
  const body = result.transcript.length > 0 ? result.transcript : "(no readable conversation content in this range)";
12427
- return ok(`${describeSummary(result.summary)}
12428
- --- last ${result.messageCount} message(s) ---
12659
+ return ok(`${describeSummary(result.summary)} machine=${result.host} (${result.machineId})
12660
+ --- last ${result.messageCount} message(s)${result.truncated ? ", truncated to fit" : ""} ---
12429
12661
  ${body}`);
12430
12662
  } catch (error) {
12431
12663
  return fail(`Failed to read session: ${error instanceof Error ? error.message : String(error)}`);
12432
12664
  }
12433
12665
  });
12434
12666
  mcp.registerTool("session_send", {
12435
- description: "Send a user message into an existing session on this machine. Only delivers when a live wrapper will read it: an archived / offline session is refused (the server would store the message unread) unless resume:true brings it back on this machine first. Returns immediately after delivery \u2014 it does NOT wait for the session to respond; use session_read later to check progress.",
12667
+ description: "Send a user message into an existing session. Only delivers when a live wrapper will read it: an archived / offline session is refused (the server would store the message unread) unless resume:true brings it back on its machine first. A session spawned by another machine of this account is delivered through that machine's daemon (it must be online). Returns immediately after delivery \u2014 it does NOT wait for the session to respond; use session_read later to check progress.",
12436
12668
  title: "Send Message to Session",
12437
12669
  inputSchema: {
12438
12670
  sessionId: z.z.string().describe("The Happy session id to message"),
12439
12671
  text: z.z.string().describe("The message text to send"),
12440
- resume: z.z.boolean().optional().describe("If the session is archived or offline, resume it on this machine (like the web Restore button) and wait until it is live before sending")
12672
+ resume: z.z.boolean().optional().describe("If the session is archived or offline, resume it on its machine (like the web Restore button) and wait until it is live before sending"),
12673
+ machineId: z.z.string().optional().describe("Machine id the session runs on, when known (skips the lookup across the account's machines)")
12441
12674
  }
12442
12675
  }, async (args) => {
12443
12676
  if (!persistence.isValidSessionId(args.sessionId)) return fail("Invalid sessionId");
12444
12677
  if (typeof args.text !== "string" || args.text.trim().length === 0) return fail("text must be non-empty");
12445
12678
  try {
12679
+ if (!persistence.readPersistedSessions()[args.sessionId] || args.machineId) {
12680
+ const remote = await agentGuidance.sendRemoteMessage(args.sessionId, args.text, { resume: args.resume === true, sentFrom: "assistant", ...args.machineId ? { machineId: args.machineId } : {} });
12681
+ if (!remote.delivered) {
12682
+ const detail = remote.error ?? `session is ${remote.status}`;
12683
+ return fail(remote.stored ? `Not delivered (via ${remote.machine.host}): ${detail}` : `Session ${args.sessionId} on ${remote.machine.host} is ${remote.status}: ${detail}`);
12684
+ }
12685
+ return ok(`Message delivered${remote.resumed ? ` (session resumed on ${remote.machine.host})` : ""} to ${args.sessionId} on machine ${remote.machine.host} (${remote.machine.id}) ${agentGuidance.sessionWebUrl(args.sessionId)}`);
12686
+ }
12446
12687
  const persisted = await agentGuidance.waitForSessionKey(args.sessionId, 0);
12447
12688
  const result = await agentGuidance.deliverToSession(args.sessionId, persisted, args.text, MCP_CLIENT_TAG, {
12448
12689
  resume: args.resume === true,
@@ -12454,6 +12695,7 @@ ${body}`);
12454
12695
  }
12455
12696
  return ok(`Message delivered${result.resumed ? " (session resumed on this machine)" : ""} to ${describeSession(args.sessionId, persisted, { live: true })}`);
12456
12697
  } catch (error) {
12698
+ if (error instanceof agentGuidance.RemoteSessionOpsError) return fail(`Failed to send (${error.code}): ${error.message}`);
12457
12699
  return fail(`Failed to send: ${error instanceof Error ? error.message : String(error)}`);
12458
12700
  }
12459
12701
  });
@@ -13261,7 +13503,7 @@ function registerSideQuestionHandler(rpc, deps) {
13261
13503
  const retainMs = deps.retainMs ?? SIDE_QUESTION_RETAIN_MS;
13262
13504
  const maxRunMs = deps.maxRunMs ?? SIDE_QUESTION_MAX_RUN_MS;
13263
13505
  const fork = deps.run ?? (async (input) => {
13264
- const { query } = await Promise.resolve().then(function () { return require('./index-CB8QnjvS.cjs'); });
13506
+ const { query } = await Promise.resolve().then(function () { return require('./index-Cz-uqnJk.cjs'); });
13265
13507
  return runSideQuestion(query, input);
13266
13508
  });
13267
13509
  const run = async (input, live) => {
@@ -13380,7 +13622,7 @@ const MAX_TITLE_CHARS = 60;
13380
13622
  const GENERATION_TIMEOUT_MS = 3e4;
13381
13623
  function resolveClaudeBinary() {
13382
13624
  try {
13383
- 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-BbtR-Qto.cjs', document.baseURI).href)));
13625
+ 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-C9QzZsUQ.cjs', document.baseURI).href)));
13384
13626
  const utilsPath = path.resolve(path.join(terminalTitleSuggest.projectPath(), "scripts", "claude_version_utils.cjs"));
13385
13627
  const { getClaudeCliPath } = require$1(utilsPath);
13386
13628
  const path$1 = getClaudeCliPath();
@@ -15624,9 +15866,9 @@ function resolveLocalSignupBootstrap(configuredMode, configuredInviteCodes, gene
15624
15866
  };
15625
15867
  }
15626
15868
 
15627
- 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-BbtR-Qto.cjs', document.baseURI).href)));
15869
+ 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-C9QzZsUQ.cjs', document.baseURI).href)));
15628
15870
  const __dirname$1 = path.dirname(__filename$1);
15629
- const require_ = node_module.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index-BbtR-Qto.cjs', document.baseURI).href)));
15871
+ const require_ = node_module.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index-C9QzZsUQ.cjs', document.baseURI).href)));
15630
15872
  const PRISMA_QUERY_ENGINE_FILES = {
15631
15873
  "arm64-darwin": "libquery_engine-darwin-arm64.dylib.node",
15632
15874
  "x64-darwin": "libquery_engine-darwin.dylib.node",
@@ -18569,7 +18811,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
18569
18811
  return;
18570
18812
  } else if (subcommand === "install-terminal-hooks") {
18571
18813
  try {
18572
- const { installTerminalHooks, parseTerminalHooksArgs, TERMINAL_HOOKS_HELP } = await Promise.resolve().then(function () { return require('./installTerminalHooks-BOAnQ1Qe.cjs'); });
18814
+ const { installTerminalHooks, parseTerminalHooksArgs, TERMINAL_HOOKS_HELP } = await Promise.resolve().then(function () { return require('./installTerminalHooks-BVVOEGhG.cjs'); });
18573
18815
  const command = parseTerminalHooksArgs(args.slice(1));
18574
18816
  if (command.action === "help") {
18575
18817
  console.log(TERMINAL_HOOKS_HELP);
@@ -18586,7 +18828,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
18586
18828
  }
18587
18829
  } else if (subcommand === "agent-home") {
18588
18830
  try {
18589
- const { parseAgentHomeArgs, runAgentHomeCommand } = await Promise.resolve().then(function () { return require('./agentHome-CmIJNV7f.cjs'); });
18831
+ const { parseAgentHomeArgs, runAgentHomeCommand } = await Promise.resolve().then(function () { return require('./agentHome-B0CLy0Qx.cjs'); });
18590
18832
  await runAgentHomeCommand(parseAgentHomeArgs(args.slice(1)));
18591
18833
  process.exit(0);
18592
18834
  } catch (error) {
@@ -18595,7 +18837,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
18595
18837
  }
18596
18838
  } else if (subcommand === "spawn") {
18597
18839
  try {
18598
- const { handleSpawnCommand } = await Promise.resolve().then(function () { return require('./spawn-CC6V2KiA.cjs'); });
18840
+ const { handleSpawnCommand } = await Promise.resolve().then(function () { return require('./spawn-HV345RN-.cjs'); });
18599
18841
  await handleSpawnCommand(args.slice(1));
18600
18842
  } catch (error) {
18601
18843
  console.error(chalk.red("Error:"), error instanceof Error ? error.message : "Unknown error");
@@ -18607,7 +18849,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
18607
18849
  return;
18608
18850
  } else if (subcommand === "sessions") {
18609
18851
  try {
18610
- const { handleSessionsCommand } = await Promise.resolve().then(function () { return require('./sessions-OmvyJb0n.cjs'); });
18852
+ const { handleSessionsCommand } = await Promise.resolve().then(function () { return require('./sessions-BFlIrKCY.cjs'); });
18611
18853
  await handleSessionsCommand(args.slice(1));
18612
18854
  } catch (error) {
18613
18855
  console.error(chalk.red("Error:"), error instanceof Error ? error.message : "Unknown error");
@@ -18619,7 +18861,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
18619
18861
  return;
18620
18862
  } else if (subcommand === "send") {
18621
18863
  try {
18622
- const { handleSendCommand } = await Promise.resolve().then(function () { return require('./send-CTcGMVuG.cjs'); });
18864
+ const { handleSendCommand } = await Promise.resolve().then(function () { return require('./send-CHxobaoI.cjs'); });
18623
18865
  await handleSendCommand(args.slice(1));
18624
18866
  } catch (error) {
18625
18867
  console.error(chalk.red("Error:"), error instanceof Error ? error.message : "Unknown error");
@@ -18725,9 +18967,9 @@ Conversation history is preserved on the server, but in-flight tool calls are in
18725
18967
  if (geminiSubcommand === "project" && args[2] === "set" && args[3]) {
18726
18968
  const projectId = args[3];
18727
18969
  try {
18728
- const { saveGoogleCloudProjectToConfig } = await Promise.resolve().then(function () { return require('./config-BYHSRY2E.cjs'); });
18729
- const { readCredentialsForConfiguredRelay: readCredentialsForConfiguredRelay2 } = await Promise.resolve().then(function () { return require('./limits-o29KXBgj.cjs'); }).then(function (n) { return n.persistence; });
18730
- const { ApiClient: ApiClient2 } = await Promise.resolve().then(function () { return require('./types-CphWjqHc.cjs'); }).then(function (n) { return n.api; });
18970
+ const { saveGoogleCloudProjectToConfig } = await Promise.resolve().then(function () { return require('./config-CzkBjZnV.cjs'); });
18971
+ const { readCredentialsForConfiguredRelay: readCredentialsForConfiguredRelay2 } = await Promise.resolve().then(function () { return require('./limits-CyuIt-Vl.cjs'); }).then(function (n) { return n.persistence; });
18972
+ const { ApiClient: ApiClient2 } = await Promise.resolve().then(function () { return require('./types-B0sSi6eM.cjs'); }).then(function (n) { return n.api; });
18731
18973
  let userEmail = void 0;
18732
18974
  try {
18733
18975
  const credentials = await readCredentialsForConfiguredRelay2();
@@ -18758,7 +19000,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
18758
19000
  }
18759
19001
  if (geminiSubcommand === "project" && args[2] === "get") {
18760
19002
  try {
18761
- const { readGeminiLocalConfig } = await Promise.resolve().then(function () { return require('./config-BYHSRY2E.cjs'); });
19003
+ const { readGeminiLocalConfig } = await Promise.resolve().then(function () { return require('./config-CzkBjZnV.cjs'); });
18762
19004
  const config = readGeminiLocalConfig();
18763
19005
  if (config.googleCloudProject) {
18764
19006
  console.log(`Current Google Cloud Project: ${config.googleCloudProject}`);
@@ -18798,7 +19040,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
18798
19040
  process.exit(0);
18799
19041
  }
18800
19042
  try {
18801
- const { runGemini } = await Promise.resolve().then(function () { return require('./runGemini--QqK-Ap5.cjs'); });
19043
+ const { runGemini } = await Promise.resolve().then(function () { return require('./runGemini-DS-0qm0L.cjs'); });
18802
19044
  let startedBy = void 0;
18803
19045
  for (let i = 1; i < args.length; i++) {
18804
19046
  if (args[i] === "--started-by") {
@@ -18821,7 +19063,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
18821
19063
  } else if (subcommand === "pi") {
18822
19064
  if (args[1] === "--terminal") {
18823
19065
  try {
18824
- const { runPiTerminal } = await Promise.resolve().then(function () { return require('./piTerminal-D-BIbov9.cjs'); });
19066
+ const { runPiTerminal } = await Promise.resolve().then(function () { return require('./piTerminal-CpU3hzrX.cjs'); });
18825
19067
  process.exitCode = await runPiTerminal(args.slice(2));
18826
19068
  } catch (error) {
18827
19069
  console.error(chalk.red("Error:"), error instanceof Error ? error.message : "Unknown error");
@@ -18838,7 +19080,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
18838
19080
  }
18839
19081
  };
18840
19082
  try {
18841
- const { runAcp, resolveAcpAgentConfig } = await Promise.resolve().then(function () { return require('./index-B_-7NpGZ.cjs'); });
19083
+ const { runAcp, resolveAcpAgentConfig } = await Promise.resolve().then(function () { return require('./index-CTbGqVFY.cjs'); });
18842
19084
  const parsed = parsePiRunnerArgs(args.slice(1));
18843
19085
  const resolved = resolveAcpAgentConfig(["pi", ...parsed.passthrough]);
18844
19086
  const { credentials } = await authAndSetupMachineIfNeeded();
@@ -18866,7 +19108,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
18866
19108
  return;
18867
19109
  } else if (subcommand === "acp") {
18868
19110
  try {
18869
- const { runAcp, resolveAcpAgentConfig } = await Promise.resolve().then(function () { return require('./index-B_-7NpGZ.cjs'); });
19111
+ const { runAcp, resolveAcpAgentConfig } = await Promise.resolve().then(function () { return require('./index-CTbGqVFY.cjs'); });
18870
19112
  let startedBy = void 0;
18871
19113
  let verbose = false;
18872
19114
  const acpArgs = [];
@@ -18906,7 +19148,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
18906
19148
  return;
18907
19149
  } else if (subcommand === "openclaw") {
18908
19150
  try {
18909
- const { runOpenClaw } = await Promise.resolve().then(function () { return require('./runOpenClaw-C0xLhTvk.cjs'); });
19151
+ const { runOpenClaw } = await Promise.resolve().then(function () { return require('./runOpenClaw-CvSm8oTc.cjs'); });
18910
19152
  let startedBy = void 0;
18911
19153
  let verbose = false;
18912
19154
  let gatewayUrl;
@@ -18957,7 +19199,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
18957
19199
  return;
18958
19200
  } else if (subcommand === "todo") {
18959
19201
  try {
18960
- const { handleTodoCommand } = await Promise.resolve().then(function () { return require('./todo-CEDvKNXK.cjs'); });
19202
+ const { handleTodoCommand } = await Promise.resolve().then(function () { return require('./todo-CMMQ6yhU.cjs'); });
18961
19203
  await handleTodoCommand(args.slice(1));
18962
19204
  } catch (error) {
18963
19205
  console.error(JSON.stringify({ error: error instanceof Error ? error.message : "Todo command failed" }));
@@ -18966,7 +19208,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
18966
19208
  return;
18967
19209
  } else if (subcommand === "teams") {
18968
19210
  try {
18969
- const { handleTeamsCommand } = await Promise.resolve().then(function () { return require('./teams-XtrH3_h3.cjs'); });
19211
+ const { handleTeamsCommand } = await Promise.resolve().then(function () { return require('./teams-BahinMnH.cjs'); });
18970
19212
  await handleTeamsCommand(args.slice(1));
18971
19213
  } catch (error) {
18972
19214
  console.error(error instanceof Error ? error.message : "Teams command failed");
@@ -18975,7 +19217,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
18975
19217
  return;
18976
19218
  } else if (subcommand === "auto") {
18977
19219
  try {
18978
- const { handleAutoCommand } = await Promise.resolve().then(function () { return require('./auto-CMDq4oIu.cjs'); });
19220
+ const { handleAutoCommand } = await Promise.resolve().then(function () { return require('./auto-DqKGFq8U.cjs'); });
18979
19221
  await handleAutoCommand(args.slice(1));
18980
19222
  } catch (error) {
18981
19223
  console.error(chalk.red("Error:"), error instanceof Error ? error.message : "Automation command failed");
@@ -18987,7 +19229,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
18987
19229
  return;
18988
19230
  } else if (subcommand === "mcp" && (args.length === 1 || args.length === 2 && args[1] === "--terminal-tools")) {
18989
19231
  try {
18990
- const { handleMcpCommand } = await Promise.resolve().then(function () { return require('./mcp-CwK1nI7Y.cjs'); });
19232
+ const { handleMcpCommand } = await Promise.resolve().then(function () { return require('./mcp-CXkvnztT.cjs'); });
18991
19233
  await handleMcpCommand(args[1] === "--terminal-tools");
18992
19234
  } catch (error) {
18993
19235
  process.stderr.write(`[very-happy mcp] Fatal: ${error instanceof Error ? error.message : String(error)}
@@ -19018,6 +19260,8 @@ Conversation history is preserved on the server, but in-flight tool calls are in
19018
19260
  console.log(JSON.stringify(sessions, null, 2));
19019
19261
  const busy = sessions.filter((s) => s.turnActive === true);
19020
19262
  console.log(busy.length === 0 ? "No turn in flight on this machine (wrappers older than 0.2.139 do not report turns)." : `${busy.length} session(s) with a turn in flight: ${busy.map((s) => s.happySessionId).join(", ")}`);
19263
+ const background = sessions.filter((s) => (s.backgroundTasks?.count ?? 0) > 0);
19264
+ console.log(background.length === 0 ? "No background tasks in flight (wrappers older than 0.2.157 do not report them)." : `${background.length} session(s) with background tasks in flight: ${background.map((s) => `${s.happySessionId} (${s.backgroundTasks?.count})`).join(", ")}`);
19021
19265
  }
19022
19266
  } catch (error) {
19023
19267
  console.log("No daemon running");