very-happy-cli 0.2.156 → 0.2.158

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-DIDRig5G.cjs} +2 -2
  2. package/dist/{AcpBackend-C3nc1u-s.mjs → AcpBackend-vDVLHuYJ.mjs} +2 -2
  3. package/dist/{AcpSessionManager-BVxkQnNf.cjs → AcpSessionManager-C44U99CC.cjs} +1 -1
  4. package/dist/{AcpSessionManager-dN3k1LbI.mjs → AcpSessionManager-CmRjfhn3.mjs} +1 -1
  5. package/dist/{agentGuidance-C604n0Zq.mjs → agentGuidance-CrR9l62U.mjs} +562 -30
  6. package/dist/{agentGuidance-C-CmV03f.cjs → agentGuidance-DwOWbX55.cjs} +581 -29
  7. package/dist/{agentHome-D2XGsoqs.mjs → agentHome-CyLmGH5L.mjs} +2 -2
  8. package/dist/{agentHome-CmIJNV7f.cjs → agentHome-Dw8Jx_CJ.cjs} +2 -2
  9. package/dist/{auto-B1I6G_Nf.mjs → auto-BlMZPwOk.mjs} +19 -10
  10. package/dist/{auto-CMDq4oIu.cjs → auto-DZbNcTXx.cjs} +19 -10
  11. package/dist/codex/happyMcpStdioBridge.cjs +2 -2
  12. package/dist/codex/happyMcpStdioBridge.mjs +2 -2
  13. package/dist/{config-BkTu25bH.mjs → config-BtPArqRH.mjs} +4 -4
  14. package/dist/{config-BYHSRY2E.cjs → config-DG84bjwF.cjs} +4 -4
  15. package/dist/{index-BbtR-Qto.cjs → index-BG932eCh.cjs} +292 -47
  16. package/dist/{index-DAAreiRF.mjs → index-CVCt3kSt.mjs} +289 -44
  17. package/dist/{index-CB8QnjvS.cjs → index-D5ScEErM.cjs} +4 -4
  18. package/dist/{index-B_-7NpGZ.cjs → index-DPCsWlWK.cjs} +7 -7
  19. package/dist/{index-PYO8Mdz4.mjs → index-DgO0FHOx.mjs} +4 -4
  20. package/dist/{index-B5QbzEga.mjs → index-ZChGsuB7.mjs} +8 -8
  21. package/dist/index.cjs +4 -4
  22. package/dist/index.mjs +4 -4
  23. package/dist/{install-CNtXzwT_.mjs → install-DarS_Wco.mjs} +1 -1
  24. package/dist/{install-CO1ps6Wt.cjs → install-wKQGgXvN.cjs} +1 -1
  25. package/dist/{installTerminalHooks-CMpOV3RU.mjs → installTerminalHooks-CpNbRFPz.mjs} +4 -4
  26. package/dist/{installTerminalHooks-BOAnQ1Qe.cjs → installTerminalHooks-DcQfee_O.cjs} +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-D2uN090G.mjs} +163 -11
  32. package/dist/{limits-o29KXBgj.cjs → limits-kqFqhfsh.cjs} +170 -10
  33. package/dist/{mcp-C_uejotl.mjs → mcp-BN6bKIGb.mjs} +4 -4
  34. package/dist/{mcp-CwK1nI7Y.cjs → mcp-DGdeUUDJ.cjs} +4 -4
  35. package/dist/{piRuntime-Dj5WnqzJ.cjs → piRuntime-3qtbKujX.cjs} +2 -2
  36. package/dist/{piRuntime-Cu2-8nOT.mjs → piRuntime-bkw2NAZU.mjs} +2 -2
  37. package/dist/{piTerminal-D-BIbov9.cjs → piTerminal-BYxp3LMr.cjs} +6 -6
  38. package/dist/{piTerminal-DanZeBrO.mjs → piTerminal-DilKwM7B.mjs} +6 -6
  39. package/dist/{runGemini--QqK-Ap5.cjs → runGemini-28O2sqyI.cjs} +6 -6
  40. package/dist/{runGemini-CZ_lhMWY.mjs → runGemini-Cjii069p.mjs} +6 -6
  41. package/dist/{runOpenClaw-C0xLhTvk.cjs → runOpenClaw-CiMZad-H.cjs} +5 -5
  42. package/dist/{runOpenClaw-CxgLpm38.mjs → runOpenClaw-jaLr7KF1.mjs} +5 -5
  43. package/dist/{send-BaOkDgH0.mjs → send-C9mOtChi.mjs} +43 -31
  44. package/dist/{send-CTcGMVuG.cjs → send-D5ejHPXG.cjs} +43 -31
  45. package/dist/{sessions-OmvyJb0n.cjs → sessions-BNMPQoLE.cjs} +133 -49
  46. package/dist/{sessions-Bn304xF1.mjs → sessions-W6771g3X.mjs} +133 -49
  47. package/dist/{spawn-BKNabutV.mjs → spawn-D0QVhzRb.mjs} +4 -4
  48. package/dist/{spawn-CC6V2KiA.cjs → spawn-Ddtom1cb.cjs} +4 -4
  49. package/dist/{teams-XtrH3_h3.cjs → teams-BZ1tayg_.cjs} +5 -5
  50. package/dist/{teams-CLbS2_4Q.mjs → teams-CqSwtw2O.mjs} +5 -5
  51. package/dist/{todo-CEDvKNXK.cjs → todo-BYMg0fR0.cjs} +2 -2
  52. package/dist/{todo-BcPbNKt2.mjs → todo-BbusB1zM.mjs} +2 -2
  53. package/dist/{types-BEVzYSoV.mjs → types-DIBF4U0Y.mjs} +78 -5
  54. package/dist/{types-CphWjqHc.cjs → types-DnrPeN80.cjs} +78 -5
  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-DnrPeN80.cjs');
7
+ var persistence = require('./limits-kqFqhfsh.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-DwOWbX55.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-Dw8Jx_CJ.cjs'); });
5428
+ const { describeAgentHome } = await Promise.resolve().then(function () { return require('./types-DnrPeN80.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-BG932eCh.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
  }
@@ -10701,6 +10917,7 @@ ${action.prompt}`, { localId: `automation-${run.id}`, ...meta });
10701
10917
  for (const item of tracked.values()) {
10702
10918
  if (item.sessionId !== sessionId) continue;
10703
10919
  if (event === "exited") item.exited = true;
10920
+ if (event === "idle") item.attentionReported = false;
10704
10921
  if (event === "blocked" && !item.attentionReported) {
10705
10922
  item.attentionReported = true;
10706
10923
  void client.report(item.runId, { claimId: item.claimId, needsAttention: true, attentionReason: "needs_input" }).catch(() => deps.log(`Automation run ${item.runId} attention report failed`));
@@ -10911,6 +11128,7 @@ async function startDaemon() {
10911
11128
  persistence.logger.debug("[DAEMON RUN] Auth and machine setup complete");
10912
11129
  const pidToTrackedSession = /* @__PURE__ */ new Map();
10913
11130
  const turnActivity = new index.TurnActivityTracker();
11131
+ const backgroundTasks = new persistence.BackgroundTaskTracker();
10914
11132
  const peerCoordinator = createPeerCoordinator({ getChildren: () => Array.from(pidToTrackedSession.values()) });
10915
11133
  const sessionIdToFinishedSession = /* @__PURE__ */ new Map();
10916
11134
  let teamWorker;
@@ -11771,6 +11989,7 @@ async function startDaemon() {
11771
11989
  if (session?.happySessionId && (session.spawnedBy === "teams" || teamWorker?.hasSession(session.happySessionId))) teamWorker?.report(session.happySessionId, "exited");
11772
11990
  if (session?.happySessionId && automationRunner?.hasSession(session.happySessionId)) automationRunner.report(session.happySessionId, "exited");
11773
11991
  if (session?.happySessionId) turnActivity.forget(session.happySessionId);
11992
+ if (session?.happySessionId) backgroundTasks.forget(session.happySessionId);
11774
11993
  if (session?.happySessionId) peerCoordinator.forget(session.happySessionId);
11775
11994
  if (session?.happySessionId && session.encryption) {
11776
11995
  sessionIdToFinishedSession.set(session.happySessionId, session);
@@ -11857,6 +12076,8 @@ async function startDaemon() {
11857
12076
  onSessionStateEvent,
11858
12077
  onClaudeAuthFailed: (sessionId) => claudeAuthServiceRef?.signalAuthFailed(sessionId),
11859
12078
  onSessionTurnEvent: (sessionId, event) => turnActivity.apply(sessionId, event),
12079
+ onSessionBackgroundTasks: (sessionId, tasks) => backgroundTasks.apply(sessionId, tasks),
12080
+ getBackgroundTasks: (sessionId) => backgroundTasks.report(sessionId),
11860
12081
  onSessionEdit: (edit) => {
11861
12082
  peerCoordinator.onEdit(edit);
11862
12083
  },
@@ -11956,6 +12177,7 @@ async function startDaemon() {
11956
12177
  listTrackedSessionIds: () => [...pidToTrackedSession.values()].map((session) => session.happySessionId).filter((sessionId) => typeof sessionId === "string"),
11957
12178
  requestShutdown: () => requestShutdown("happy-app")
11958
12179
  });
12180
+ apiMachine.setRemoteSessionOpsHandlers(createRemoteSessionOpsHandlers(machineId));
11959
12181
  const claudeAuthService = new ClaudeAuthService({
11960
12182
  happyHomeDir: persistence.configuration.happyHomeDir,
11961
12183
  happyLibDir: terminalTitleSuggest.projectPath(),
@@ -11988,8 +12210,9 @@ async function startDaemon() {
11988
12210
  enabled: async () => ((await persistence.readSettings()).cliAutoUpdate ?? "idle") !== "off",
11989
12211
  // B-466: "idle" = no agent turn in flight. Idle wrappers survive a
11990
12212
  // 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(),
12213
+ // in tmux, so neither is a reason to hold an update. B-507: a session
12214
+ // whose turn ended but still has background tasks is busy too.
12215
+ idle: () => !turnActivity.hasActiveTurn() && !backgroundTasks.hasAny(),
11993
12216
  install: installCliSafely,
11994
12217
  publish: (state) => {
11995
12218
  cliUpdateStateRef = state;
@@ -12044,7 +12267,7 @@ async function startDaemon() {
12044
12267
  } catch {
12045
12268
  }
12046
12269
  }
12047
- if (bundleReplaced && !teamWorker?.busy && !automationRunner?.busy && !updateController.isRunning() && !turnActivity.hasActiveTurn()) {
12270
+ if (bundleReplaced && !teamWorker?.busy && !automationRunner?.busy && !updateController.isRunning() && !turnActivity.hasActiveTurn() && !backgroundTasks.hasAny()) {
12048
12271
  const preflight = await preflightNewBundle(bundlePath);
12049
12272
  if (preflight.action === "hold") {
12050
12273
  if (lastHandoverHold !== preflight.reason) {
@@ -12054,7 +12277,7 @@ async function startDaemon() {
12054
12277
  updateController.holdHandover(preflight.reason);
12055
12278
  return;
12056
12279
  }
12057
- if (teamWorker?.busy || automationRunner?.busy || updateController.isRunning() || turnActivity.hasActiveTurn()) return;
12280
+ if (teamWorker?.busy || automationRunner?.busy || updateController.isRunning() || turnActivity.hasActiveTurn() || backgroundTasks.hasAny()) return;
12058
12281
  lastHandoverHold = null;
12059
12282
  persistence.logger.debug("[DAEMON RUN] Daemon bundle replaced on disk and verified, handing off to new daemon");
12060
12283
  teamWorker?.stop();
@@ -12120,6 +12343,7 @@ async function startDaemon() {
12120
12343
  spawn: spawnSession,
12121
12344
  live: (id) => [...pidToTrackedSession.values()].some((s) => s.happySessionId === id && isPidAlive(s.pid)),
12122
12345
  turnActive: (id) => turnActivity.activeSessions().includes(id),
12346
+ backgroundTasks: (id) => backgroundTasks.count(id),
12123
12347
  log: (message) => persistence.logger.debug(`[DAEMON RUN] ${message}`)
12124
12348
  });
12125
12349
  void apiMachine.updateMachineMetadata((current) => ({
@@ -12413,36 +12637,54 @@ ${sessions.map(describeSummary).join("\n")}`);
12413
12637
  }
12414
12638
  });
12415
12639
  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).",
12640
+ 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
12641
  title: "Read Session Transcript",
12418
12642
  inputSchema: {
12419
12643
  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)")
12644
+ limit: z.z.number().optional().describe("How many recent messages to fetch (default 20, max 100)"),
12645
+ machineId: z.z.string().optional().describe("Machine id the session runs on, when known (skips the lookup across the account's machines)")
12421
12646
  }
12422
12647
  }, async (args) => {
12423
12648
  if (!persistence.isValidSessionId(args.sessionId)) return fail("Invalid sessionId");
12424
12649
  try {
12425
- const result = await agentGuidance.readSessionTranscript(args.sessionId, args.limit ?? 20);
12650
+ const local = persistence.readPersistedSessions()[args.sessionId];
12651
+ if (local && !args.machineId) {
12652
+ const result2 = await agentGuidance.readSessionTranscript(args.sessionId, args.limit ?? 20);
12653
+ const body2 = result2.transcript.length > 0 ? result2.transcript : "(no readable conversation content in this range)";
12654
+ return ok(`${describeSummary(result2.summary)}
12655
+ --- last ${result2.messageCount} message(s) ---
12656
+ ${body2}`);
12657
+ }
12658
+ const result = await agentGuidance.readRemoteTranscript(args.sessionId, { limit: args.limit ?? 20, ...args.machineId ? { machineId: args.machineId } : {} });
12426
12659
  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) ---
12660
+ return ok(`${describeSummary(result.summary)} machine=${result.host} (${result.machineId})
12661
+ --- last ${result.messageCount} message(s)${result.truncated ? ", truncated to fit" : ""} ---
12429
12662
  ${body}`);
12430
12663
  } catch (error) {
12431
12664
  return fail(`Failed to read session: ${error instanceof Error ? error.message : String(error)}`);
12432
12665
  }
12433
12666
  });
12434
12667
  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.",
12668
+ 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
12669
  title: "Send Message to Session",
12437
12670
  inputSchema: {
12438
12671
  sessionId: z.z.string().describe("The Happy session id to message"),
12439
12672
  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")
12673
+ 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"),
12674
+ machineId: z.z.string().optional().describe("Machine id the session runs on, when known (skips the lookup across the account's machines)")
12441
12675
  }
12442
12676
  }, async (args) => {
12443
12677
  if (!persistence.isValidSessionId(args.sessionId)) return fail("Invalid sessionId");
12444
12678
  if (typeof args.text !== "string" || args.text.trim().length === 0) return fail("text must be non-empty");
12445
12679
  try {
12680
+ if (!persistence.readPersistedSessions()[args.sessionId] || args.machineId) {
12681
+ const remote = await agentGuidance.sendRemoteMessage(args.sessionId, args.text, { resume: args.resume === true, sentFrom: "assistant", ...args.machineId ? { machineId: args.machineId } : {} });
12682
+ if (!remote.delivered) {
12683
+ const detail = remote.error ?? `session is ${remote.status}`;
12684
+ return fail(remote.stored ? `Not delivered (via ${remote.machine.host}): ${detail}` : `Session ${args.sessionId} on ${remote.machine.host} is ${remote.status}: ${detail}`);
12685
+ }
12686
+ 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)}`);
12687
+ }
12446
12688
  const persisted = await agentGuidance.waitForSessionKey(args.sessionId, 0);
12447
12689
  const result = await agentGuidance.deliverToSession(args.sessionId, persisted, args.text, MCP_CLIENT_TAG, {
12448
12690
  resume: args.resume === true,
@@ -12454,6 +12696,7 @@ ${body}`);
12454
12696
  }
12455
12697
  return ok(`Message delivered${result.resumed ? " (session resumed on this machine)" : ""} to ${describeSession(args.sessionId, persisted, { live: true })}`);
12456
12698
  } catch (error) {
12699
+ if (error instanceof agentGuidance.RemoteSessionOpsError) return fail(`Failed to send (${error.code}): ${error.message}`);
12457
12700
  return fail(`Failed to send: ${error instanceof Error ? error.message : String(error)}`);
12458
12701
  }
12459
12702
  });
@@ -13261,7 +13504,7 @@ function registerSideQuestionHandler(rpc, deps) {
13261
13504
  const retainMs = deps.retainMs ?? SIDE_QUESTION_RETAIN_MS;
13262
13505
  const maxRunMs = deps.maxRunMs ?? SIDE_QUESTION_MAX_RUN_MS;
13263
13506
  const fork = deps.run ?? (async (input) => {
13264
- const { query } = await Promise.resolve().then(function () { return require('./index-CB8QnjvS.cjs'); });
13507
+ const { query } = await Promise.resolve().then(function () { return require('./index-D5ScEErM.cjs'); });
13265
13508
  return runSideQuestion(query, input);
13266
13509
  });
13267
13510
  const run = async (input, live) => {
@@ -13380,7 +13623,7 @@ const MAX_TITLE_CHARS = 60;
13380
13623
  const GENERATION_TIMEOUT_MS = 3e4;
13381
13624
  function resolveClaudeBinary() {
13382
13625
  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)));
13626
+ 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-BG932eCh.cjs', document.baseURI).href)));
13384
13627
  const utilsPath = path.resolve(path.join(terminalTitleSuggest.projectPath(), "scripts", "claude_version_utils.cjs"));
13385
13628
  const { getClaudeCliPath } = require$1(utilsPath);
13386
13629
  const path$1 = getClaudeCliPath();
@@ -15624,9 +15867,9 @@ function resolveLocalSignupBootstrap(configuredMode, configuredInviteCodes, gene
15624
15867
  };
15625
15868
  }
15626
15869
 
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)));
15870
+ 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-BG932eCh.cjs', document.baseURI).href)));
15628
15871
  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)));
15872
+ const require_ = node_module.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index-BG932eCh.cjs', document.baseURI).href)));
15630
15873
  const PRISMA_QUERY_ENGINE_FILES = {
15631
15874
  "arm64-darwin": "libquery_engine-darwin-arm64.dylib.node",
15632
15875
  "x64-darwin": "libquery_engine-darwin.dylib.node",
@@ -18569,7 +18812,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
18569
18812
  return;
18570
18813
  } else if (subcommand === "install-terminal-hooks") {
18571
18814
  try {
18572
- const { installTerminalHooks, parseTerminalHooksArgs, TERMINAL_HOOKS_HELP } = await Promise.resolve().then(function () { return require('./installTerminalHooks-BOAnQ1Qe.cjs'); });
18815
+ const { installTerminalHooks, parseTerminalHooksArgs, TERMINAL_HOOKS_HELP } = await Promise.resolve().then(function () { return require('./installTerminalHooks-DcQfee_O.cjs'); });
18573
18816
  const command = parseTerminalHooksArgs(args.slice(1));
18574
18817
  if (command.action === "help") {
18575
18818
  console.log(TERMINAL_HOOKS_HELP);
@@ -18586,7 +18829,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
18586
18829
  }
18587
18830
  } else if (subcommand === "agent-home") {
18588
18831
  try {
18589
- const { parseAgentHomeArgs, runAgentHomeCommand } = await Promise.resolve().then(function () { return require('./agentHome-CmIJNV7f.cjs'); });
18832
+ const { parseAgentHomeArgs, runAgentHomeCommand } = await Promise.resolve().then(function () { return require('./agentHome-Dw8Jx_CJ.cjs'); });
18590
18833
  await runAgentHomeCommand(parseAgentHomeArgs(args.slice(1)));
18591
18834
  process.exit(0);
18592
18835
  } catch (error) {
@@ -18595,7 +18838,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
18595
18838
  }
18596
18839
  } else if (subcommand === "spawn") {
18597
18840
  try {
18598
- const { handleSpawnCommand } = await Promise.resolve().then(function () { return require('./spawn-CC6V2KiA.cjs'); });
18841
+ const { handleSpawnCommand } = await Promise.resolve().then(function () { return require('./spawn-Ddtom1cb.cjs'); });
18599
18842
  await handleSpawnCommand(args.slice(1));
18600
18843
  } catch (error) {
18601
18844
  console.error(chalk.red("Error:"), error instanceof Error ? error.message : "Unknown error");
@@ -18607,7 +18850,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
18607
18850
  return;
18608
18851
  } else if (subcommand === "sessions") {
18609
18852
  try {
18610
- const { handleSessionsCommand } = await Promise.resolve().then(function () { return require('./sessions-OmvyJb0n.cjs'); });
18853
+ const { handleSessionsCommand } = await Promise.resolve().then(function () { return require('./sessions-BNMPQoLE.cjs'); });
18611
18854
  await handleSessionsCommand(args.slice(1));
18612
18855
  } catch (error) {
18613
18856
  console.error(chalk.red("Error:"), error instanceof Error ? error.message : "Unknown error");
@@ -18619,7 +18862,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
18619
18862
  return;
18620
18863
  } else if (subcommand === "send") {
18621
18864
  try {
18622
- const { handleSendCommand } = await Promise.resolve().then(function () { return require('./send-CTcGMVuG.cjs'); });
18865
+ const { handleSendCommand } = await Promise.resolve().then(function () { return require('./send-D5ejHPXG.cjs'); });
18623
18866
  await handleSendCommand(args.slice(1));
18624
18867
  } catch (error) {
18625
18868
  console.error(chalk.red("Error:"), error instanceof Error ? error.message : "Unknown error");
@@ -18725,9 +18968,9 @@ Conversation history is preserved on the server, but in-flight tool calls are in
18725
18968
  if (geminiSubcommand === "project" && args[2] === "set" && args[3]) {
18726
18969
  const projectId = args[3];
18727
18970
  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; });
18971
+ const { saveGoogleCloudProjectToConfig } = await Promise.resolve().then(function () { return require('./config-DG84bjwF.cjs'); });
18972
+ const { readCredentialsForConfiguredRelay: readCredentialsForConfiguredRelay2 } = await Promise.resolve().then(function () { return require('./limits-kqFqhfsh.cjs'); }).then(function (n) { return n.persistence; });
18973
+ const { ApiClient: ApiClient2 } = await Promise.resolve().then(function () { return require('./types-DnrPeN80.cjs'); }).then(function (n) { return n.api; });
18731
18974
  let userEmail = void 0;
18732
18975
  try {
18733
18976
  const credentials = await readCredentialsForConfiguredRelay2();
@@ -18758,7 +19001,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
18758
19001
  }
18759
19002
  if (geminiSubcommand === "project" && args[2] === "get") {
18760
19003
  try {
18761
- const { readGeminiLocalConfig } = await Promise.resolve().then(function () { return require('./config-BYHSRY2E.cjs'); });
19004
+ const { readGeminiLocalConfig } = await Promise.resolve().then(function () { return require('./config-DG84bjwF.cjs'); });
18762
19005
  const config = readGeminiLocalConfig();
18763
19006
  if (config.googleCloudProject) {
18764
19007
  console.log(`Current Google Cloud Project: ${config.googleCloudProject}`);
@@ -18798,7 +19041,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
18798
19041
  process.exit(0);
18799
19042
  }
18800
19043
  try {
18801
- const { runGemini } = await Promise.resolve().then(function () { return require('./runGemini--QqK-Ap5.cjs'); });
19044
+ const { runGemini } = await Promise.resolve().then(function () { return require('./runGemini-28O2sqyI.cjs'); });
18802
19045
  let startedBy = void 0;
18803
19046
  for (let i = 1; i < args.length; i++) {
18804
19047
  if (args[i] === "--started-by") {
@@ -18821,7 +19064,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
18821
19064
  } else if (subcommand === "pi") {
18822
19065
  if (args[1] === "--terminal") {
18823
19066
  try {
18824
- const { runPiTerminal } = await Promise.resolve().then(function () { return require('./piTerminal-D-BIbov9.cjs'); });
19067
+ const { runPiTerminal } = await Promise.resolve().then(function () { return require('./piTerminal-BYxp3LMr.cjs'); });
18825
19068
  process.exitCode = await runPiTerminal(args.slice(2));
18826
19069
  } catch (error) {
18827
19070
  console.error(chalk.red("Error:"), error instanceof Error ? error.message : "Unknown error");
@@ -18838,7 +19081,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
18838
19081
  }
18839
19082
  };
18840
19083
  try {
18841
- const { runAcp, resolveAcpAgentConfig } = await Promise.resolve().then(function () { return require('./index-B_-7NpGZ.cjs'); });
19084
+ const { runAcp, resolveAcpAgentConfig } = await Promise.resolve().then(function () { return require('./index-DPCsWlWK.cjs'); });
18842
19085
  const parsed = parsePiRunnerArgs(args.slice(1));
18843
19086
  const resolved = resolveAcpAgentConfig(["pi", ...parsed.passthrough]);
18844
19087
  const { credentials } = await authAndSetupMachineIfNeeded();
@@ -18866,7 +19109,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
18866
19109
  return;
18867
19110
  } else if (subcommand === "acp") {
18868
19111
  try {
18869
- const { runAcp, resolveAcpAgentConfig } = await Promise.resolve().then(function () { return require('./index-B_-7NpGZ.cjs'); });
19112
+ const { runAcp, resolveAcpAgentConfig } = await Promise.resolve().then(function () { return require('./index-DPCsWlWK.cjs'); });
18870
19113
  let startedBy = void 0;
18871
19114
  let verbose = false;
18872
19115
  const acpArgs = [];
@@ -18906,7 +19149,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
18906
19149
  return;
18907
19150
  } else if (subcommand === "openclaw") {
18908
19151
  try {
18909
- const { runOpenClaw } = await Promise.resolve().then(function () { return require('./runOpenClaw-C0xLhTvk.cjs'); });
19152
+ const { runOpenClaw } = await Promise.resolve().then(function () { return require('./runOpenClaw-CiMZad-H.cjs'); });
18910
19153
  let startedBy = void 0;
18911
19154
  let verbose = false;
18912
19155
  let gatewayUrl;
@@ -18957,7 +19200,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
18957
19200
  return;
18958
19201
  } else if (subcommand === "todo") {
18959
19202
  try {
18960
- const { handleTodoCommand } = await Promise.resolve().then(function () { return require('./todo-CEDvKNXK.cjs'); });
19203
+ const { handleTodoCommand } = await Promise.resolve().then(function () { return require('./todo-BYMg0fR0.cjs'); });
18961
19204
  await handleTodoCommand(args.slice(1));
18962
19205
  } catch (error) {
18963
19206
  console.error(JSON.stringify({ error: error instanceof Error ? error.message : "Todo command failed" }));
@@ -18966,7 +19209,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
18966
19209
  return;
18967
19210
  } else if (subcommand === "teams") {
18968
19211
  try {
18969
- const { handleTeamsCommand } = await Promise.resolve().then(function () { return require('./teams-XtrH3_h3.cjs'); });
19212
+ const { handleTeamsCommand } = await Promise.resolve().then(function () { return require('./teams-BZ1tayg_.cjs'); });
18970
19213
  await handleTeamsCommand(args.slice(1));
18971
19214
  } catch (error) {
18972
19215
  console.error(error instanceof Error ? error.message : "Teams command failed");
@@ -18975,7 +19218,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
18975
19218
  return;
18976
19219
  } else if (subcommand === "auto") {
18977
19220
  try {
18978
- const { handleAutoCommand } = await Promise.resolve().then(function () { return require('./auto-CMDq4oIu.cjs'); });
19221
+ const { handleAutoCommand } = await Promise.resolve().then(function () { return require('./auto-DZbNcTXx.cjs'); });
18979
19222
  await handleAutoCommand(args.slice(1));
18980
19223
  } catch (error) {
18981
19224
  console.error(chalk.red("Error:"), error instanceof Error ? error.message : "Automation command failed");
@@ -18987,7 +19230,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
18987
19230
  return;
18988
19231
  } else if (subcommand === "mcp" && (args.length === 1 || args.length === 2 && args[1] === "--terminal-tools")) {
18989
19232
  try {
18990
- const { handleMcpCommand } = await Promise.resolve().then(function () { return require('./mcp-CwK1nI7Y.cjs'); });
19233
+ const { handleMcpCommand } = await Promise.resolve().then(function () { return require('./mcp-DGdeUUDJ.cjs'); });
18991
19234
  await handleMcpCommand(args[1] === "--terminal-tools");
18992
19235
  } catch (error) {
18993
19236
  process.stderr.write(`[very-happy mcp] Fatal: ${error instanceof Error ? error.message : String(error)}
@@ -19018,6 +19261,8 @@ Conversation history is preserved on the server, but in-flight tool calls are in
19018
19261
  console.log(JSON.stringify(sessions, null, 2));
19019
19262
  const busy = sessions.filter((s) => s.turnActive === true);
19020
19263
  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(", ")}`);
19264
+ const background = sessions.filter((s) => (s.backgroundTasks?.count ?? 0) > 0);
19265
+ 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
19266
  }
19022
19267
  } catch (error) {
19023
19268
  console.log("No daemon running");