very-happy-cli 0.2.90 → 0.2.92

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 (31) hide show
  1. package/dist/{AcpBackend-CnYZFdd0.cjs → AcpBackend-BP7id8L6.cjs} +1 -1
  2. package/dist/{AcpBackend-BV4wSnJ3.mjs → AcpBackend-DDEsgc1c.mjs} +1 -1
  3. package/dist/{AcpSessionManager-Cyne6Rmg.mjs → AcpSessionManager-C29t6wb_.mjs} +1 -1
  4. package/dist/{AcpSessionManager-BPBdrrME.cjs → AcpSessionManager-Cys1Hsb8.cjs} +1 -1
  5. package/dist/{config-CgXitj0f.cjs → config-B77vhdwT.cjs} +2 -2
  6. package/dist/{config-BEdyyciP.mjs → config-CJQw0z1o.mjs} +2 -2
  7. package/dist/{index-an09rejO.mjs → index-8LDXVYWi.mjs} +409 -51
  8. package/dist/{index-4YmVbx7j.cjs → index-B63Vjt4W.cjs} +425 -67
  9. package/dist/{index-Dfu5uvjk.mjs → index-BP9pfzdZ.mjs} +5 -5
  10. package/dist/{index-B1wTVXjt.cjs → index-L3o5Gz-2.cjs} +4 -4
  11. package/dist/index.cjs +2 -2
  12. package/dist/index.mjs +2 -2
  13. package/dist/{installTerminalHooks-DDpVxk8-.cjs → installTerminalHooks-BBc2nij4.cjs} +2 -2
  14. package/dist/{installTerminalHooks-C-OgZr5k.mjs → installTerminalHooks-DDRrUG_n.mjs} +2 -2
  15. package/dist/lib.cjs +1 -1
  16. package/dist/lib.d.cts +103 -3
  17. package/dist/lib.d.mts +103 -3
  18. package/dist/lib.mjs +1 -1
  19. package/dist/{mcp-Du-N0qlK.mjs → mcp-CYJAl5pk.mjs} +2 -2
  20. package/dist/{mcp-B6Nq-RUL.cjs → mcp-DbYXyw1U.cjs} +2 -2
  21. package/dist/{runGemini-ChG7cGMC.cjs → runGemini-BDSWSID6.cjs} +4 -4
  22. package/dist/{runGemini-DBr_TiTL.mjs → runGemini-DHYs_Beq.mjs} +4 -4
  23. package/dist/{runOpenClaw-D2jtVgpC.cjs → runOpenClaw-DC9gb1bd.cjs} +3 -3
  24. package/dist/{runOpenClaw-Cbde8t92.mjs → runOpenClaw-DTaXxvNd.mjs} +3 -3
  25. package/dist/{send-Bjen1TUE.cjs → send-BEdGwmA-.cjs} +2 -2
  26. package/dist/{send-BHliX59m.mjs → send-BQSaVz9r.mjs} +2 -2
  27. package/dist/{spawn-CH1Rq-LW.cjs → spawn-CK1ma_qc.cjs} +2 -2
  28. package/dist/{spawn-JxaPHAoP.mjs → spawn-DS-Uz_Hw.mjs} +2 -2
  29. package/dist/{types-DS3i_5LV.mjs → types-B_8X_rZk.mjs} +572 -93
  30. package/dist/{types-BNGeiP1C.cjs → types-CjlB_fKT.cjs} +573 -93
  31. package/package.json +7 -7
@@ -3,7 +3,7 @@
3
3
  var chalk = require('chalk');
4
4
  var os = require('node:os');
5
5
  var node_crypto = require('node:crypto');
6
- var persistence = require('./types-BNGeiP1C.cjs');
6
+ var persistence = require('./types-CjlB_fKT.cjs');
7
7
  var spawn = require('cross-spawn');
8
8
  var path = require('node:path');
9
9
  var node_readline = require('node:readline');
@@ -46,24 +46,74 @@ var promises$1 = require('node:readline/promises');
46
46
 
47
47
  var _documentCurrentScript = typeof document !== 'undefined' ? document.currentScript : null;
48
48
  function _interopNamespaceDefault(e) {
49
- var n = Object.create(null);
50
- if (e) {
51
- Object.keys(e).forEach(function (k) {
52
- if (k !== 'default') {
53
- var d = Object.getOwnPropertyDescriptor(e, k);
54
- Object.defineProperty(n, k, d.get ? d : {
55
- enumerable: true,
56
- get: function () { return e[k]; }
49
+ var n = Object.create(null);
50
+ if (e) {
51
+ Object.keys(e).forEach(function (k) {
52
+ if (k !== 'default') {
53
+ var d = Object.getOwnPropertyDescriptor(e, k);
54
+ Object.defineProperty(n, k, d.get ? d : {
55
+ enumerable: true,
56
+ get: function () { return e[k]; }
57
+ });
58
+ }
57
59
  });
58
- }
59
- });
60
- }
61
- n.default = e;
62
- return Object.freeze(n);
60
+ }
61
+ n.default = e;
62
+ return Object.freeze(n);
63
63
  }
64
64
 
65
65
  var tmp__namespace = /*#__PURE__*/_interopNamespaceDefault(tmp);
66
66
 
67
+ const PROCESS_IDENTITY_FIELDS = [
68
+ "hostPid",
69
+ "version",
70
+ "startedBy",
71
+ "startedFromDaemon",
72
+ "happyHomeDir",
73
+ "happyLibDir",
74
+ "happyToolsDir",
75
+ "capabilities",
76
+ "attachmentKinds",
77
+ "queueCancellation",
78
+ "sandbox",
79
+ "dangerouslySkipPermissions",
80
+ "os",
81
+ "host",
82
+ "homeDir",
83
+ "permissionMode"
84
+ ];
85
+ function processIdentityFields(local) {
86
+ const out = {};
87
+ for (const key of PROCESS_IDENTITY_FIELDS) {
88
+ const value = local[key];
89
+ if (value !== void 0) out[key] = value;
90
+ }
91
+ return out;
92
+ }
93
+ function mergeReconnectMetadata(server, local, now) {
94
+ return {
95
+ ...server,
96
+ ...processIdentityFields(local),
97
+ lifecycleState: "running",
98
+ lifecycleStateSince: now,
99
+ archivedBy: void 0,
100
+ archiveReason: void 0
101
+ };
102
+ }
103
+ function applyServerSnapshot(response, snapshot) {
104
+ return {
105
+ ...response,
106
+ seq: snapshot.seq,
107
+ metadata: snapshot.metadata,
108
+ metadataVersion: snapshot.metadataVersion,
109
+ agentState: snapshot.agentState,
110
+ agentStateVersion: snapshot.agentStateVersion
111
+ };
112
+ }
113
+ function withoutServerSnapshot(response) {
114
+ return { ...response, metadataVersion: 0, agentStateVersion: 0 };
115
+ }
116
+
67
117
  function daemonControlHeaders(controlToken) {
68
118
  return {
69
119
  "Content-Type": "application/json",
@@ -1570,6 +1620,9 @@ function query(params) {
1570
1620
  if (opts?.mcpServers && Object.keys(opts.mcpServers).length > 0) {
1571
1621
  ensureLocalProxyBypass(env);
1572
1622
  }
1623
+ if (sdkOptions.allowDangerouslySkipPermissions && typeof process.getuid === "function" && process.getuid() === 0 && env.IS_SANDBOX === void 0) {
1624
+ env.IS_SANDBOX = "1";
1625
+ }
1573
1626
  sdkOptions.env = env;
1574
1627
  if (opts?.canCallTool) {
1575
1628
  const callback = opts.canCallTool;
@@ -1655,6 +1708,12 @@ function resolveRemoteClaudePermissionMode(currentMode, incomingMode, sandboxEna
1655
1708
  }
1656
1709
  return nextMode;
1657
1710
  }
1711
+ function reconcilePublishedPermissionMode(input) {
1712
+ if (!input.effective) return null;
1713
+ const mismatch = input.effective !== input.intent;
1714
+ if (input.effective === input.published) return mismatch ? { publish: input.effective, mismatch } : null;
1715
+ return { publish: input.effective, mismatch };
1716
+ }
1658
1717
 
1659
1718
  function parseCompact(message) {
1660
1719
  const trimmed = message.trim();
@@ -1984,7 +2043,12 @@ async function claudeRemote(opts) {
1984
2043
  mcpServers: systemInit.mcp_servers?.map((s) => ({ name: s.name, status: s.status })),
1985
2044
  skills: systemInit.skills,
1986
2045
  model: systemInit.model,
1987
- modelIsDefault: initial.mode.model == null
2046
+ modelIsDefault: initial.mode.model == null,
2047
+ // The SDK's own verdict on the mode it will enforce —
2048
+ // settings (permissions.deny/ask/defaultMode/
2049
+ // disableBypassPermissionsMode) can override what we
2050
+ // asked for. runClaude publishes THIS, not our intent.
2051
+ permissionMode: systemInit.permissionMode
1988
2052
  });
1989
2053
  }
1990
2054
  if (systemInit.session_id) {
@@ -2002,6 +2066,10 @@ async function claudeRemote(opts) {
2002
2066
  if (message.type === "result") {
2003
2067
  updateThinking(false);
2004
2068
  persistence.logger.debug("[claudeRemote] Result received");
2069
+ const denials = message.permission_denials;
2070
+ if (denials && denials.length > 0) {
2071
+ persistence.logger.warn(`[claudeRemote] ${denials.length} tool call(s) auto-denied by Claude Code policy: ${denials.map((d) => d.tool_name ?? "?").join(", ")}`);
2072
+ }
2005
2073
  if (isCompactCommand) {
2006
2074
  const compactSucceeded = message.subtype === "success";
2007
2075
  persistence.logger.debug(`[claudeRemote] Compaction ${compactSucceeded ? "completed" : "failed"}`);
@@ -2212,16 +2280,9 @@ class PermissionHandler {
2212
2280
  }
2213
2281
  } else {
2214
2282
  if (response.approved && response.mode) {
2215
- try {
2216
- if (!this.setPermissionModeCallback) throw new Error("permission mode updater unavailable");
2217
- await this.setPermissionModeCallback(response.mode);
2218
- this.permissionMode = response.mode;
2219
- this.onModeChangedCallback?.(response.mode);
2220
- } catch (err) {
2221
- const reason = `Failed to switch permission mode: ${err instanceof Error ? err.message : String(err)}`;
2222
- pending.resolve({ behavior: "deny", message: reason });
2223
- return { ...response, approved: false, reason };
2224
- }
2283
+ this.permissionMode = response.mode;
2284
+ this.deferredPermissionMode = response.mode;
2285
+ this.onModeChangedCallback?.(response.mode);
2225
2286
  }
2226
2287
  if (response.approved && !pending.suggestions?.length && response.allowTools?.length) {
2227
2288
  response.allowTools.forEach((tool) => {
@@ -2562,6 +2623,17 @@ class PermissionHandler {
2562
2623
  }
2563
2624
  }
2564
2625
 
2626
+ function rewriteQueuedPermissionMode(queue, hasher, permissionMode) {
2627
+ let rewritten = 0;
2628
+ for (const item of queue) {
2629
+ if (item.mode.permissionMode === permissionMode) continue;
2630
+ item.mode = { ...item.mode, permissionMode };
2631
+ item.modeHash = hasher(item.mode);
2632
+ rewritten += 1;
2633
+ }
2634
+ return rewritten;
2635
+ }
2636
+
2565
2637
  function formatClaudeMessageForInk(message, messageBuffer, onAssistantResult) {
2566
2638
  persistence.logger.debugLargeJson("[CLAUDE INK] Message from remote mode:", message);
2567
2639
  switch (message.type) {
@@ -2816,7 +2888,13 @@ class SDKToLogConverter {
2816
2888
  type: "user",
2817
2889
  message: userMsg.message,
2818
2890
  ...userMsg.parent_tool_use_id ? { parent_tool_use_id: userMsg.parent_tool_use_id } : {},
2819
- ...meta ? { isMeta: true } : {}
2891
+ ...meta ? { isMeta: true } : {},
2892
+ // B-260-P2: structured tool output (Agent/Task final report +
2893
+ // run totals, or the `async_launched` stub marker) and the
2894
+ // message origin (task-notification). Both are consumed by
2895
+ // sessionProtocolMapper; the raw-line schema is passthrough.
2896
+ ...userMsg.tool_use_result !== void 0 ? { tool_use_result: userMsg.tool_use_result } : {},
2897
+ ...userMsg.origin ? { origin: userMsg.origin } : {}
2820
2898
  };
2821
2899
  if (Array.isArray(userMsg.message.content)) {
2822
2900
  for (const content of userMsg.message.content) {
@@ -3327,7 +3405,7 @@ function createTurnSteeringController() {
3327
3405
  };
3328
3406
  }
3329
3407
 
3330
- async function claudeRemoteLauncher(session, onPermissionModeChange) {
3408
+ async function claudeRemoteLauncher(session, onPermissionModeChange, onEffectivePermissionMode) {
3331
3409
  persistence.logger.debug("[claudeRemoteLauncher] Starting remote launcher");
3332
3410
  const hasTTY = process.stdout.isTTY && process.stdin.isTTY;
3333
3411
  persistence.logger.debug(`[claudeRemoteLauncher] TTY available: ${hasTTY}`);
@@ -3561,6 +3639,10 @@ async function claudeRemoteLauncher(session, onPermissionModeChange) {
3561
3639
  mode = { ...mode, permissionMode: nextMode };
3562
3640
  modeHash = session.queue.modeHasher(mode);
3563
3641
  }
3642
+ rewriteQueuedPermissionMode(session.queue.queue, session.queue.modeHasher, nextMode);
3643
+ if (pending) {
3644
+ pending = { ...pending, mode: { ...pending.mode, permissionMode: nextMode } };
3645
+ }
3564
3646
  onPermissionModeChange?.(nextMode);
3565
3647
  return nextMode;
3566
3648
  };
@@ -3633,6 +3715,7 @@ async function claudeRemoteLauncher(session, onPermissionModeChange) {
3633
3715
  skillCount: metadata.skills?.length ?? 0
3634
3716
  });
3635
3717
  session.client.updateMetadata((currentMetadata) => applyClaudeSdkMetadata(currentMetadata, metadata));
3718
+ if (metadata.permissionMode) onEffectivePermissionMode?.(metadata.permissionMode);
3636
3719
  },
3637
3720
  onQueryReady: (q) => {
3638
3721
  turnSteering.setInterrupt(q.interrupt);
@@ -3810,7 +3893,7 @@ async function loop(opts) {
3810
3893
  break;
3811
3894
  }
3812
3895
  case "remote": {
3813
- const reason = await claudeRemoteLauncher(session, opts.onPermissionModeChange);
3896
+ const reason = await claudeRemoteLauncher(session, opts.onPermissionModeChange, opts.onEffectivePermissionMode);
3814
3897
  switch (reason) {
3815
3898
  case "exit":
3816
3899
  return 0;
@@ -5285,6 +5368,45 @@ function sanitizeSpawnPermissionMode(value) {
5285
5368
  return ALLOWED_SPAWN_PERMISSION_MODES.includes(value) ? value : null;
5286
5369
  }
5287
5370
 
5371
+ function resumePrecheck(metadata, fs) {
5372
+ const flavor = metadata.flavor ?? "claude";
5373
+ if (flavor !== "claude" && flavor !== "codex") {
5374
+ return { ok: false, reason: "unsupported-flavor", detail: `flavor "${flavor}" cannot be resumed` };
5375
+ }
5376
+ if (!metadata.path || !fs.cwdExists(metadata.path)) {
5377
+ return { ok: false, reason: "missing-cwd", detail: `working directory ${metadata.path ?? "(none)"} does not exist` };
5378
+ }
5379
+ if (flavor === "codex") {
5380
+ if (!metadata.codexThreadId) return { ok: false, reason: "no-backend-id", detail: "session has no Codex thread id" };
5381
+ return { ok: true };
5382
+ }
5383
+ if (!persistence.isClaudeSessionId(metadata.claudeSessionId)) {
5384
+ return { ok: false, reason: "no-backend-id", detail: "session has no Claude session id" };
5385
+ }
5386
+ if (!fs.conversationExists(metadata.path, metadata.claudeSessionId)) {
5387
+ return { ok: false, reason: "conversation-missing", detail: `conversation ${metadata.claudeSessionId} is not on disk` };
5388
+ }
5389
+ return { ok: true };
5390
+ }
5391
+ function sanitizeResumeModel(value) {
5392
+ if (typeof value !== "string") return null;
5393
+ return /^[A-Za-z0-9][A-Za-z0-9._:-]{0,63}$/.test(value) ? value : null;
5394
+ }
5395
+
5396
+ const DEFAULT_MAX_RESTARTS = 3;
5397
+ function decideRestart(priorAttempts, max = DEFAULT_MAX_RESTARTS) {
5398
+ if (priorAttempts >= max) {
5399
+ return {
5400
+ allowed: false,
5401
+ reason: `restart-limit: this session has already been restarted ${priorAttempts} time(s) this daemon session (max ${max}). Start a new session instead.`
5402
+ };
5403
+ }
5404
+ return { allowed: true, attempt: priorAttempts + 1 };
5405
+ }
5406
+ function recordRestartAttempt(priorAttempts) {
5407
+ return priorAttempts + 1;
5408
+ }
5409
+
5288
5410
  const CONTROL_TOKEN_BYTES = 32;
5289
5411
  function createDaemonControlToken() {
5290
5412
  return node_crypto.randomBytes(CONTROL_TOKEN_BYTES).toString("base64url");
@@ -7102,6 +7224,7 @@ async function startDaemon() {
7102
7224
  tracked.pid = livePid;
7103
7225
  tracked.startedBy = "recovered after daemon restart";
7104
7226
  pidToTrackedSession.set(livePid, tracked);
7227
+ persistence.persistSession(id, { ...s, savedAt: Date.now() });
7105
7228
  } else {
7106
7229
  sessionIdToFinishedSession.set(id, tracked);
7107
7230
  }
@@ -7530,6 +7653,13 @@ async function startDaemon() {
7530
7653
  const timeout = setTimeout(() => {
7531
7654
  pidToAwaiter.delete(happyProcess.pid);
7532
7655
  persistence.logger.debug(`[DAEMON RUN] Session webhook timeout for PID ${happyProcess.pid}`);
7656
+ if (happyProcess.pid) {
7657
+ try {
7658
+ terminateProcess(happyProcess.pid, () => {
7659
+ });
7660
+ } catch {
7661
+ }
7662
+ }
7533
7663
  resolve({
7534
7664
  type: "error",
7535
7665
  errorMessage: `Session webhook timeout for PID ${happyProcess.pid}`
@@ -7552,6 +7682,19 @@ async function startDaemon() {
7552
7682
  return sessionIdToFinishedSession.get(happySessionId);
7553
7683
  };
7554
7684
  const fetchServerSessionMetadata = async (sessionId, encryptionKey, encryptionVariant) => {
7685
+ try {
7686
+ const byId = await axios.get(`${persistence.configuration.serverUrl}/v1/sessions/${encodeURIComponent(sessionId)}`, {
7687
+ headers: { Authorization: `Bearer ${credentials.token}` },
7688
+ timeout: 1e4,
7689
+ validateStatus: (status) => status >= 200 && status < 300 || status === 404
7690
+ });
7691
+ if (byId.status !== 404) {
7692
+ const row = byId.data.session;
7693
+ if (row?.metadata) return persistence.decrypt(encryptionKey, encryptionVariant, persistence.decodeBase64(row.metadata));
7694
+ }
7695
+ } catch (error) {
7696
+ persistence.logger.debug(`[DAEMON RUN] by-id session metadata fetch failed, falling back to list: ${error instanceof Error ? error.message : error}`);
7697
+ }
7555
7698
  try {
7556
7699
  const response = await axios.get(`${persistence.configuration.serverUrl}/v1/sessions`, {
7557
7700
  headers: { Authorization: `Bearer ${credentials.token}` },
@@ -7567,17 +7710,38 @@ async function startDaemon() {
7567
7710
  return null;
7568
7711
  }
7569
7712
  };
7713
+ const resumeGates = /* @__PURE__ */ new Map();
7570
7714
  const resumeSession = async (happySessionId, options) => {
7715
+ let gate = resumeGates.get(happySessionId);
7716
+ if (!gate) {
7717
+ gate = createSpawnGate();
7718
+ resumeGates.set(happySessionId, gate);
7719
+ }
7571
7720
  try {
7721
+ return await gate.join(() => resumeSessionImpl(happySessionId, options));
7722
+ } finally {
7723
+ if (!gate.inFlight()) resumeGates.delete(happySessionId);
7724
+ }
7725
+ };
7726
+ const resumeSessionImpl = async (happySessionId, options) => {
7727
+ try {
7728
+ for (const [pid, live] of pidToTrackedSession.entries()) {
7729
+ if (live.happySessionId !== happySessionId) continue;
7730
+ if (isPidAlive(pid)) {
7731
+ persistence.logger.debug(`[DAEMON RUN] resume ${happySessionId}: process ${pid} already alive \u2014 idempotent success`);
7732
+ return { type: "success", sessionId: happySessionId };
7733
+ }
7734
+ onChildExited(pid);
7735
+ }
7572
7736
  const tracked = findTrackedSessionById(happySessionId);
7573
7737
  if (!tracked) {
7574
- return { type: "error", errorMessage: `Session ${happySessionId} is not tracked by this daemon. It may have been started before the daemon or on another machine.` };
7738
+ return { type: "error", errorMessage: `resume-precheck:not-tracked: Session ${happySessionId} is not tracked by this daemon. It may have been started before the daemon, more than 14 days ago, or on another machine.` };
7575
7739
  }
7576
7740
  if (!tracked.happySessionMetadataFromLocalWebhook) {
7577
- return { type: "error", errorMessage: `Session ${happySessionId} has no metadata. Cannot resume.` };
7741
+ return { type: "error", errorMessage: `resume-precheck:no-metadata: Session ${happySessionId} has no metadata. Cannot resume.` };
7578
7742
  }
7579
7743
  if (!tracked.encryption) {
7580
- return { type: "error", errorMessage: `Session ${happySessionId} has no stored encryption data. It was likely started before this feature was available. Restart the daemon and start a new session to enable resume.` };
7744
+ return { type: "error", errorMessage: `resume-precheck:no-encryption: Session ${happySessionId} has no stored encryption data. It was likely started before this feature was available. Restart the daemon and start a new session to enable resume.` };
7581
7745
  }
7582
7746
  let metadata = tracked.happySessionMetadataFromLocalWebhook;
7583
7747
  const needsFetch = !metadata.claudeSessionId && (!metadata.flavor || metadata.flavor === "claude") || !metadata.codexThreadId && metadata.flavor === "codex";
@@ -7589,18 +7753,24 @@ async function startDaemon() {
7589
7753
  tracked.happySessionMetadataFromLocalWebhook = serverMetadata;
7590
7754
  }
7591
7755
  }
7756
+ const precheck = resumePrecheck(metadata, {
7757
+ cwdExists: (p) => fs$1.existsSync(p),
7758
+ conversationExists: (cwd, claudeSessionId) => fs$1.existsSync(path$1.join(persistence.getProjectPath(cwd), `${claudeSessionId}.jsonl`))
7759
+ });
7760
+ if (!precheck.ok) {
7761
+ return { type: "error", errorMessage: `resume-precheck:${precheck.reason}: ${precheck.detail}` };
7762
+ }
7592
7763
  const launch = buildResumeLaunch(
7593
7764
  { id: happySessionId, active: true, metadata },
7594
7765
  { startedBy: "daemon", claudeStartingMode: "remote" }
7595
7766
  );
7596
- if (options?.model) {
7597
- launch.args.push("--model", options.model);
7598
- }
7599
- if (options?.permissionMode) {
7600
- launch.args.push("--permission-mode", options.permissionMode);
7601
- }
7602
- await fs.access(launch.cwd);
7603
- return spawnTrackedHappyProcess({
7767
+ const model = sanitizeResumeModel(options?.model);
7768
+ if (model) launch.args.push("--model", model);
7769
+ else if (options?.model !== void 0) persistence.logger.debug(`[DAEMON RUN] resume: ignoring invalid model ${JSON.stringify(options.model)}`);
7770
+ const permissionMode = sanitizeSpawnPermissionMode(options?.permissionMode);
7771
+ if (permissionMode) launch.args.push("--permission-mode", permissionMode);
7772
+ else if (options?.permissionMode !== void 0) persistence.logger.debug(`[DAEMON RUN] resume: ignoring invalid permission mode ${JSON.stringify(options.permissionMode)}`);
7773
+ const result = await spawnTrackedHappyProcess({
7604
7774
  args: launch.args,
7605
7775
  cwd: launch.cwd,
7606
7776
  env: {
@@ -7613,6 +7783,18 @@ async function startDaemon() {
7613
7783
  HAPPY_RECONNECT_AGENT_STATE_VERSION: String(tracked.encryption.agentStateVersion)
7614
7784
  }
7615
7785
  });
7786
+ if (result.type === "success") {
7787
+ persistence.persistSession(happySessionId, {
7788
+ encryptionKey: persistence.encodeBase64(tracked.encryption.encryptionKey),
7789
+ encryptionVariant: tracked.encryption.encryptionVariant,
7790
+ seq: tracked.encryption.seq,
7791
+ metadataVersion: tracked.encryption.metadataVersion,
7792
+ agentStateVersion: tracked.encryption.agentStateVersion,
7793
+ metadata,
7794
+ savedAt: Date.now()
7795
+ });
7796
+ }
7797
+ return result;
7616
7798
  } catch (error) {
7617
7799
  const errorMessage = error instanceof Error ? error.message : error && typeof error === "object" ? JSON.stringify(error) : String(error);
7618
7800
  persistence.logger.debug(`[DAEMON RUN] Failed to resume session: ${errorMessage}`, error instanceof Error ? error.stack : void 0);
@@ -7622,6 +7804,136 @@ async function startDaemon() {
7622
7804
  };
7623
7805
  }
7624
7806
  };
7807
+ const restartCounts = /* @__PURE__ */ new Map();
7808
+ const stopSessionAndWait = (happySessionId, timeoutMs = 8e3) => {
7809
+ let targetPid = null;
7810
+ for (const [pid2, s] of pidToTrackedSession.entries()) {
7811
+ if (s.happySessionId === happySessionId && isPidAlive(pid2)) {
7812
+ targetPid = pid2;
7813
+ break;
7814
+ }
7815
+ }
7816
+ if (targetPid === null) return Promise.resolve();
7817
+ const pid = targetPid;
7818
+ return new Promise((resolve) => {
7819
+ let settled = false;
7820
+ const done = () => {
7821
+ if (!settled) {
7822
+ settled = true;
7823
+ resolve();
7824
+ }
7825
+ };
7826
+ const requested = terminateProcess(pid, () => {
7827
+ const tracked = pidToTrackedSession.get(pid);
7828
+ if (tracked) {
7829
+ if (tracked.happySessionId && tracked.encryption) {
7830
+ sessionIdToFinishedSession.set(tracked.happySessionId, tracked);
7831
+ }
7832
+ pidToTrackedSession.delete(pid);
7833
+ }
7834
+ done();
7835
+ });
7836
+ if (!requested) done();
7837
+ setTimeout(done, timeoutMs).unref?.();
7838
+ });
7839
+ };
7840
+ const restartSession = async (happySessionId, options) => {
7841
+ let gate = resumeGates.get(happySessionId);
7842
+ if (!gate) {
7843
+ gate = createSpawnGate();
7844
+ resumeGates.set(happySessionId, gate);
7845
+ }
7846
+ try {
7847
+ return await gate.replace(() => restartSessionImpl(happySessionId, options));
7848
+ } finally {
7849
+ if (!gate.inFlight()) resumeGates.delete(happySessionId);
7850
+ }
7851
+ };
7852
+ const restartSessionImpl = async (happySessionId, options) => {
7853
+ try {
7854
+ const prior = restartCounts.get(happySessionId) ?? 0;
7855
+ const decision = decideRestart(prior, DEFAULT_MAX_RESTARTS);
7856
+ if (!decision.allowed) {
7857
+ return { type: "error", errorMessage: `restart:${decision.reason}` };
7858
+ }
7859
+ await stopSessionAndWait(happySessionId);
7860
+ const tracked = findTrackedSessionById(happySessionId);
7861
+ if (!tracked) {
7862
+ return { type: "error", errorMessage: `restart-precheck:not-tracked: Session ${happySessionId} is not tracked by this daemon.` };
7863
+ }
7864
+ if (!tracked.happySessionMetadataFromLocalWebhook) {
7865
+ return { type: "error", errorMessage: `restart-precheck:no-metadata: Session ${happySessionId} has no metadata. Cannot restart.` };
7866
+ }
7867
+ if (!tracked.encryption) {
7868
+ return { type: "error", errorMessage: `restart-precheck:no-encryption: Session ${happySessionId} has no stored encryption data. Restart the daemon and start a new session.` };
7869
+ }
7870
+ let metadata = tracked.happySessionMetadataFromLocalWebhook;
7871
+ const needsFetch = !metadata.claudeSessionId && (!metadata.flavor || metadata.flavor === "claude") || !metadata.codexThreadId && metadata.flavor === "codex";
7872
+ if (needsFetch) {
7873
+ const serverMetadata = await fetchServerSessionMetadata(happySessionId, tracked.encryption.encryptionKey, tracked.encryption.encryptionVariant);
7874
+ if (serverMetadata) {
7875
+ metadata = serverMetadata;
7876
+ tracked.happySessionMetadataFromLocalWebhook = serverMetadata;
7877
+ }
7878
+ }
7879
+ const precheck = resumePrecheck(metadata, {
7880
+ cwdExists: (p) => fs$1.existsSync(p),
7881
+ conversationExists: (cwd2, claudeSessionId) => fs$1.existsSync(path$1.join(persistence.getProjectPath(cwd2), `${claudeSessionId}.jsonl`))
7882
+ });
7883
+ let args;
7884
+ let cwd;
7885
+ if (precheck.ok) {
7886
+ const launch = buildResumeLaunch(
7887
+ { id: happySessionId, active: true, metadata },
7888
+ { startedBy: "daemon", claudeStartingMode: "remote" }
7889
+ );
7890
+ args = launch.args;
7891
+ cwd = launch.cwd;
7892
+ } else if ((metadata.flavor ?? "claude") === "claude" && typeof metadata.path === "string" && metadata.path.length > 0) {
7893
+ cwd = metadata.path;
7894
+ if (!fs$1.existsSync(cwd)) {
7895
+ return { type: "error", errorMessage: `restart-precheck:cwd-missing: ${cwd}` };
7896
+ }
7897
+ args = ["claude", "--happy-starting-mode", "remote", "--started-by", "daemon"];
7898
+ } else {
7899
+ return { type: "error", errorMessage: `restart-precheck:${precheck.ok ? "unknown" : precheck.reason}: ${precheck.ok ? "" : precheck.detail}` };
7900
+ }
7901
+ const model = sanitizeResumeModel(options?.model);
7902
+ if (model) args.push("--model", model);
7903
+ const permissionMode = sanitizeSpawnPermissionMode(options?.permissionMode);
7904
+ if (permissionMode) args.push("--permission-mode", permissionMode);
7905
+ restartCounts.set(happySessionId, recordRestartAttempt(prior));
7906
+ const result = await spawnTrackedHappyProcess({
7907
+ args,
7908
+ cwd,
7909
+ env: {
7910
+ ...process.env,
7911
+ HAPPY_RECONNECT_SESSION_ID: happySessionId,
7912
+ HAPPY_RECONNECT_ENCRYPTION_KEY: persistence.encodeBase64(tracked.encryption.encryptionKey),
7913
+ HAPPY_RECONNECT_ENCRYPTION_VARIANT: tracked.encryption.encryptionVariant,
7914
+ HAPPY_RECONNECT_SEQ: String(tracked.encryption.seq),
7915
+ HAPPY_RECONNECT_METADATA_VERSION: String(tracked.encryption.metadataVersion),
7916
+ HAPPY_RECONNECT_AGENT_STATE_VERSION: String(tracked.encryption.agentStateVersion)
7917
+ }
7918
+ });
7919
+ if (result.type === "success") {
7920
+ persistence.persistSession(happySessionId, {
7921
+ encryptionKey: persistence.encodeBase64(tracked.encryption.encryptionKey),
7922
+ encryptionVariant: tracked.encryption.encryptionVariant,
7923
+ seq: tracked.encryption.seq,
7924
+ metadataVersion: tracked.encryption.metadataVersion,
7925
+ agentStateVersion: tracked.encryption.agentStateVersion,
7926
+ metadata,
7927
+ savedAt: Date.now()
7928
+ });
7929
+ }
7930
+ return result;
7931
+ } catch (error) {
7932
+ const errorMessage = error instanceof Error ? error.message : String(error);
7933
+ persistence.logger.debug(`[DAEMON RUN] Failed to restart session: ${errorMessage}`, error instanceof Error ? error.stack : void 0);
7934
+ return { type: "error", errorMessage: `Failed to restart session: ${errorMessage}` };
7935
+ }
7936
+ };
7625
7937
  const stopSession = (sessionId) => {
7626
7938
  persistence.logger.debug(`[DAEMON RUN] Attempting to stop session ${sessionId}`);
7627
7939
  for (const [pid, session] of pidToTrackedSession.entries()) {
@@ -7792,6 +8104,7 @@ async function startDaemon() {
7792
8104
  apiMachine.setRPCHandlers({
7793
8105
  spawnSession,
7794
8106
  resumeSession,
8107
+ restartSession,
7795
8108
  stopSession,
7796
8109
  listTrackedSessionIds: () => [...pidToTrackedSession.values()].map((session) => session.happySessionId).filter((sessionId) => typeof sessionId === "string"),
7797
8110
  requestShutdown: () => requestShutdown("happy-app")
@@ -8843,7 +9156,7 @@ const MAX_TITLE_CHARS = 60;
8843
9156
  const GENERATION_TIMEOUT_MS = 3e4;
8844
9157
  function resolveClaudeBinary() {
8845
9158
  try {
8846
- 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-4YmVbx7j.cjs', document.baseURI).href)));
9159
+ 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-B63Vjt4W.cjs', document.baseURI).href)));
8847
9160
  const utilsPath = path.resolve(path.join(persistence.projectPath(), "scripts", "claude_version_utils.cjs"));
8848
9161
  const { getClaudeCliPath } = require$1(utilsPath);
8849
9162
  const path$1 = getClaudeCliPath();
@@ -9383,6 +9696,18 @@ async function runClaude(credentials, options = {}) {
9383
9696
  if (reconnectSessionId && !await api.reactivateSession(response.id)) {
9384
9697
  throw new Error(`Failed to reactivate archived session ${response.id}`);
9385
9698
  }
9699
+ let reconnectSeeded = false;
9700
+ if (reconnectSessionId) {
9701
+ const snapshot = await api.getSession(response.id, response.encryptionKey, response.encryptionVariant);
9702
+ if (snapshot.ok) {
9703
+ response = applyServerSnapshot(response, snapshot.session);
9704
+ reconnectSeeded = true;
9705
+ persistence.logger.debug(`[START] Reconnect seeded from server: seq=${snapshot.session.seq} metadataVersion=${snapshot.session.metadataVersion}`);
9706
+ } else {
9707
+ response = withoutServerSnapshot(response);
9708
+ persistence.logger.debug(`[START] Reconnect without server snapshot (${snapshot.reason}); skipping existing messages`);
9709
+ }
9710
+ }
9386
9711
  try {
9387
9712
  persistence.logger.debug(`[START] Reporting session ${response.id} to daemon`);
9388
9713
  const result = await notifyDaemonSessionStarted(response.id, metadata, {
@@ -9400,15 +9725,17 @@ async function runClaude(credentials, options = {}) {
9400
9725
  } catch (error) {
9401
9726
  persistence.logger.debug("[START] Failed to report to daemon (may not be running):", error);
9402
9727
  }
9403
- const session = api.sessionSyncClient(response);
9728
+ const session = api.sessionSyncClient(response, reconnectSeeded ? { initialSeq: response.seq } : void 0);
9404
9729
  if (reconnectSessionId) {
9405
9730
  session.suppressNextArchiveSignal();
9406
- session.skipExistingMessages();
9731
+ if (!reconnectSeeded) session.skipExistingMessages();
9407
9732
  session.updateMetadata((meta) => ({
9408
- ...meta,
9409
- lifecycleState: "running",
9410
- archivedBy: void 0,
9411
- queueCancellation: true
9733
+ ...mergeReconnectMetadata(meta, metadata, Date.now()),
9734
+ queueCancellation: true,
9735
+ // B-262 batch 2 (B5): a reconnected process re-publishes the mode
9736
+ // IT enforces; the server copy may still carry the previous
9737
+ // process's value.
9738
+ permissionMode: mapToClaudeMode(initialPermissionMode ?? "default")
9412
9739
  }));
9413
9740
  }
9414
9741
  const forkClaudeSessionId = process.env.HAPPY_FORK_CLAUDE_SESSION_ID;
@@ -9548,6 +9875,22 @@ async function runClaude(credentials, options = {}) {
9548
9875
  publishedPermissionMode = published;
9549
9876
  session.updateMetadata((meta) => ({ ...meta, permissionMode: published }));
9550
9877
  };
9878
+ const publishEffectivePermissionMode = (effective) => {
9879
+ const decision = reconcilePublishedPermissionMode({
9880
+ intent: mapToClaudeMode(currentPermissionMode ?? "default"),
9881
+ published: publishedPermissionMode,
9882
+ effective
9883
+ });
9884
+ if (!decision) return;
9885
+ if (decision.mismatch) {
9886
+ persistence.logger.warn(`[loop] Claude Code enforces permission mode '${effective}' but this process asked for '${mapToClaudeMode(currentPermissionMode ?? "default")}' \u2014 check ~/.claude settings (permissions.deny/ask/defaultMode/disableBypassPermissionsMode). Publishing the effective mode.`);
9887
+ }
9888
+ if (decision.publish !== publishedPermissionMode) {
9889
+ publishedPermissionMode = decision.publish;
9890
+ session.updateMetadata((meta) => ({ ...meta, permissionMode: decision.publish }));
9891
+ }
9892
+ };
9893
+ let lastExplicitModeSwitchAt = 0;
9551
9894
  let currentModel = options.model ?? DEFAULT_CLAUDE_MODEL;
9552
9895
  let currentFallbackModel = void 0;
9553
9896
  let currentCustomSystemPrompt = void 0;
@@ -9592,7 +9935,11 @@ async function runClaude(credentials, options = {}) {
9592
9935
  }
9593
9936
  const attachmentsForThisMessage = await session.drainAttachmentsForUserMessage();
9594
9937
  let messagePermissionMode = currentPermissionMode;
9595
- if (message.meta?.permissionMode) {
9938
+ const messageCreatedAt = message.createdAt;
9939
+ const staleModeSnapshot = message.meta?.permissionMode !== void 0 && typeof messageCreatedAt === "number" && messageCreatedAt < lastExplicitModeSwitchAt;
9940
+ if (staleModeSnapshot) {
9941
+ persistence.logger.debug(`[loop] Ignoring stale meta.permissionMode=${message.meta?.permissionMode} (message ${messageCreatedAt} predates explicit switch ${lastExplicitModeSwitchAt}); keeping ${currentPermissionMode}`);
9942
+ } else if (message.meta?.permissionMode) {
9596
9943
  const previousPermissionMode = currentPermissionMode;
9597
9944
  messagePermissionMode = resolveRemoteClaudePermissionMode(
9598
9945
  currentPermissionMode,
@@ -9856,9 +10203,11 @@ async function runClaude(credentials, options = {}) {
9856
10203
  },
9857
10204
  onAbort: resetCurrentModeDefaults,
9858
10205
  onPermissionModeChange: (mode) => {
10206
+ lastExplicitModeSwitchAt = Date.now();
9859
10207
  publishPermissionMode(mode);
9860
10208
  persistence.logger.debug(`[loop] Permission mode updated from session RPC / approval to: ${mode}`);
9861
10209
  },
10210
+ onEffectivePermissionMode: (mode) => publishEffectivePermissionMode(mode),
9862
10211
  mcpServers: {
9863
10212
  "happy": {
9864
10213
  type: "http",
@@ -11001,9 +11350,9 @@ function resolveLocalSignupBootstrap(configuredMode, configuredInviteCodes, gene
11001
11350
  };
11002
11351
  }
11003
11352
 
11004
- 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-4YmVbx7j.cjs', document.baseURI).href)));
11353
+ 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-B63Vjt4W.cjs', document.baseURI).href)));
11005
11354
  const __dirname$1 = path.dirname(__filename$1);
11006
- const require_ = node_module.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index-4YmVbx7j.cjs', document.baseURI).href)));
11355
+ const require_ = node_module.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index-B63Vjt4W.cjs', document.baseURI).href)));
11007
11356
  const PRISMA_QUERY_ENGINE_FILES = {
11008
11357
  "arm64-darwin": "libquery_engine-darwin-arm64.dylib.node",
11009
11358
  "x64-darwin": "libquery_engine-darwin.dylib.node",
@@ -12092,7 +12441,7 @@ function setupOfflineReconnection(opts) {
12092
12441
  });
12093
12442
  return { session, reconnectionHandle, isOffline: true };
12094
12443
  } else {
12095
- session = api.sessionSyncClient(response);
12444
+ session = api.sessionSyncClient(response, opts.sessionClientOptions);
12096
12445
  return { session, reconnectionHandle: null, isOffline: false };
12097
12446
  }
12098
12447
  }
@@ -12861,6 +13210,18 @@ async function runCodex(opts) {
12861
13210
  if (reconnectSessionId && response && !await api.reactivateSession(response.id)) {
12862
13211
  throw new Error(`Failed to reactivate archived session ${response.id}`);
12863
13212
  }
13213
+ let reconnectSeeded = false;
13214
+ if (reconnectSessionId && response) {
13215
+ const snapshot = await api.getSession(response.id, response.encryptionKey, response.encryptionVariant);
13216
+ if (snapshot.ok) {
13217
+ response = applyServerSnapshot(response, snapshot.session);
13218
+ reconnectSeeded = true;
13219
+ persistence.logger.debug(`[START] Reconnect seeded from server: seq=${snapshot.session.seq} metadataVersion=${snapshot.session.metadataVersion}`);
13220
+ } else {
13221
+ response = withoutServerSnapshot(response);
13222
+ persistence.logger.debug(`[START] Reconnect without server snapshot (${snapshot.reason}); skipping existing messages`);
13223
+ }
13224
+ }
12864
13225
  let session;
12865
13226
  let permissionHandler;
12866
13227
  let client;
@@ -12872,6 +13233,7 @@ async function runCodex(opts) {
12872
13233
  metadata,
12873
13234
  state,
12874
13235
  response,
13236
+ sessionClientOptions: reconnectSeeded && response ? { initialSeq: response.seq } : void 0,
12875
13237
  onSessionSwap: (newSession) => {
12876
13238
  session = newSession;
12877
13239
  if (permissionHandler) {
@@ -12882,12 +13244,8 @@ async function runCodex(opts) {
12882
13244
  session = initialSession;
12883
13245
  if (reconnectSessionId) {
12884
13246
  session.suppressNextArchiveSignal();
12885
- session.skipExistingMessages();
12886
- session.updateMetadata((meta) => ({
12887
- ...meta,
12888
- lifecycleState: "running",
12889
- archivedBy: void 0
12890
- }));
13247
+ if (!reconnectSeeded) session.skipExistingMessages();
13248
+ session.updateMetadata((meta) => mergeReconnectMetadata(meta, metadata, Date.now()));
12891
13249
  }
12892
13250
  if (response) {
12893
13251
  try {
@@ -13615,7 +13973,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
13615
13973
  process.exit(0);
13616
13974
  } else if (subcommand === "install-terminal-hooks") {
13617
13975
  try {
13618
- const { installTerminalHooks, parseTerminalHooksArgs, TERMINAL_HOOKS_HELP } = await Promise.resolve().then(function () { return require('./installTerminalHooks-DDpVxk8-.cjs'); });
13976
+ const { installTerminalHooks, parseTerminalHooksArgs, TERMINAL_HOOKS_HELP } = await Promise.resolve().then(function () { return require('./installTerminalHooks-BBc2nij4.cjs'); });
13619
13977
  const command = parseTerminalHooksArgs(args.slice(1));
13620
13978
  if (command.action === "help") {
13621
13979
  console.log(TERMINAL_HOOKS_HELP);
@@ -13632,7 +13990,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
13632
13990
  }
13633
13991
  } else if (subcommand === "spawn") {
13634
13992
  try {
13635
- const { handleSpawnCommand } = await Promise.resolve().then(function () { return require('./spawn-CH1Rq-LW.cjs'); });
13993
+ const { handleSpawnCommand } = await Promise.resolve().then(function () { return require('./spawn-CK1ma_qc.cjs'); });
13636
13994
  await handleSpawnCommand(args.slice(1));
13637
13995
  } catch (error) {
13638
13996
  console.error(chalk.red("Error:"), error instanceof Error ? error.message : "Unknown error");
@@ -13644,7 +14002,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
13644
14002
  return;
13645
14003
  } else if (subcommand === "send") {
13646
14004
  try {
13647
- const { handleSendCommand } = await Promise.resolve().then(function () { return require('./send-Bjen1TUE.cjs'); });
14005
+ const { handleSendCommand } = await Promise.resolve().then(function () { return require('./send-BEdGwmA-.cjs'); });
13648
14006
  await handleSendCommand(args.slice(1));
13649
14007
  } catch (error) {
13650
14008
  console.error(chalk.red("Error:"), error instanceof Error ? error.message : "Unknown error");
@@ -13750,9 +14108,9 @@ Conversation history is preserved on the server, but in-flight tool calls are in
13750
14108
  if (geminiSubcommand === "project" && args[2] === "set" && args[3]) {
13751
14109
  const projectId = args[3];
13752
14110
  try {
13753
- const { saveGoogleCloudProjectToConfig } = await Promise.resolve().then(function () { return require('./config-CgXitj0f.cjs'); });
13754
- const { readCredentialsForConfiguredRelay: readCredentialsForConfiguredRelay2 } = await Promise.resolve().then(function () { return require('./types-BNGeiP1C.cjs'); }).then(function (n) { return n.persistence; });
13755
- const { ApiClient: ApiClient2 } = await Promise.resolve().then(function () { return require('./types-BNGeiP1C.cjs'); }).then(function (n) { return n.api; });
14111
+ const { saveGoogleCloudProjectToConfig } = await Promise.resolve().then(function () { return require('./config-B77vhdwT.cjs'); });
14112
+ const { readCredentialsForConfiguredRelay: readCredentialsForConfiguredRelay2 } = await Promise.resolve().then(function () { return require('./types-CjlB_fKT.cjs'); }).then(function (n) { return n.persistence; });
14113
+ const { ApiClient: ApiClient2 } = await Promise.resolve().then(function () { return require('./types-CjlB_fKT.cjs'); }).then(function (n) { return n.api; });
13756
14114
  let userEmail = void 0;
13757
14115
  try {
13758
14116
  const credentials = await readCredentialsForConfiguredRelay2();
@@ -13783,7 +14141,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
13783
14141
  }
13784
14142
  if (geminiSubcommand === "project" && args[2] === "get") {
13785
14143
  try {
13786
- const { readGeminiLocalConfig } = await Promise.resolve().then(function () { return require('./config-CgXitj0f.cjs'); });
14144
+ const { readGeminiLocalConfig } = await Promise.resolve().then(function () { return require('./config-B77vhdwT.cjs'); });
13787
14145
  const config = readGeminiLocalConfig();
13788
14146
  if (config.googleCloudProject) {
13789
14147
  console.log(`Current Google Cloud Project: ${config.googleCloudProject}`);
@@ -13823,7 +14181,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
13823
14181
  process.exit(0);
13824
14182
  }
13825
14183
  try {
13826
- const { runGemini } = await Promise.resolve().then(function () { return require('./runGemini-ChG7cGMC.cjs'); });
14184
+ const { runGemini } = await Promise.resolve().then(function () { return require('./runGemini-BDSWSID6.cjs'); });
13827
14185
  let startedBy = void 0;
13828
14186
  for (let i = 1; i < args.length; i++) {
13829
14187
  if (args[i] === "--started-by") {
@@ -13845,7 +14203,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
13845
14203
  return;
13846
14204
  } else if (subcommand === "acp") {
13847
14205
  try {
13848
- const { runAcp, resolveAcpAgentConfig } = await Promise.resolve().then(function () { return require('./index-B1wTVXjt.cjs'); });
14206
+ const { runAcp, resolveAcpAgentConfig } = await Promise.resolve().then(function () { return require('./index-L3o5Gz-2.cjs'); });
13849
14207
  let startedBy = void 0;
13850
14208
  let verbose = false;
13851
14209
  const acpArgs = [];
@@ -13885,7 +14243,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
13885
14243
  return;
13886
14244
  } else if (subcommand === "openclaw") {
13887
14245
  try {
13888
- const { runOpenClaw } = await Promise.resolve().then(function () { return require('./runOpenClaw-D2jtVgpC.cjs'); });
14246
+ const { runOpenClaw } = await Promise.resolve().then(function () { return require('./runOpenClaw-DC9gb1bd.cjs'); });
13889
14247
  let startedBy = void 0;
13890
14248
  let verbose = false;
13891
14249
  let gatewayUrl;
@@ -13936,7 +14294,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
13936
14294
  return;
13937
14295
  } else if (subcommand === "mcp" && args.length === 1) {
13938
14296
  try {
13939
- const { handleMcpCommand } = await Promise.resolve().then(function () { return require('./mcp-B6Nq-RUL.cjs'); });
14297
+ const { handleMcpCommand } = await Promise.resolve().then(function () { return require('./mcp-DbYXyw1U.cjs'); });
13940
14298
  await handleMcpCommand();
13941
14299
  } catch (error) {
13942
14300
  process.stderr.write(`[very-happy mcp] Fatal: ${error instanceof Error ? error.message : String(error)}