very-happy-cli 0.2.143 → 0.2.145

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 (49) hide show
  1. package/dist/{AcpBackend-LEgn9vol.mjs → AcpBackend-BITeBnbV.mjs} +2 -2
  2. package/dist/{AcpBackend-B8oehrfU.cjs → AcpBackend-FPv5uXFa.cjs} +30 -30
  3. package/dist/{AcpSessionManager-BomdfyhZ.cjs → AcpSessionManager-vqLzM219.cjs} +9 -9
  4. package/dist/{AcpSessionManager-Yfbs5bi2.mjs → AcpSessionManager-w2srpWQJ.mjs} +1 -1
  5. package/dist/{agentGuidance-CJSl54ua.cjs → agentGuidance-Bd6GEiYp.cjs} +1 -1
  6. package/dist/{agentGuidance-BU4hxm8M.mjs → agentGuidance-HFHrz3C1.mjs} +1 -1
  7. package/dist/agentHome-CGl7FF7a.cjs +113 -0
  8. package/dist/agentHome-DBqr8rpv.mjs +107 -0
  9. package/dist/codex/happyMcpStdioBridge.cjs +2 -2
  10. package/dist/codex/happyMcpStdioBridge.mjs +2 -2
  11. package/dist/{config-euZ_K5Lo.mjs → config-B9zAvnGT.mjs} +4 -4
  12. package/dist/{config-CfqWoHmO.cjs → config-CPfFuHP6.cjs} +4 -4
  13. package/dist/{index-ZOMC8Gzn.mjs → index-BzLZu_aF.mjs} +8 -8
  14. package/dist/{index-PM_SsRpw.mjs → index-CxK0l_t0.mjs} +4 -4
  15. package/dist/{index-BREtikhm.cjs → index-D4Smqppj.cjs} +4 -4
  16. package/dist/{index-C510dSUn.cjs → index-DhwtFJEe.cjs} +309 -212
  17. package/dist/{index-Bj68y6ee.cjs → index-avfJgX4p.cjs} +31 -31
  18. package/dist/{index-DoiG88oX.mjs → index-eBrE-0R1.mjs} +136 -39
  19. package/dist/index.cjs +4 -4
  20. package/dist/index.mjs +4 -4
  21. package/dist/{installTerminalHooks-BGVQqbgq.mjs → installTerminalHooks-Dq1MFFDQ.mjs} +4 -4
  22. package/dist/{installTerminalHooks-C_jraM1j.cjs → installTerminalHooks-DspFGxBI.cjs} +4 -4
  23. package/dist/lib.cjs +5 -5
  24. package/dist/lib.mjs +2 -2
  25. package/dist/{limits-uABU-yq3.mjs → limits-CzWD9hWU.mjs} +8 -8
  26. package/dist/{limits-B3oVgqBJ.cjs → limits-DGZB-OVl.cjs} +7 -7
  27. package/dist/{mcp-G-3lL_KH.cjs → mcp-BioGrTC_.cjs} +9 -9
  28. package/dist/{mcp-CfbTQXyh.mjs → mcp-L1Yq25LB.mjs} +4 -4
  29. package/dist/{piRuntime-CWE-1W-y.cjs → piRuntime-DodWS0UI.cjs} +2 -2
  30. package/dist/{piRuntime-BE6iYQwU.mjs → piRuntime-UdVG4eJ7.mjs} +2 -2
  31. package/dist/{piTerminal-Dyc_9pGP.cjs → piTerminal-6P00O_w8.cjs} +6 -6
  32. package/dist/{piTerminal-rqKn1_Zy.mjs → piTerminal-BIRroC_N.mjs} +6 -6
  33. package/dist/{runGemini-BMlXIaTL.mjs → runGemini-B-It6K8t.mjs} +6 -6
  34. package/dist/{runGemini-C6qMFzcn.cjs → runGemini-ChCHjnIh.cjs} +24 -24
  35. package/dist/{runOpenClaw-C2_aCP7v.cjs → runOpenClaw-Cc4_zmHz.cjs} +26 -26
  36. package/dist/{runOpenClaw-CoO5Vp3S.mjs → runOpenClaw-DET6LY2v.mjs} +5 -5
  37. package/dist/{send-CBrJylJc.mjs → send-CPayvXBm.mjs} +4 -4
  38. package/dist/{send-DGVwmB-p.cjs → send-LBjLfAos.cjs} +4 -4
  39. package/dist/{sessions-DbLubh2N.mjs → sessions-CJUEp43_.mjs} +4 -4
  40. package/dist/{sessions-DyQXMN-8.cjs → sessions-WBowxNO-.cjs} +5 -5
  41. package/dist/{spawn-DIyFOn3W.cjs → spawn-BqgZc7YE.cjs} +6 -6
  42. package/dist/{spawn-wkkxEGdF.mjs → spawn-Dcetf5Jt.mjs} +4 -4
  43. package/dist/{teams-BTyVFK3P.mjs → teams-CW_Zb2Q1.mjs} +4 -4
  44. package/dist/{teams-QOkGFjkJ.cjs → teams-eIUxGmqg.cjs} +4 -4
  45. package/dist/{todo-DoLkqdBe.mjs → todo-CV5fwHg_.mjs} +3 -3
  46. package/dist/{todo-Du6pjwx_.cjs → todo-DeouLiGa.cjs} +5 -5
  47. package/dist/{types-BG4gFjLL.mjs → types-BbvxVQF3.mjs} +321 -11
  48. package/dist/{types-6__wqmmP.cjs → types-Bqo68u61.cjs} +328 -9
  49. package/package.json +7 -7
@@ -1,11 +1,11 @@
1
1
  'use strict';
2
2
 
3
- var AcpBackend = require('./AcpBackend-B8oehrfU.cjs');
4
- var persistence = require('./limits-B3oVgqBJ.cjs');
5
- var AcpSessionManager = require('./AcpSessionManager-BomdfyhZ.cjs');
6
- var api = require('./types-6__wqmmP.cjs');
7
- var index = require('./index-C510dSUn.cjs');
8
- var piRuntime = require('./piRuntime-CWE-1W-y.cjs');
3
+ var AcpBackend = require('./AcpBackend-FPv5uXFa.cjs');
4
+ var persistence = require('./limits-DGZB-OVl.cjs');
5
+ var AcpSessionManager = require('./AcpSessionManager-vqLzM219.cjs');
6
+ var index = require('./types-Bqo68u61.cjs');
7
+ var index$1 = require('./index-DhwtFJEe.cjs');
8
+ var piRuntime = require('./piRuntime-DodWS0UI.cjs');
9
9
  var node_crypto = require('node:crypto');
10
10
  var path = require('node:path');
11
11
  var projectPath = require('./projectPath-ChLhdOyt.cjs');
@@ -34,7 +34,7 @@ require('fs');
34
34
  require('node:readline');
35
35
  require('@anthropic-ai/sandbox-runtime');
36
36
  require('expo-server-sdk');
37
- require('./agentGuidance-CJSl54ua.cjs');
37
+ require('./agentGuidance-Bd6GEiYp.cjs');
38
38
  require('ink');
39
39
  require('react');
40
40
  require('@anthropic-ai/claude-agent-sdk');
@@ -555,7 +555,7 @@ function resolveRequestedLegacyModelCode(models, requested) {
555
555
  }
556
556
  return null;
557
557
  }
558
- class GenericAcpPermissionHandler extends index.BasePermissionHandler {
558
+ class GenericAcpPermissionHandler extends index$1.BasePermissionHandler {
559
559
  logPrefix;
560
560
  constructor(session, agentName) {
561
561
  super(session);
@@ -589,17 +589,17 @@ function resolveSessionFlavor(agentName) {
589
589
  async function runAcp(opts) {
590
590
  const verbose = opts.verbose === true;
591
591
  const sessionTag = node_crypto.randomUUID();
592
- api.connectionState.setBackend(opts.agentName);
593
- const api$1 = await api.ApiClient.create(opts.credentials);
592
+ index.connectionState.setBackend(opts.agentName);
593
+ const api = await index.ApiClient.create(opts.credentials);
594
594
  const settings = await persistence.readSettings();
595
595
  if (!settings?.machineId) {
596
596
  throw new Error("No machine ID found in settings");
597
597
  }
598
- await api$1.getOrCreateMachine({
598
+ await api.getOrCreateMachine({
599
599
  machineId: settings.machineId,
600
- metadata: index.initialMachineMetadata
600
+ metadata: index$1.initialMachineMetadata
601
601
  });
602
- const { state, metadata } = index.createSessionMetadata({
602
+ const { state, metadata } = index$1.createSessionMetadata({
603
603
  flavor: resolveSessionFlavor(opts.agentName),
604
604
  ...process.env.VH_TEAM_OPERATION_ID ? { teamOperationId: process.env.VH_TEAM_OPERATION_ID } : {},
605
605
  machineId: settings.machineId,
@@ -607,14 +607,14 @@ async function runAcp(opts) {
607
607
  sandbox: settings.sandboxConfig
608
608
  });
609
609
  metadata.attachmentKinds = [];
610
- const response = await api$1.getOrCreateSession({ tag: sessionTag, metadata, state });
610
+ const response = await api.getOrCreateSession({ tag: sessionTag, metadata, state });
611
611
  if (response) {
612
612
  logAcp("muted", `Happy Session ID: ${response.id}`);
613
613
  }
614
614
  let session;
615
615
  let permissionHandler;
616
- const { session: initialSession, reconnectionHandle } = index.setupOfflineReconnection({
617
- api: api$1,
616
+ const { session: initialSession, reconnectionHandle } = index$1.setupOfflineReconnection({
617
+ api,
618
618
  sessionTag,
619
619
  metadata,
620
620
  state,
@@ -629,7 +629,7 @@ async function runAcp(opts) {
629
629
  session = initialSession;
630
630
  if (response) {
631
631
  try {
632
- await api.notifyDaemonSessionStarted(response.id, metadata, {
632
+ await index.notifyDaemonSessionStarted(response.id, metadata, {
633
633
  encryptionKey: persistence.encodeBase64(response.encryptionKey),
634
634
  encryptionVariant: response.encryptionVariant,
635
635
  seq: response.seq,
@@ -643,11 +643,11 @@ async function runAcp(opts) {
643
643
  permissionHandler = new GenericAcpPermissionHandler(session, opts.agentName);
644
644
  permissionHandler.reset("Previous CLI process exited before responding");
645
645
  const streamingEnabled = process.env.HAPPY_SESSION_STREAM_DISABLED !== "1";
646
- const streamRelay = new index.StreamRelay({
646
+ const streamRelay = new index$1.StreamRelay({
647
647
  send: (frame) => session.sendStreamFrame(frame)
648
648
  });
649
649
  const sessionManager = new AcpSessionManager.AcpSessionManager(streamingEnabled ? { stream: streamRelay } : {});
650
- const messageQueue = new index.MessageQueue2((mode) => index.hashObject(mode));
650
+ const messageQueue = new index$1.MessageQueue2((mode) => index$1.hashObject(mode));
651
651
  let currentPermissionMode;
652
652
  let currentModel;
653
653
  let modeSelector = null;
@@ -668,7 +668,7 @@ async function runAcp(opts) {
668
668
  return true;
669
669
  }
670
670
  try {
671
- index.writeSessionModeFile(session.sessionId, mode);
671
+ index$1.writeSessionModeFile(session.sessionId, mode);
672
672
  } catch (error) {
673
673
  persistence.logger.debug(`[${opts.agentName}] Failed to write session mode file:`, error);
674
674
  return false;
@@ -679,7 +679,7 @@ async function runAcp(opts) {
679
679
  return true;
680
680
  };
681
681
  const isAssistantVariant = process.env.HAPPY_SESSION_VARIANT === "assistant";
682
- const happyServer = await index.startHappyServer(session, {
682
+ const happyServer = await index$1.startHappyServer(session, {
683
683
  assistant: isAssistantVariant,
684
684
  ...opts.agentName === "pi" ? { onContextUsage: (contextUsage) => {
685
685
  session.updateAgentState((state2) => ({ ...state2, contextUsage }));
@@ -767,7 +767,7 @@ async function runAcp(opts) {
767
767
  return;
768
768
  }
769
769
  if (permissionModeIsFileBacked()) {
770
- const mode = index.normalizeAcpPermissionMode(requestedMode);
770
+ const mode = index$1.normalizeAcpPermissionMode(requestedMode);
771
771
  if (!mode) {
772
772
  persistence.logger.debug(`[${opts.agentName}] Ignoring unknown file-backed permission mode request: ${requestedMode}`);
773
773
  return;
@@ -1031,8 +1031,8 @@ async function runAcp(opts) {
1031
1031
  sendEnvelopes(sessionManager.mapMessage(msg));
1032
1032
  };
1033
1033
  backend.onMessage(onBackendMessage);
1034
- const titleGenerator = new index.TitleGenerator(session);
1035
- index.registerAgentAttachmentDownloads(session);
1034
+ const titleGenerator = new index$1.TitleGenerator(session);
1035
+ index$1.registerAgentAttachmentDownloads(session);
1036
1036
  let userMessageDelivery = Promise.resolve();
1037
1037
  session.onUserMessage((message) => {
1038
1038
  const downloads = session.drainAttachmentsForUserMessage();
@@ -1088,7 +1088,7 @@ async function runAcp(opts) {
1088
1088
  if (!fileBackedModeActive) {
1089
1089
  throw new Error(`${opts.agentName} does not support live permission mode changes`);
1090
1090
  }
1091
- const mode = typeof request?.mode === "string" ? index.normalizeAcpPermissionMode(request.mode) : null;
1091
+ const mode = typeof request?.mode === "string" ? index$1.normalizeAcpPermissionMode(request.mode) : null;
1092
1092
  if (!mode) {
1093
1093
  throw new Error("Invalid permission mode");
1094
1094
  }
@@ -1098,7 +1098,7 @@ async function runAcp(opts) {
1098
1098
  return { mode };
1099
1099
  }
1100
1100
  );
1101
- const disposeTermination = index.registerKillSessionHandler(session.rpcHandlerManager, async () => {
1101
+ const disposeTermination = index$1.registerKillSessionHandler(session.rpcHandlerManager, async () => {
1102
1102
  shouldExit = true;
1103
1103
  messageQueue.close();
1104
1104
  clearPendingTurn(new Error("Session terminated"));
@@ -1114,7 +1114,7 @@ async function runAcp(opts) {
1114
1114
  }
1115
1115
  session.updateMetadata((current) => ({
1116
1116
  ...current,
1117
- attachmentKinds: opts.agentName === "pi" && backend.supportsImageAttachments ? [...index.CLAUDE_ATTACHMENT_KINDS] : []
1117
+ attachmentKinds: opts.agentName === "pi" && backend.supportsImageAttachments ? [...index$1.CLAUDE_ATTACHMENT_KINDS] : []
1118
1118
  }));
1119
1119
  if (permissionModeIsFileBacked()) {
1120
1120
  fileBackedModeActive = true;
@@ -1164,13 +1164,13 @@ async function runAcp(opts) {
1164
1164
  }
1165
1165
  const prompt = todoDiscoverySent ? batch.message : `${batch.message}
1166
1166
 
1167
- ${api.BUILTIN_TODO_DISCOVERY}`;
1167
+ ${index.BUILTIN_TODO_DISCOVERY}`;
1168
1168
  const attachments = batch.attachments ?? [];
1169
- const staged = attachments.length ? await index.stageClaudeAttachments(attachments, {
1169
+ const staged = attachments.length ? await index$1.stageClaudeAttachments(attachments, {
1170
1170
  happyHomeDir: persistence.configuration.happyHomeDir,
1171
1171
  sessionId: session.sessionId
1172
1172
  }) : [];
1173
- await backend.sendPrompt(acpSessionId, index.appendStagedAttachmentsToPrompt(prompt, staged), attachments);
1173
+ await backend.sendPrompt(acpSessionId, index$1.appendStagedAttachmentsToPrompt(prompt, staged), attachments);
1174
1174
  todoDiscoverySent = true;
1175
1175
  await turnEnded;
1176
1176
  sendEnvelopes(sessionManager.endTurn(turnCancelled ? "cancelled" : "completed"));
@@ -1208,7 +1208,7 @@ ${api.BUILTIN_TODO_DISCOVERY}`;
1208
1208
  await backend.dispose();
1209
1209
  if (fileBackedPermissionMode) {
1210
1210
  try {
1211
- index.removeSessionModeFile(session.sessionId);
1211
+ index$1.removeSessionModeFile(session.sessionId);
1212
1212
  } catch (error) {
1213
1213
  persistence.logger.debug(`[${opts.agentName}] Failed to remove session mode file:`, error);
1214
1214
  }
@@ -1,14 +1,14 @@
1
1
  import{createRequire as _pkgrollCR}from"node:module";const require=_pkgrollCR(import.meta.url);import chalk from 'chalk';
2
2
  import os, { homedir, userInfo, tmpdir } from 'node:os';
3
3
  import { randomUUID, randomInt, randomBytes, createHash as createHash$1, timingSafeEqual } from 'node:crypto';
4
- import { o as notifyDaemonSessionEvent, q as getProjectPath, j as BUILTIN_TODO_DISCOVERY, r as initializeSandbox, w as wrapCommand, l as contentLogMetadata, I as InvalidateSync, R as RawJSONLinesSchema, m as delay, t as AsyncLock, S as STREAM_DELTA_MAX_CHARS, M as MAX_CHAT_ATTACHMENT_SOURCE_BYTES, u as notifyDaemonClaudeAuthFailed, v as commandOnPath, c as checkIfDaemonRunningAndCleanupStaleState, x as deriveLocalCliUpdateSummary, y as AGENT_VERSION_SOURCES, z as isClaudeSessionId, C as getLocalHappyAgentCredentialPath, D as readLocalHappyAgentCredentials, E as parseExactVersion, F as compareExactVersions, G as extractCompleteLines, H as decideBackfill, J as parseTerminalHookPayload, K as tmuxArgs, L as scrubTmuxClientEnv, N as decideMirrorBinding, O as MIRROR_BACKFILL_LINES_DEFAULT, P as mirrorLineKey, Q as mirrorLocalId, T as listDaemonSessions, U as stopDaemonSession, V as detectCLIAvailability, W as detectResumeSupport, X as isDaemonRunningCurrentlyInstalledHappyVersion, Y as stopDaemon, Z as TurnActivityTracker, _ as summarizeSpawnSessionForLog, $ as shellescape, A as ApiClient, a0 as fetchCliUpdateState, a1 as resolveCliUpdateCheckInterval, a2 as DEFAULT_CLI_UPDATE_CHECK_INTERVAL_MS, a3 as cleanupDaemonState, i as isValidSessionId, s as spawnDaemonSession, a4 as listVhTerminals, a5 as isValidTerminalId, a6 as readVhTerminal, a7 as sendToVhTerminal, a8 as ContextUsageSchema, a9 as TITLE_PROMPT_PREFIX, aa as BOARD_ANALYZER_PROMPT_PREFIX, h as connectionState, ab as startOfflineReconnection, n as notifyDaemonSessionStarted, d as createEnvelope, ac as CodexAppServerClient } from './types-BG4gFjLL.mjs';
5
- import { l as logger, E as ensurePrivateDirectory, F as hardenPrivateFile, c as configuration, p as packageJson, f as readSettings, G as readCredentials, v as credentialRelayProblem, o as readDaemonState, g as encodeBase64, H as readSettingsOutcome, I as updateSettings, J as encodeBase64Url, m as decodeBase64, K as writeCredentialsLegacy, L as writeCredentialsDataKey, d as readCredentialsForConfiguredRelay, j as encrypt, r as readPersistedSessions, w as writePrivateFileSync, M as decryptWithDataKey, N as decryptLegacy, O as persistSession, k as decrypt, h as ensurePrivateDirectorySync, P as acquireDaemonLock, Q as deletePersistedSessions, R as writeDaemonState, S as writeSettings, T as releaseDaemonLock, C as CLIPBOARD_TOOL_NAME, a as CLIPBOARD_TOOL_TITLE, b as CLIPBOARD_TOOL_DESCRIPTION, e as CLIPBOARD_MAX_BYTES, U as clearCredentials, V as clearMachineId, W as SandboxConfigSchema, X as getLatestDaemonLog } from './limits-uABU-yq3.mjs';
4
+ import { v as notifyDaemonSessionEvent, w as getProjectPath, o as BUILTIN_TODO_DISCOVERY, x as initializeSandbox, y as wrapCommand, t as contentLogMetadata, I as InvalidateSync, R as RawJSONLinesSchema, u as delay, z as AsyncLock, S as STREAM_DELTA_MAX_CHARS, M as MAX_CHAT_ATTACHMENT_SOURCE_BYTES, C as notifyDaemonClaudeAuthFailed, D as commandOnPath, c as checkIfDaemonRunningAndCleanupStaleState, E as deriveLocalCliUpdateSummary, F as AGENT_VERSION_SOURCES, G as isClaudeSessionId, H as getLocalHappyAgentCredentialPath, J as readLocalHappyAgentCredentials, K as parseExactVersion, L as compareExactVersions, N as extractCompleteLines, O as decideBackfill, P as parseTerminalHookPayload, Q as tmuxArgs, T as scrubTmuxClientEnv, U as decideMirrorBinding, V as MIRROR_BACKFILL_LINES_DEFAULT, W as mirrorLineKey, X as mirrorLocalId, Y as listDaemonSessions, Z as stopDaemonSession, _ as detectCLIAvailability, $ as detectResumeSupport, a0 as refreshAgentHomes, d as describeAgentHome, a1 as isDaemonRunningCurrentlyInstalledHappyVersion, a2 as stopDaemon, a3 as TurnActivityTracker, a4 as summarizeSpawnSessionForLog, a5 as locateClaudeConversation, a6 as agentHomeSpawnEnv, a7 as shellescape, A as ApiClient, a8 as fetchCliUpdateState, a9 as resolveCliUpdateCheckInterval, aa as DEFAULT_CLI_UPDATE_CHECK_INTERVAL_MS, ab as cleanupDaemonState, i as isValidSessionId, s as spawnDaemonSession, ac as listVhTerminals, ad as isValidTerminalId, ae as readVhTerminal, af as sendToVhTerminal, ag as ContextUsageSchema, ah as TITLE_PROMPT_PREFIX, ai as BOARD_ANALYZER_PROMPT_PREFIX, m as connectionState, aj as startOfflineReconnection, n as notifyDaemonSessionStarted, g as createEnvelope, ak as CodexAppServerClient } from './types-BbvxVQF3.mjs';
5
+ import { l as logger, F as ensurePrivateDirectory, G as hardenPrivateFile, c as configuration, p as packageJson, r as readSettings, H as readCredentials, x as credentialRelayProblem, o as readDaemonState, g as encodeBase64, I as readSettingsOutcome, u as updateSettings, J as encodeBase64Url, m as decodeBase64, K as writeCredentialsLegacy, L as writeCredentialsDataKey, e as readCredentialsForConfiguredRelay, j as encrypt, d as readPersistedSessions, w as writePrivateFileSync, M as decryptWithDataKey, N as decryptLegacy, O as persistSession, k as decrypt, h as ensurePrivateDirectorySync, P as acquireDaemonLock, Q as deletePersistedSessions, R as writeDaemonState, S as writeSettings, T as releaseDaemonLock, C as CLIPBOARD_TOOL_NAME, a as CLIPBOARD_TOOL_TITLE, b as CLIPBOARD_TOOL_DESCRIPTION, f as CLIPBOARD_MAX_BYTES, U as clearCredentials, V as clearMachineId, W as SandboxConfigSchema, X as getLatestDaemonLog } from './limits-CzWD9hWU.mjs';
6
6
  import spawn$1, { spawn } from 'cross-spawn';
7
7
  import path, { join, resolve, basename, isAbsolute, sep, dirname, delimiter, normalize } from 'node:path';
8
8
  import { createInterface } from 'node:readline';
9
9
  import { existsSync, readFileSync, readdirSync, statSync, mkdirSync, unlinkSync, renameSync, writeFileSync, accessSync, constants, openSync, fsyncSync, closeSync, rmSync as rmSync$1, chmodSync as chmodSync$1 } from 'node:fs';
10
10
  import { p as projectPath } from './projectPath-CSpqWdxp.mjs';
11
- import { f as trimIdent, A as AGENT_GUIDANCE, t as teamScopePath, T as TeamConnectionPreflightError, e as createTeamsClient, P as PREVIEW_TOOL_NAME, R as REPORT_PROGRESS_TOOL_NAME, g as TEAM_TOOL_NAMES, r as registerTeamsTools, a as PREVIEW_TOOL_TITLE, b as PREVIEW_TOOL_DESCRIPTION, h as REPORT_PROGRESS_TOOL_TITLE, i as REPORT_PROGRESS_TOOL_DESCRIPTION } from './agentGuidance-BU4hxm8M.mjs';
11
+ import { f as trimIdent, A as AGENT_GUIDANCE, t as teamScopePath, T as TeamConnectionPreflightError, e as createTeamsClient, P as PREVIEW_TOOL_NAME, R as REPORT_PROGRESS_TOOL_NAME, g as TEAM_TOOL_NAMES, r as registerTeamsTools, a as PREVIEW_TOOL_TITLE, b as PREVIEW_TOOL_DESCRIPTION, h as REPORT_PROGRESS_TOOL_TITLE, i as REPORT_PROGRESS_TOOL_DESCRIPTION } from './agentGuidance-HFHrz3C1.mjs';
12
12
  import { readFile, writeFile, rename, unlink, mkdir, symlink, rm, readlink, lstat, stat, open as open$1, appendFile } from 'node:fs/promises';
13
13
  import fs, { watch, access } from 'fs/promises';
14
14
  import { useStdout, useInput, Box, Text, render } from 'ink';
@@ -5294,6 +5294,16 @@ ${typeLabels[type] || type}:`));
5294
5294
  console.log(chalk.gray(" OS-keychain credentials cannot be verified here; see /docs/configuration#claude-credentials."));
5295
5295
  }
5296
5296
  console.log(chalk.gray(" An external claude command is only needed for native terminal/mirror use."));
5297
+ try {
5298
+ const { resolveAgentHomesForCli } = await import('./agentHome-DBqr8rpv.mjs');
5299
+ const { describeAgentHome } = await import('./types-BbvxVQF3.mjs').then(function (n) { return n.al; });
5300
+ const homes = await resolveAgentHomesForCli();
5301
+ console.log(chalk.green(`\u2713 Claude config dir: ${describeAgentHome(homes.claudeConfigDir)}`));
5302
+ console.log(chalk.green(`\u2713 Codex home: ${describeAgentHome(homes.codexHome)}`));
5303
+ console.log(chalk.gray(" Resolved from settings.json, then your login shell, then the daemon environment; pin with `very-happy agent-home`."));
5304
+ } catch {
5305
+ console.log(chalk.yellow("\u25CB Could not resolve the Claude/Codex home directories"));
5306
+ }
5297
5307
  if (availableAgents.length === 0) {
5298
5308
  console.log(chalk.yellow("\u25CB No external agent command found on this daemon PATH"));
5299
5309
  console.log(chalk.gray(" Codex, Gemini, OpenCode, OpenClaw, and native Claude terminal paths need their local command or gateway."));
@@ -10094,6 +10104,12 @@ async function startDaemon() {
10094
10104
  let cliUpdateStateRef = null;
10095
10105
  let lastHandoverHold = null;
10096
10106
  let claudeCredentialStoreSetting = (await readSettings()).claudeCredentialStore === "file" ? "file" : "auto";
10107
+ try {
10108
+ const homes = await refreshAgentHomes();
10109
+ logger.debug(`[DAEMON RUN] Claude config dir: ${describeAgentHome(homes.claudeConfigDir)}; Codex home: ${describeAgentHome(homes.codexHome)}`);
10110
+ } catch (error) {
10111
+ logger.debug("[DAEMON RUN] agent home resolution failed; using the daemon environment as-is", error);
10112
+ }
10097
10113
  let requestShutdown;
10098
10114
  let resolvesWhenShutdownRequested = new Promise((resolve) => {
10099
10115
  requestShutdown = (source, errorMessage) => {
@@ -10259,7 +10275,8 @@ async function startDaemon() {
10259
10275
  }
10260
10276
  };
10261
10277
  const assistantSpawnGate = createSpawnGate();
10262
- const spawnSession = (options) => {
10278
+ const spawnSession = async (options) => {
10279
+ await refreshAgentHomes();
10263
10280
  if (assistantSpawnMode(options) !== "claude-singleton") {
10264
10281
  return spawnSessionImpl(options);
10265
10282
  }
@@ -10332,7 +10349,7 @@ async function startDaemon() {
10332
10349
  s.encryptionVariant
10333
10350
  );
10334
10351
  const claudeSessionId = resolveAssistantClaudeSessionId(s.metadata, serverMetadata);
10335
- const canResumeClaude = !!claudeSessionId && existsSync$1(join$1(getProjectPath(assistantHome()), `${claudeSessionId}.jsonl`));
10352
+ const canResumeClaude = !!claudeSessionId && locateClaudeConversation(assistantHome(), claudeSessionId) !== null;
10336
10353
  return spawnTrackedHappyProcess({
10337
10354
  args: [
10338
10355
  "claude",
@@ -10351,6 +10368,8 @@ async function startDaemon() {
10351
10368
  // B-297: see the resume/restart paths — every spawn carries the
10352
10369
  // credentialStore=file shim, not just fresh sessions (B-276 D8).
10353
10370
  ...claudeAuthServiceRef?.claudeProcessEnvOverrides() ?? {},
10371
+ // B-478: point Claude at the directory the transcript was found in.
10372
+ ...canResumeClaude ? agentHomeSpawnEnv({ workingDirectory: assistantHome(), claudeSessionId }) : {},
10354
10373
  HAPPY_SESSION_VARIANT: "assistant",
10355
10374
  HAPPY_RECONNECT_SESSION_ID: assistantSessionId,
10356
10375
  HAPPY_RECONNECT_ENCRYPTION_KEY: s.encryptionKey,
@@ -10505,6 +10524,7 @@ async function startDaemon() {
10505
10524
  tmuxEnv[key] = value;
10506
10525
  }
10507
10526
  }
10527
+ Object.assign(tmuxEnv, agentHomeSpawnEnv({ workingDirectory: directory, claudeSessionId: options.resumeClaudeSessionId, codexThreadId: options.resumeCodexThreadId }));
10508
10528
  Object.assign(tmuxEnv, extraEnv);
10509
10529
  const tmuxResult = await tmux.spawnInTmux([fullCommand], {
10510
10530
  sessionName: tmuxSessionName,
@@ -10599,6 +10619,9 @@ async function startDaemon() {
10599
10619
  cwd: directory,
10600
10620
  env: {
10601
10621
  ...process.env,
10622
+ // B-478: a fork/duplicate resumes a transcript that may live in
10623
+ // a moved config dir. Explicit environmentVariables still win.
10624
+ ...agentHomeSpawnEnv({ workingDirectory: directory, claudeSessionId: options.resumeClaudeSessionId, codexThreadId: options.resumeCodexThreadId }),
10602
10625
  ...extraEnv
10603
10626
  },
10604
10627
  directoryCreated,
@@ -10749,6 +10772,7 @@ async function startDaemon() {
10749
10772
  gate = createSpawnGate();
10750
10773
  resumeGates.set(happySessionId, gate);
10751
10774
  }
10775
+ await refreshAgentHomes();
10752
10776
  try {
10753
10777
  return await gate.join(() => resumeSessionImpl(happySessionId, options));
10754
10778
  } finally {
@@ -10795,7 +10819,9 @@ async function startDaemon() {
10795
10819
  }
10796
10820
  const precheck = resumePrecheck(metadata, {
10797
10821
  cwdExists: (p) => existsSync$1(p),
10798
- conversationExists: (cwd, claudeSessionId) => existsSync$1(join$1(getProjectPath(cwd), `${claudeSessionId}.jsonl`))
10822
+ // B-478: also looks in every other Claude config dir the user's shell
10823
+ // or settings point at, not just the one the daemon was started with.
10824
+ conversationExists: (cwd, claudeSessionId) => locateClaudeConversation(cwd, claudeSessionId) !== null
10799
10825
  });
10800
10826
  let freshConversation = false;
10801
10827
  if (!precheck.ok) {
@@ -10826,6 +10852,9 @@ async function startDaemon() {
10826
10852
  // fell back to `auto` reads a different credential store than the
10827
10853
  // fresh one next to it (B-276 D8).
10828
10854
  ...claudeAuthServiceRef?.claudeProcessEnvOverrides() ?? {},
10855
+ // B-478: if the transcript lives in a Claude/Codex home other than
10856
+ // the resolved one, this spawn is pointed there.
10857
+ ...freshConversation ? {} : agentHomeSpawnEnv({ workingDirectory: launch.cwd, claudeSessionId: metadata.claudeSessionId, codexThreadId: metadata.codexThreadId }),
10829
10858
  HAPPY_RECONNECT_SESSION_ID: happySessionId,
10830
10859
  HAPPY_RECONNECT_ENCRYPTION_KEY: encodeBase64(tracked.encryption.encryptionKey),
10831
10860
  HAPPY_RECONNECT_ENCRYPTION_VARIANT: tracked.encryption.encryptionVariant,
@@ -10887,6 +10916,7 @@ async function startDaemon() {
10887
10916
  gate = createSpawnGate();
10888
10917
  resumeGates.set(happySessionId, gate);
10889
10918
  }
10919
+ await refreshAgentHomes();
10890
10920
  try {
10891
10921
  return await gate.replace(() => restartSessionImpl(happySessionId, options));
10892
10922
  } finally {
@@ -10922,7 +10952,9 @@ async function startDaemon() {
10922
10952
  }
10923
10953
  const precheck = resumePrecheck(metadata, {
10924
10954
  cwdExists: (p) => existsSync$1(p),
10925
- conversationExists: (cwd2, claudeSessionId) => existsSync$1(join$1(getProjectPath(cwd2), `${claudeSessionId}.jsonl`))
10955
+ // B-478: also looks in every other Claude config dir the user's shell
10956
+ // or settings point at, not just the one the daemon was started with.
10957
+ conversationExists: (cwd2, claudeSessionId) => locateClaudeConversation(cwd2, claudeSessionId) !== null
10926
10958
  });
10927
10959
  let args;
10928
10960
  let cwd;
@@ -10957,6 +10989,8 @@ async function startDaemon() {
10957
10989
  // fell back to `auto` reads a different credential store than the
10958
10990
  // fresh one next to it (B-276 D8).
10959
10991
  ...claudeAuthServiceRef?.claudeProcessEnvOverrides() ?? {},
10992
+ // B-478: see resumeSession.
10993
+ ...precheck.ok ? agentHomeSpawnEnv({ workingDirectory: cwd, claudeSessionId: metadata.claudeSessionId, codexThreadId: metadata.codexThreadId }) : {},
10960
10994
  HAPPY_RECONNECT_SESSION_ID: happySessionId,
10961
10995
  HAPPY_RECONNECT_ENCRYPTION_KEY: encodeBase64(tracked.encryption.encryptionKey),
10962
10996
  HAPPY_RECONNECT_ENCRYPTION_VARIANT: tracked.encryption.encryptionVariant,
@@ -12243,13 +12277,27 @@ function registerKillSessionHandler(rpcHandlerManager, killThisHappy, archiveEve
12243
12277
  }
12244
12278
 
12245
12279
  const SIDE_QUESTION_SYSTEM_PROMPT = [
12246
- "This is a SIDE QUESTION from the user, asked next to the main conversation above.",
12247
- "Answer it directly in a single response, using the conversation context and your own knowledge.",
12248
- "Side questions cannot use tools: do not attempt to read files, run commands, or call tools \u2014 if",
12249
- "the answer would require that, say what you would check and why.",
12250
- "Do NOT continue, resume, or reference progress on the main task; the main conversation is",
12251
- "unaffected by this exchange."
12280
+ "A user message wrapped in a side-question system-reminder is a SIDE QUESTION: answer it",
12281
+ "directly in one response from the conversation context, with no tools and no action on the main task."
12252
12282
  ].join(" ");
12283
+ const SIDE_QUESTION_REMINDER = [
12284
+ "<system-reminder>This is a side question from the user. You must answer this question directly in a single response.",
12285
+ "",
12286
+ "IMPORTANT CONTEXT:",
12287
+ "- You are a separate, lightweight agent spawned to answer this one question",
12288
+ "- The main agent is NOT interrupted - it continues working independently in the background",
12289
+ "- You share the conversation context but are a completely separate instance",
12290
+ '- Do NOT reference being interrupted or what you were "previously doing" - that framing is incorrect',
12291
+ "",
12292
+ "CRITICAL CONSTRAINTS:",
12293
+ "- You have NO tools available - you cannot read files, run commands, search, or take any actions",
12294
+ "- This is a one-off response - there will be no follow-up turns",
12295
+ "- You can ONLY provide information based on what you already know from the conversation context",
12296
+ `- NEVER say things like "Let me try...", "I'll now...", "Let me check...", or promise to take any action`,
12297
+ "- If you don't know the answer, say so - do not offer to look it up or investigate",
12298
+ "",
12299
+ "Simply answer the question with the information you have.</system-reminder>"
12300
+ ].join("\n");
12253
12301
  const MAX_HISTORY_CHARS = 2e3;
12254
12302
  function clip(text, max) {
12255
12303
  return text.length > max ? `${text.slice(0, max)}\u2026` : text;
@@ -12257,14 +12305,17 @@ function clip(text, max) {
12257
12305
  function buildSideQuestionPrompt(question, history = []) {
12258
12306
  const trimmed = question.trim();
12259
12307
  const prior = history.filter((h) => h.question.trim() && h.answer.trim()).slice(-12);
12260
- if (prior.length === 0) return trimmed;
12308
+ const body = `${SIDE_QUESTION_REMINDER}
12309
+
12310
+ ${trimmed}`;
12311
+ if (prior.length === 0) return body;
12261
12312
  const lines = prior.map((h) => `Q: ${clip(h.question.trim(), MAX_HISTORY_CHARS)}
12262
12313
  A: ${clip(h.answer.trim(), MAX_HISTORY_CHARS)}`);
12263
12314
  return `<earlier-side-questions>
12264
12315
  ${lines.join("\n\n")}
12265
12316
  </earlier-side-questions>
12266
12317
 
12267
- ${trimmed}`;
12318
+ ${body}`;
12268
12319
  }
12269
12320
  function sideQuestionQueryOptions(input) {
12270
12321
  return {
@@ -12285,17 +12336,36 @@ function sideQuestionQueryOptions(input) {
12285
12336
  abort: input.signal
12286
12337
  };
12287
12338
  }
12288
- function textFromAssistant(message) {
12289
- if (message.type !== "assistant") return "";
12339
+ function assistantBlocks(message) {
12340
+ if (message.type !== "assistant") return [];
12290
12341
  const content = message.message?.content;
12291
- if (!Array.isArray(content)) return "";
12292
- return content.map((block) => block && typeof block === "object" && block.type === "text" ? String(block.text ?? "") : "").join("");
12342
+ return Array.isArray(content) ? content.filter((b) => Boolean(b) && typeof b === "object") : [];
12343
+ }
12344
+ function textFromAssistant(message) {
12345
+ return assistantBlocks(message).map((block) => block.type === "text" ? String(block.text ?? "") : "").join("");
12346
+ }
12347
+ function toolUseFromAssistant(message) {
12348
+ const block = assistantBlocks(message).find((b) => b.type === "tool_use");
12349
+ return block ? String(block.name ?? "a tool") : null;
12350
+ }
12351
+ function toolAttemptNotice(toolName) {
12352
+ return `(The model tried to call ${toolName} instead of answering directly. Try rephrasing or ask in the main conversation.)`;
12353
+ }
12354
+ function apiErrorFromSystem(message) {
12355
+ if (message.type !== "system") return null;
12356
+ const m = message;
12357
+ if (m.subtype !== "api_error") return null;
12358
+ if (typeof m.error === "string") return m.error;
12359
+ const detail = m.error?.formatted ?? m.error?.message;
12360
+ return typeof detail === "string" && detail ? detail : "API error";
12293
12361
  }
12294
12362
  async function runSideQuestion(query, input) {
12295
12363
  const options = sideQuestionQueryOptions(input);
12296
12364
  const stream = query({ prompt: buildSideQuestionPrompt(input.question, input.history), options });
12297
12365
  let streamed = "";
12298
12366
  let final = "";
12367
+ let toolAttempt = null;
12368
+ let lastApiError = null;
12299
12369
  let resultSeen = false;
12300
12370
  for await (const message of stream) {
12301
12371
  if (message.type === "stream_event") {
@@ -12314,20 +12384,31 @@ async function runSideQuestion(query, input) {
12314
12384
  ${text}` : text;
12315
12385
  input.onText?.(final);
12316
12386
  }
12387
+ toolAttempt ??= toolUseFromAssistant(message);
12388
+ continue;
12389
+ }
12390
+ if (message.type === "system") {
12391
+ lastApiError = apiErrorFromSystem(message) ?? lastApiError;
12317
12392
  continue;
12318
12393
  }
12319
12394
  if (message.type === "result") {
12320
12395
  resultSeen = true;
12321
12396
  const result = message;
12322
12397
  if (result.subtype !== "success") {
12323
- const detail = Array.isArray(result.errors) && result.errors.length > 0 ? String(result.errors[0]) : typeof result.result === "string" && result.result ? result.result : result.subtype ?? "unknown";
12398
+ if (toolAttempt && result.subtype === "error_max_turns") break;
12399
+ const detail = Array.isArray(result.errors) && result.errors.length > 0 ? String(result.errors[0]) : typeof result.result === "string" && result.result ? result.result : lastApiError ?? result.subtype ?? "unknown";
12324
12400
  throw new Error(`Side question failed: ${detail}`);
12325
12401
  }
12326
12402
  if (!final && typeof result.result === "string") final = result.result;
12327
12403
  }
12328
12404
  }
12329
12405
  if (input.signal?.aborted) throw new Error("Side question cancelled");
12330
- if (!resultSeen && !final && !streamed) throw new Error("Side question ended without a result");
12406
+ if (toolAttempt && !final.trim() && !streamed.trim()) {
12407
+ const notice = toolAttemptNotice(toolAttempt);
12408
+ input.onText?.(notice);
12409
+ return { answer: notice, hadContext: Boolean(input.resumeSessionId) };
12410
+ }
12411
+ if (!resultSeen && !final && !streamed) throw new Error(`Side question ended without a result${lastApiError ? `: ${lastApiError}` : ""}`);
12331
12412
  return { answer: final || streamed, hadContext: Boolean(input.resumeSessionId) };
12332
12413
  }
12333
12414
 
@@ -12354,7 +12435,7 @@ function registerSideQuestionHandler(rpc, deps) {
12354
12435
  const retainMs = deps.retainMs ?? SIDE_QUESTION_RETAIN_MS;
12355
12436
  const maxRunMs = deps.maxRunMs ?? SIDE_QUESTION_MAX_RUN_MS;
12356
12437
  const run = deps.run ?? (async (input) => {
12357
- const { query } = await import('./index-PM_SsRpw.mjs');
12438
+ const { query } = await import('./index-CxK0l_t0.mjs');
12358
12439
  return runSideQuestion(query, input);
12359
12440
  });
12360
12441
  const slots = /* @__PURE__ */ new Map();
@@ -12377,7 +12458,12 @@ function registerSideQuestionHandler(rpc, deps) {
12377
12458
  if (!question) throw new Error("Side question is empty");
12378
12459
  if (question.length > SIDE_QUESTION_MAX_CHARS) throw new Error("Side question is too long");
12379
12460
  prune();
12380
- if (active) throw new Error("A side question is already running");
12461
+ if (active) {
12462
+ const stale = active;
12463
+ stale.abort.abort("superseded");
12464
+ finish(stale, "cancelled");
12465
+ logger.debug(`[btw] side question ${stale.requestId} superseded by a new ask`);
12466
+ }
12381
12467
  const resumeSessionId = deps.getClaudeSessionId() ?? null;
12382
12468
  const slot = {
12383
12469
  requestId: randomUUID(),
@@ -17599,7 +17685,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
17599
17685
  return;
17600
17686
  } else if (subcommand === "install-terminal-hooks") {
17601
17687
  try {
17602
- const { installTerminalHooks, parseTerminalHooksArgs, TERMINAL_HOOKS_HELP } = await import('./installTerminalHooks-BGVQqbgq.mjs');
17688
+ const { installTerminalHooks, parseTerminalHooksArgs, TERMINAL_HOOKS_HELP } = await import('./installTerminalHooks-Dq1MFFDQ.mjs');
17603
17689
  const command = parseTerminalHooksArgs(args.slice(1));
17604
17690
  if (command.action === "help") {
17605
17691
  console.log(TERMINAL_HOOKS_HELP);
@@ -17614,9 +17700,18 @@ Conversation history is preserved on the server, but in-flight tool calls are in
17614
17700
  }
17615
17701
  process.exit(1);
17616
17702
  }
17703
+ } else if (subcommand === "agent-home") {
17704
+ try {
17705
+ const { parseAgentHomeArgs, runAgentHomeCommand } = await import('./agentHome-DBqr8rpv.mjs');
17706
+ await runAgentHomeCommand(parseAgentHomeArgs(args.slice(1)));
17707
+ process.exit(0);
17708
+ } catch (error) {
17709
+ console.error(chalk.red("Error:"), error instanceof Error ? error.message : "Unknown error");
17710
+ process.exit(1);
17711
+ }
17617
17712
  } else if (subcommand === "spawn") {
17618
17713
  try {
17619
- const { handleSpawnCommand } = await import('./spawn-wkkxEGdF.mjs');
17714
+ const { handleSpawnCommand } = await import('./spawn-Dcetf5Jt.mjs');
17620
17715
  await handleSpawnCommand(args.slice(1));
17621
17716
  } catch (error) {
17622
17717
  console.error(chalk.red("Error:"), error instanceof Error ? error.message : "Unknown error");
@@ -17628,7 +17723,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
17628
17723
  return;
17629
17724
  } else if (subcommand === "sessions") {
17630
17725
  try {
17631
- const { handleSessionsCommand } = await import('./sessions-DbLubh2N.mjs');
17726
+ const { handleSessionsCommand } = await import('./sessions-CJUEp43_.mjs');
17632
17727
  await handleSessionsCommand(args.slice(1));
17633
17728
  } catch (error) {
17634
17729
  console.error(chalk.red("Error:"), error instanceof Error ? error.message : "Unknown error");
@@ -17640,7 +17735,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
17640
17735
  return;
17641
17736
  } else if (subcommand === "send") {
17642
17737
  try {
17643
- const { handleSendCommand } = await import('./send-CBrJylJc.mjs');
17738
+ const { handleSendCommand } = await import('./send-CPayvXBm.mjs');
17644
17739
  await handleSendCommand(args.slice(1));
17645
17740
  } catch (error) {
17646
17741
  console.error(chalk.red("Error:"), error instanceof Error ? error.message : "Unknown error");
@@ -17746,9 +17841,9 @@ Conversation history is preserved on the server, but in-flight tool calls are in
17746
17841
  if (geminiSubcommand === "project" && args[2] === "set" && args[3]) {
17747
17842
  const projectId = args[3];
17748
17843
  try {
17749
- const { saveGoogleCloudProjectToConfig } = await import('./config-euZ_K5Lo.mjs');
17750
- const { readCredentialsForConfiguredRelay: readCredentialsForConfiguredRelay2 } = await import('./limits-uABU-yq3.mjs').then(function (n) { return n.Y; });
17751
- const { ApiClient: ApiClient2 } = await import('./types-BG4gFjLL.mjs').then(function (n) { return n.ad; });
17844
+ const { saveGoogleCloudProjectToConfig } = await import('./config-B9zAvnGT.mjs');
17845
+ const { readCredentialsForConfiguredRelay: readCredentialsForConfiguredRelay2 } = await import('./limits-CzWD9hWU.mjs').then(function (n) { return n.Y; });
17846
+ const { ApiClient: ApiClient2 } = await import('./types-BbvxVQF3.mjs').then(function (n) { return n.am; });
17752
17847
  let userEmail = void 0;
17753
17848
  try {
17754
17849
  const credentials = await readCredentialsForConfiguredRelay2();
@@ -17779,7 +17874,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
17779
17874
  }
17780
17875
  if (geminiSubcommand === "project" && args[2] === "get") {
17781
17876
  try {
17782
- const { readGeminiLocalConfig } = await import('./config-euZ_K5Lo.mjs');
17877
+ const { readGeminiLocalConfig } = await import('./config-B9zAvnGT.mjs');
17783
17878
  const config = readGeminiLocalConfig();
17784
17879
  if (config.googleCloudProject) {
17785
17880
  console.log(`Current Google Cloud Project: ${config.googleCloudProject}`);
@@ -17819,7 +17914,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
17819
17914
  process.exit(0);
17820
17915
  }
17821
17916
  try {
17822
- const { runGemini } = await import('./runGemini-BMlXIaTL.mjs');
17917
+ const { runGemini } = await import('./runGemini-B-It6K8t.mjs');
17823
17918
  let startedBy = void 0;
17824
17919
  for (let i = 1; i < args.length; i++) {
17825
17920
  if (args[i] === "--started-by") {
@@ -17842,7 +17937,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
17842
17937
  } else if (subcommand === "pi") {
17843
17938
  if (args[1] === "--terminal") {
17844
17939
  try {
17845
- const { runPiTerminal } = await import('./piTerminal-rqKn1_Zy.mjs');
17940
+ const { runPiTerminal } = await import('./piTerminal-BIRroC_N.mjs');
17846
17941
  process.exitCode = await runPiTerminal(args.slice(2));
17847
17942
  } catch (error) {
17848
17943
  console.error(chalk.red("Error:"), error instanceof Error ? error.message : "Unknown error");
@@ -17859,7 +17954,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
17859
17954
  }
17860
17955
  };
17861
17956
  try {
17862
- const { runAcp, resolveAcpAgentConfig } = await import('./index-ZOMC8Gzn.mjs');
17957
+ const { runAcp, resolveAcpAgentConfig } = await import('./index-BzLZu_aF.mjs');
17863
17958
  const parsed = parsePiRunnerArgs(args.slice(1));
17864
17959
  const resolved = resolveAcpAgentConfig(["pi", ...parsed.passthrough]);
17865
17960
  const { credentials } = await authAndSetupMachineIfNeeded();
@@ -17887,7 +17982,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
17887
17982
  return;
17888
17983
  } else if (subcommand === "acp") {
17889
17984
  try {
17890
- const { runAcp, resolveAcpAgentConfig } = await import('./index-ZOMC8Gzn.mjs');
17985
+ const { runAcp, resolveAcpAgentConfig } = await import('./index-BzLZu_aF.mjs');
17891
17986
  let startedBy = void 0;
17892
17987
  let verbose = false;
17893
17988
  const acpArgs = [];
@@ -17927,7 +18022,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
17927
18022
  return;
17928
18023
  } else if (subcommand === "openclaw") {
17929
18024
  try {
17930
- const { runOpenClaw } = await import('./runOpenClaw-CoO5Vp3S.mjs');
18025
+ const { runOpenClaw } = await import('./runOpenClaw-DET6LY2v.mjs');
17931
18026
  let startedBy = void 0;
17932
18027
  let verbose = false;
17933
18028
  let gatewayUrl;
@@ -17978,7 +18073,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
17978
18073
  return;
17979
18074
  } else if (subcommand === "todo") {
17980
18075
  try {
17981
- const { handleTodoCommand } = await import('./todo-DoLkqdBe.mjs');
18076
+ const { handleTodoCommand } = await import('./todo-CV5fwHg_.mjs');
17982
18077
  await handleTodoCommand(args.slice(1));
17983
18078
  } catch (error) {
17984
18079
  console.error(JSON.stringify({ error: error instanceof Error ? error.message : "Todo command failed" }));
@@ -17987,7 +18082,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
17987
18082
  return;
17988
18083
  } else if (subcommand === "teams") {
17989
18084
  try {
17990
- const { handleTeamsCommand } = await import('./teams-BTyVFK3P.mjs');
18085
+ const { handleTeamsCommand } = await import('./teams-CW_Zb2Q1.mjs');
17991
18086
  await handleTeamsCommand(args.slice(1));
17992
18087
  } catch (error) {
17993
18088
  console.error(error instanceof Error ? error.message : "Teams command failed");
@@ -17996,7 +18091,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
17996
18091
  return;
17997
18092
  } else if (subcommand === "mcp" && (args.length === 1 || args.length === 2 && args[1] === "--terminal-tools")) {
17998
18093
  try {
17999
- const { handleMcpCommand } = await import('./mcp-CfbTQXyh.mjs');
18094
+ const { handleMcpCommand } = await import('./mcp-L1Yq25LB.mjs');
18000
18095
  await handleMcpCommand(args[1] === "--terminal-tools");
18001
18096
  } catch (error) {
18002
18097
  process.stderr.write(`[very-happy mcp] Fatal: ${error instanceof Error ? error.message : String(error)}
@@ -18226,6 +18321,8 @@ ${chalk.bold("Usage:")}
18226
18321
  very-happy install-terminal-hooks
18227
18322
  Install optional Claude terminal mirror hooks
18228
18323
  (add --remove to uninstall them)
18324
+ very-happy agent-home Show or pin where Claude Code / Codex keep their
18325
+ conversations on this machine (agent-home --help)
18229
18326
  very-happy connect Connect AI vendor API keys
18230
18327
  very-happy todo Built-in Todos and official agent skill (todo --help)
18231
18328
  very-happy sandbox Configure and manage OS-level sandboxing