very-happy-cli 0.2.142 → 0.2.144

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-D2LqY2to.mjs → AcpBackend-DLsPpWnc.mjs} +2 -2
  2. package/dist/{AcpBackend-DJsqfgjD.cjs → AcpBackend-DssrjZDS.cjs} +30 -30
  3. package/dist/{AcpSessionManager-CdeM5KD9.mjs → AcpSessionManager-1pAH8SdV.mjs} +1 -1
  4. package/dist/{AcpSessionManager-CTfDxziP.cjs → AcpSessionManager-DkBV80Rr.cjs} +9 -9
  5. package/dist/{agentGuidance-Cz8QVcX3.mjs → agentGuidance-CupQ9Lve.mjs} +1 -1
  6. package/dist/{agentGuidance-Bi8iBjy3.cjs → agentGuidance-D1PDVswF.cjs} +1 -1
  7. package/dist/agentHome-BaSxP7lQ.mjs +107 -0
  8. package/dist/agentHome-uf1zs2Fi.cjs +113 -0
  9. package/dist/codex/happyMcpStdioBridge.cjs +2 -2
  10. package/dist/codex/happyMcpStdioBridge.mjs +2 -2
  11. package/dist/{config-ZsBeq10u.mjs → config-CxHoQo52.mjs} +4 -4
  12. package/dist/{config-BIbYBmTd.cjs → config-kx4y9oAI.cjs} +4 -4
  13. package/dist/{index-Bom8mTuS.cjs → index-DIoSNgtt.cjs} +4 -4
  14. package/dist/{index-CYFendNf.mjs → index-Diu81aSC.mjs} +77 -28
  15. package/dist/{index-CSQZhQ0C.cjs → index-Dn0JMM8l.cjs} +250 -201
  16. package/dist/{index-BPTPrjhL.cjs → index-Dox9iD5R.cjs} +31 -31
  17. package/dist/{index-CNARLBax.mjs → index-DxEaiVzX.mjs} +4 -4
  18. package/dist/{index-CY0zmhIp.mjs → index-J6a8OHS6.mjs} +8 -8
  19. package/dist/index.cjs +4 -4
  20. package/dist/index.mjs +4 -4
  21. package/dist/{installTerminalHooks-BPJu2WVz.mjs → installTerminalHooks-BBMGk3q5.mjs} +4 -4
  22. package/dist/{installTerminalHooks-DA7SyFYW.cjs → installTerminalHooks-De7_iOOC.cjs} +4 -4
  23. package/dist/lib.cjs +5 -5
  24. package/dist/lib.mjs +2 -2
  25. package/dist/{limits-B3hngubn.cjs → limits-C_Sklt--.cjs} +7 -7
  26. package/dist/{limits-CHsz3Ba-.mjs → limits-DxArdmkZ.mjs} +8 -8
  27. package/dist/{mcp-BkWBRWFe.mjs → mcp-C1oNnlw5.mjs} +4 -4
  28. package/dist/{mcp-ySrfNOYl.cjs → mcp-xyb8dYIQ.cjs} +9 -9
  29. package/dist/{piRuntime-uX0WHVr4.cjs → piRuntime-3Vbdgv6X.cjs} +2 -2
  30. package/dist/{piRuntime-DBLUyXFr.mjs → piRuntime-CzJdE4z4.mjs} +2 -2
  31. package/dist/{piTerminal-DNr3hkzY.cjs → piTerminal-BFpwVGWr.cjs} +6 -6
  32. package/dist/{piTerminal-Bc3jSCnY.mjs → piTerminal-Do2GiKMN.mjs} +6 -6
  33. package/dist/{runGemini-eJ08cXk7.cjs → runGemini-CCdGxTF2.cjs} +24 -24
  34. package/dist/{runGemini-rgFHTnG7.mjs → runGemini-De5NRMT9.mjs} +6 -6
  35. package/dist/{runOpenClaw-GjLWwjas.mjs → runOpenClaw-C2t4DRyi.mjs} +5 -5
  36. package/dist/{runOpenClaw-D0LVzxqM.cjs → runOpenClaw-CRMUfrWk.cjs} +26 -26
  37. package/dist/{send-Bg2oqt7f.cjs → send-BA1Dgpgn.cjs} +4 -4
  38. package/dist/{send-DV8liaRN.mjs → send-l6Rj09c0.mjs} +4 -4
  39. package/dist/{sessions-DPimBZ8H.cjs → sessions-CtVcoXvG.cjs} +5 -5
  40. package/dist/{sessions-JiL4aJkC.mjs → sessions-MWLDqQk-.mjs} +4 -4
  41. package/dist/{spawn-COOcUwkG.cjs → spawn-Be4nsNuQ.cjs} +6 -6
  42. package/dist/{spawn-CnMk3LFG.mjs → spawn-DKWR-6Qc.mjs} +4 -4
  43. package/dist/{teams-DSQgHBLE.cjs → teams-CcjjNLi8.cjs} +4 -4
  44. package/dist/{teams-uHZcdX9j.mjs → teams-DMf9GNGE.mjs} +4 -4
  45. package/dist/{todo-oHWNpEx_.mjs → todo-BEXZRm1A.mjs} +3 -3
  46. package/dist/{todo-DeauuUd6.cjs → todo-EffYAnre.cjs} +5 -5
  47. package/dist/{types-Dnoxgb7G.mjs → types-D6YKR7wo.mjs} +372 -15
  48. package/dist/{types-Xd_LJRJN.cjs → types-DZ5c-9f3.cjs} +379 -13
  49. package/package.json +7 -7
@@ -1,7 +1,7 @@
1
1
  'use strict';
2
2
 
3
3
  var axios = require('axios');
4
- var persistence = require('./limits-B3hngubn.cjs');
4
+ var persistence = require('./limits-C_Sklt--.cjs');
5
5
  var node_events = require('node:events');
6
6
  var socket_ioClient = require('socket.io-client');
7
7
  var z = require('zod');
@@ -1377,6 +1377,40 @@ class RpcHandlerManager {
1377
1377
  }
1378
1378
  }
1379
1379
 
1380
+ function describeSocketAckDrop(drop) {
1381
+ switch (drop.reason) {
1382
+ case "no-ack":
1383
+ return "no ack callback on the frame (re-delivered after a transport close?); response dropped";
1384
+ case "handler-threw":
1385
+ return `handler threw: ${drop.error instanceof Error ? drop.error.message : String(drop.error)}`;
1386
+ case "ack-threw":
1387
+ return `ack callback threw: ${drop.error instanceof Error ? drop.error.message : String(drop.error)}`;
1388
+ }
1389
+ }
1390
+ function safeAck(ack, onDrop) {
1391
+ return (value) => {
1392
+ if (typeof ack !== "function") {
1393
+ onDrop({ reason: "no-ack" });
1394
+ return;
1395
+ }
1396
+ try {
1397
+ ack(value);
1398
+ } catch (error) {
1399
+ onDrop({ reason: "ack-threw", error });
1400
+ }
1401
+ };
1402
+ }
1403
+ async function answerSocketRequest(ack, run, onDrop) {
1404
+ let value;
1405
+ try {
1406
+ value = await run();
1407
+ } catch (error) {
1408
+ onDrop({ reason: "handler-threw", error });
1409
+ return;
1410
+ }
1411
+ safeAck(ack, onDrop)(value);
1412
+ }
1413
+
1380
1414
  function run$1(args, options) {
1381
1415
  const RUNNER_PATH = path.resolve(path.join(projectPath.projectPath(), "scripts", "ripgrep_launcher.cjs"));
1382
1416
  return new Promise((resolve2, reject) => {
@@ -3279,7 +3313,11 @@ class ApiSessionClient extends node_events.EventEmitter {
3279
3313
  void this.connectSessionRelay();
3280
3314
  });
3281
3315
  this.socket.on("rpc-request", async (data, callback) => {
3282
- callback(await this.rpcHandlerManager.handleRequest(data));
3316
+ await answerSocketRequest(
3317
+ callback,
3318
+ () => this.rpcHandlerManager.handleRequest(data),
3319
+ (drop) => persistence.logger.debug(`[API] RPC ${data?.method} unanswered \u2014 ${describeSocketAckDrop(drop)}`)
3320
+ );
3283
3321
  });
3284
3322
  this.socket.on("disconnect", (reason) => {
3285
3323
  persistence.logger.debug(`[API] Socket disconnected: ${reason}`);
@@ -3715,9 +3753,14 @@ class ApiSessionClient extends node_events.EventEmitter {
3715
3753
  persistence.logger.debug(`[API] Session connected to regional relay ${assignment.relayId}`);
3716
3754
  });
3717
3755
  relaySocket.on("rpc-request", async (data, callback) => {
3718
- callback(await this.rpcHandlerManager.handleRequest(data));
3756
+ await answerSocketRequest(
3757
+ callback,
3758
+ () => this.rpcHandlerManager.handleRequest(data),
3759
+ (drop) => persistence.logger.debug(`[API] Relay RPC ${data?.method} unanswered \u2014 ${describeSocketAckDrop(drop)}`)
3760
+ );
3719
3761
  });
3720
- relaySocket.on("session-message-deliver", async (data, callback) => {
3762
+ relaySocket.on("session-message-deliver", async (data, rawCallback) => {
3763
+ const callback = safeAck(rawCallback, (drop) => persistence.logger.debug(`[API] session-message-deliver unanswered \u2014 ${describeSocketAckDrop(drop)}`));
3721
3764
  if (data?.sessionId !== this.sessionId || !Array.isArray(data.messages) || data.messages.length === 0 || data.messages.length > 50) {
3722
3765
  callback({ ok: false, error: "Invalid session message request" });
3723
3766
  return;
@@ -4928,17 +4971,315 @@ function scrubTmuxClientEnv(env) {
4928
4971
  return env;
4929
4972
  }
4930
4973
 
4931
- function getClaudeConfigDir() {
4932
- return process.env.CLAUDE_CONFIG_DIR || path$1.join(os$1.homedir(), ".claude");
4974
+ const CLAUDE_CONFIG_DIR_ENV = "CLAUDE_CONFIG_DIR";
4975
+ const CODEX_HOME_ENV = "CODEX_HOME";
4976
+ const AGENT_HOME_ENV_NAMES = [CLAUDE_CONFIG_DIR_ENV, CODEX_HOME_ENV];
4977
+ function expandHomePath(value, homeDir) {
4978
+ const trimmed = value.trim();
4979
+ if (trimmed === "~") return homeDir;
4980
+ if (trimmed.startsWith("~/")) return path$1.join(homeDir, trimmed.slice(2));
4981
+ return path$1.isAbsolute(trimmed) ? trimmed : path$1.resolve(homeDir, trimmed);
4982
+ }
4983
+ function nonEmpty(value) {
4984
+ const trimmed = value?.trim();
4985
+ return trimmed ? trimmed : null;
4986
+ }
4987
+ function pick(envName, settingValue, input, defaultRelative) {
4988
+ const fromSettings = nonEmpty(settingValue);
4989
+ if (fromSettings) return { path: expandHomePath(fromSettings, input.homeDir), source: "settings" };
4990
+ const fromShell = nonEmpty(input.loginShellEnv?.[envName]);
4991
+ if (fromShell) return { path: expandHomePath(fromShell, input.homeDir), source: "login-shell" };
4992
+ const fromDaemon = nonEmpty(input.daemonEnv[envName]);
4993
+ if (fromDaemon) return { path: expandHomePath(fromDaemon, input.homeDir), source: "daemon-env" };
4994
+ return { path: path$1.join(input.homeDir, defaultRelative), source: "default" };
4995
+ }
4996
+ function resolveAgentHomes(input) {
4997
+ return {
4998
+ claudeConfigDir: pick(CLAUDE_CONFIG_DIR_ENV, input.settings.claudeConfigDir, input, ".claude"),
4999
+ codexHome: pick(CODEX_HOME_ENV, input.settings.codexHome, input, ".codex")
5000
+ };
4933
5001
  }
4934
- function getClaudeProjectsRoot() {
4935
- return path$1.join(getClaudeConfigDir(), "projects");
5002
+ function agentHomeEnv(homes) {
5003
+ const env = {};
5004
+ if (homes.claudeConfigDir.source !== "default") env[CLAUDE_CONFIG_DIR_ENV] = homes.claudeConfigDir.path;
5005
+ if (homes.codexHome.source !== "default") env[CODEX_HOME_ENV] = homes.codexHome.path;
5006
+ return env;
4936
5007
  }
4937
- function getProjectPath(workingDirectory) {
4938
- const projectId = path$1.resolve(workingDirectory).replace(/[^a-zA-Z0-9-]/g, "-");
4939
- return path$1.join(getClaudeProjectsRoot(), projectId);
5008
+ function claudeProjectDirName(workingDirectory) {
5009
+ return path$1.resolve(workingDirectory).replace(/[^a-zA-Z0-9-]/g, "-");
5010
+ }
5011
+ function claudeConversationPath(configDir, workingDirectory, claudeSessionId) {
5012
+ return path$1.join(configDir, "projects", claudeProjectDirName(workingDirectory), `${claudeSessionId}.jsonl`);
5013
+ }
5014
+ function agentHomeCandidates(kind, input, homes = resolveAgentHomes(input)) {
5015
+ const envName = kind === "claude" ? CLAUDE_CONFIG_DIR_ENV : CODEX_HOME_ENV;
5016
+ const resolved = kind === "claude" ? homes.claudeConfigDir : homes.codexHome;
5017
+ const raw = [
5018
+ resolved.path,
5019
+ nonEmpty(kind === "claude" ? input.settings.claudeConfigDir : input.settings.codexHome),
5020
+ nonEmpty(input.loginShellEnv?.[envName]),
5021
+ nonEmpty(input.daemonEnv[envName]),
5022
+ path$1.join(input.homeDir, kind === "claude" ? ".claude" : ".codex")
5023
+ ];
5024
+ const out = [];
5025
+ for (const value of raw) {
5026
+ if (!value) continue;
5027
+ const expanded = expandHomePath(value, input.homeDir);
5028
+ if (!out.includes(expanded)) out.push(expanded);
5029
+ }
5030
+ return out;
5031
+ }
5032
+ function findClaudeConversation(claudeSessionId, workingDirectory, candidates, fileSize) {
5033
+ let best = null;
5034
+ let bestSize = -1;
5035
+ for (let i = 0; i < candidates.length; i++) {
5036
+ const file = claudeConversationPath(candidates[i], workingDirectory, claudeSessionId);
5037
+ const size = fileSize(file);
5038
+ if (size === null || size <= bestSize) continue;
5039
+ best = { home: candidates[i], file, resolved: i === 0 };
5040
+ bestSize = size;
5041
+ }
5042
+ return best;
5043
+ }
5044
+ function codexRolloutFileMatches(fileName, threadId) {
5045
+ return fileName.startsWith("rollout-") && fileName.endsWith(`-${threadId}.jsonl`);
5046
+ }
5047
+ function findCodexThread(threadId, candidates, listDir) {
5048
+ const digits = /^\d+$/;
5049
+ for (let i = 0; i < candidates.length; i++) {
5050
+ const sessions = path$1.join(candidates[i], "sessions");
5051
+ for (const year of listDir(sessions).filter((name) => digits.test(name)).sort().reverse()) {
5052
+ for (const month of listDir(path$1.join(sessions, year)).filter((name) => digits.test(name)).sort().reverse()) {
5053
+ for (const day of listDir(path$1.join(sessions, year, month)).filter((name) => digits.test(name)).sort().reverse()) {
5054
+ const dayDir = path$1.join(sessions, year, month, day);
5055
+ const hit = listDir(dayDir).find((name) => codexRolloutFileMatches(name, threadId));
5056
+ if (hit) return { home: candidates[i], file: path$1.join(dayDir, hit), resolved: i === 0 };
5057
+ }
5058
+ }
5059
+ }
5060
+ }
5061
+ return null;
5062
+ }
5063
+ function describeAgentHome(choice) {
5064
+ const source = {
5065
+ settings: "settings.json",
5066
+ "login-shell": "login shell",
5067
+ "daemon-env": "daemon environment",
5068
+ default: "default"
5069
+ };
5070
+ return `${choice.path} (${source[choice.source]})`;
4940
5071
  }
4941
5072
 
5073
+ const LOGIN_SHELL_ENV_MARKER = "__VH_ENV__";
5074
+ const LOGIN_SHELL_PROBE_TIMEOUT_MS = 3e3;
5075
+ function loginShellProbeScript(names) {
5076
+ const pairs = names.map((name) => `${name} "$${name}"`).join(" ");
5077
+ return `printf '${LOGIN_SHELL_ENV_MARKER}%s=%s\\n' ${pairs}`;
5078
+ }
5079
+ function parseLoginShellEnv(output, names) {
5080
+ const wanted = new Set(names);
5081
+ const env = {};
5082
+ for (const rawLine of output.split(/\r?\n/)) {
5083
+ const at = rawLine.indexOf(LOGIN_SHELL_ENV_MARKER);
5084
+ if (at < 0) continue;
5085
+ const line = rawLine.slice(at + LOGIN_SHELL_ENV_MARKER.length);
5086
+ const eq = line.indexOf("=");
5087
+ if (eq <= 0) continue;
5088
+ const name = line.slice(0, eq);
5089
+ if (!wanted.has(name)) continue;
5090
+ const value = line.slice(eq + 1).trim();
5091
+ env[name] = value ? value : void 0;
5092
+ }
5093
+ return env;
5094
+ }
5095
+ function probeLoginShellEnv(names, options = {}) {
5096
+ const platform = options.platform ?? process.platform;
5097
+ if (platform === "win32") return Promise.resolve(null);
5098
+ const shell = (options.shell ?? process.env.SHELL ?? "").trim() || "/bin/sh";
5099
+ const timeoutMs = options.timeoutMs ?? LOGIN_SHELL_PROBE_TIMEOUT_MS;
5100
+ return new Promise((resolve) => {
5101
+ let stdout = "";
5102
+ let settled = false;
5103
+ const finish = (value) => {
5104
+ if (settled) return;
5105
+ settled = true;
5106
+ clearTimeout(timer);
5107
+ resolve(value);
5108
+ };
5109
+ let child;
5110
+ try {
5111
+ child = node_child_process.spawn(shell, ["-l", "-i", "-c", loginShellProbeScript(names)], {
5112
+ stdio: ["ignore", "pipe", "ignore"],
5113
+ env: options.env ?? process.env,
5114
+ windowsHide: true
5115
+ });
5116
+ } catch {
5117
+ resolve(null);
5118
+ return;
5119
+ }
5120
+ const timer = setTimeout(() => {
5121
+ try {
5122
+ child.kill("SIGKILL");
5123
+ } catch {
5124
+ }
5125
+ finish(null);
5126
+ }, timeoutMs);
5127
+ child.stdout?.on("data", (chunk) => {
5128
+ stdout += chunk.toString("utf8");
5129
+ });
5130
+ child.on("error", () => finish(null));
5131
+ child.on("close", () => {
5132
+ finish(stdout.includes(LOGIN_SHELL_ENV_MARKER) ? parseLoginShellEnv(stdout, names) : null);
5133
+ });
5134
+ });
5135
+ }
5136
+
5137
+ const AGENT_HOME_CACHE_MS = 6e4;
5138
+ const AGENT_HOME_FAILURE_CACHE_MS = 5 * 6e4;
5139
+ let cache = null;
5140
+ let inFlight = null;
5141
+ let originalDaemonEnv = null;
5142
+ function snapshotDaemonEnv() {
5143
+ if (!originalDaemonEnv) {
5144
+ originalDaemonEnv = {};
5145
+ for (const name of AGENT_HOME_ENV_NAMES) originalDaemonEnv[name] = process.env[name];
5146
+ }
5147
+ return originalDaemonEnv;
5148
+ }
5149
+ async function load(now) {
5150
+ const settings = await persistence.readSettings();
5151
+ const loginShellEnv = await probeLoginShellEnv(AGENT_HOME_ENV_NAMES);
5152
+ const input = {
5153
+ settings: { claudeConfigDir: settings.claudeConfigDir, codexHome: settings.codexHome },
5154
+ daemonEnv: snapshotDaemonEnv(),
5155
+ loginShellEnv,
5156
+ homeDir: os$1.homedir()
5157
+ };
5158
+ const homes = resolveAgentHomes(input);
5159
+ return {
5160
+ input,
5161
+ homes,
5162
+ expiresAt: now + (loginShellEnv ? AGENT_HOME_CACHE_MS : AGENT_HOME_FAILURE_CACHE_MS)
5163
+ };
5164
+ }
5165
+ async function refreshAgentHomes(now = Date.now()) {
5166
+ if (cache && cache.expiresAt > now) return cache.homes;
5167
+ if (!inFlight) {
5168
+ inFlight = load(now).finally(() => {
5169
+ inFlight = null;
5170
+ });
5171
+ }
5172
+ let entry;
5173
+ try {
5174
+ entry = await inFlight;
5175
+ } catch (error) {
5176
+ persistence.logger.debug("[AGENT HOME] resolve failed, falling back", error);
5177
+ if (cache) return cache.homes;
5178
+ const input = { settings: {}, daemonEnv: snapshotDaemonEnv(), loginShellEnv: null, homeDir: os$1.homedir() };
5179
+ return resolveAgentHomes(input);
5180
+ }
5181
+ const previous = cache?.homes;
5182
+ cache = entry;
5183
+ applyAgentHomesToProcessEnv(entry.homes);
5184
+ if (!previous || previous.claudeConfigDir.path !== entry.homes.claudeConfigDir.path || previous.codexHome.path !== entry.homes.codexHome.path) {
5185
+ persistence.logger.debug(`[AGENT HOME] Claude config dir: ${describeAgentHome(entry.homes.claudeConfigDir)}; Codex home: ${describeAgentHome(entry.homes.codexHome)}`);
5186
+ }
5187
+ return entry.homes;
5188
+ }
5189
+ function currentAgentHomes() {
5190
+ return cache?.homes ?? null;
5191
+ }
5192
+ function resetAgentHomesCache() {
5193
+ cache = null;
5194
+ inFlight = null;
5195
+ originalDaemonEnv = null;
5196
+ }
5197
+ function applyAgentHomesToProcessEnv(homes) {
5198
+ const overlay = agentHomeEnv(homes);
5199
+ for (const name of AGENT_HOME_ENV_NAMES) {
5200
+ const next = overlay[name];
5201
+ if (next === void 0) {
5202
+ const original = snapshotDaemonEnv()[name];
5203
+ if (original === void 0) delete process.env[name];
5204
+ else process.env[name] = original;
5205
+ } else if (process.env[name] !== next) {
5206
+ process.env[name] = next;
5207
+ }
5208
+ }
5209
+ }
5210
+ function listDirSafe(path) {
5211
+ try {
5212
+ return node_fs.readdirSync(path);
5213
+ } catch {
5214
+ return [];
5215
+ }
5216
+ }
5217
+ function fileSizeSafe(path) {
5218
+ try {
5219
+ const st = node_fs.statSync(path);
5220
+ return st.isFile() ? st.size : null;
5221
+ } catch {
5222
+ return null;
5223
+ }
5224
+ }
5225
+ function locateClaudeConversation(workingDirectory, claudeSessionId) {
5226
+ const entry = cache;
5227
+ if (!entry) {
5228
+ const input = { settings: {}, daemonEnv: process.env, loginShellEnv: null, homeDir: os$1.homedir() };
5229
+ return findClaudeConversation(claudeSessionId, workingDirectory, agentHomeCandidates("claude", input), fileSizeSafe);
5230
+ }
5231
+ return findClaudeConversation(claudeSessionId, workingDirectory, agentHomeCandidates("claude", entry.input, entry.homes), fileSizeSafe);
5232
+ }
5233
+ function locateCodexThread(codexThreadId) {
5234
+ const entry = cache;
5235
+ const input = entry?.input ?? { settings: {}, daemonEnv: process.env, loginShellEnv: null, homeDir: os$1.homedir() };
5236
+ return findCodexThread(codexThreadId, agentHomeCandidates("codex", input, entry?.homes), listDirSafe);
5237
+ }
5238
+ function agentHomeSpawnEnv(input) {
5239
+ const env = {};
5240
+ if (input.claudeSessionId) {
5241
+ const hit = locateClaudeConversation(input.workingDirectory, input.claudeSessionId);
5242
+ if (hit && !hit.resolved) {
5243
+ env[CLAUDE_CONFIG_DIR_ENV] = hit.home;
5244
+ persistence.logger.debug(`[AGENT HOME] Claude conversation ${input.claudeSessionId} found under ${hit.home}; overriding ${CLAUDE_CONFIG_DIR_ENV} for this spawn`);
5245
+ }
5246
+ }
5247
+ if (input.codexThreadId) {
5248
+ const hit = locateCodexThread(input.codexThreadId);
5249
+ if (hit && !hit.resolved) {
5250
+ env[CODEX_HOME_ENV] = hit.home;
5251
+ persistence.logger.debug(`[AGENT HOME] Codex thread ${input.codexThreadId} found under ${hit.home}; overriding ${CODEX_HOME_ENV} for this spawn`);
5252
+ }
5253
+ }
5254
+ return env;
5255
+ }
5256
+
5257
+ var index = /*#__PURE__*/Object.freeze({
5258
+ __proto__: null,
5259
+ AGENT_HOME_CACHE_MS: AGENT_HOME_CACHE_MS,
5260
+ AGENT_HOME_ENV_NAMES: AGENT_HOME_ENV_NAMES,
5261
+ AGENT_HOME_FAILURE_CACHE_MS: AGENT_HOME_FAILURE_CACHE_MS,
5262
+ CLAUDE_CONFIG_DIR_ENV: CLAUDE_CONFIG_DIR_ENV,
5263
+ CODEX_HOME_ENV: CODEX_HOME_ENV,
5264
+ agentHomeCandidates: agentHomeCandidates,
5265
+ agentHomeEnv: agentHomeEnv,
5266
+ agentHomeSpawnEnv: agentHomeSpawnEnv,
5267
+ claudeConversationPath: claudeConversationPath,
5268
+ claudeProjectDirName: claudeProjectDirName,
5269
+ codexRolloutFileMatches: codexRolloutFileMatches,
5270
+ currentAgentHomes: currentAgentHomes,
5271
+ describeAgentHome: describeAgentHome,
5272
+ expandHomePath: expandHomePath,
5273
+ findClaudeConversation: findClaudeConversation,
5274
+ findCodexThread: findCodexThread,
5275
+ locateClaudeConversation: locateClaudeConversation,
5276
+ locateCodexThread: locateCodexThread,
5277
+ probeLoginShellEnv: probeLoginShellEnv,
5278
+ refreshAgentHomes: refreshAgentHomes,
5279
+ resetAgentHomesCache: resetAgentHomesCache,
5280
+ resolveAgentHomes: resolveAgentHomes
5281
+ });
5282
+
4942
5283
  var xtermHeadless = {};
4943
5284
 
4944
5285
  var hasRequiredXtermHeadless;
@@ -11299,7 +11640,8 @@ class WebTerminalManager {
11299
11640
  return false;
11300
11641
  }
11301
11642
  },
11302
- conversationExists: (cwd, claudeSessionId) => node_fs.existsSync(path$1.join(getProjectPath(cwd), `${claudeSessionId}.jsonl`)),
11643
+ // B-478: every Claude config dir the user might have pointed a shell at.
11644
+ conversationExists: (cwd, claudeSessionId) => locateClaudeConversation(cwd, claudeSessionId) !== null,
11303
11645
  // B-273: only consulted for records that were attach terminals.
11304
11646
  // Unbounded: the panel's 50-row cap must not hide a restore target.
11305
11647
  userSessions: record.attachTmux ? this.listUserTmuxSessions(Infinity) : [],
@@ -12649,6 +12991,17 @@ function detectResumeSupport(happyHomeDir = persistence.configuration.happyHomeD
12649
12991
  };
12650
12992
  }
12651
12993
 
12994
+ function getClaudeConfigDir() {
12995
+ return process.env.CLAUDE_CONFIG_DIR || path$1.join(os$1.homedir(), ".claude");
12996
+ }
12997
+ function getClaudeProjectsRoot() {
12998
+ return path$1.join(getClaudeConfigDir(), "projects");
12999
+ }
13000
+ function getProjectPath(workingDirectory) {
13001
+ const projectId = path$1.resolve(workingDirectory).replace(/[^a-zA-Z0-9-]/g, "-");
13002
+ return path$1.join(getClaudeProjectsRoot(), projectId);
13003
+ }
13004
+
12652
13005
  const TITLE_PROMPT_PREFIX = "Summarize the SPECIFIC topic/request of this message into a 3-6 word title";
12653
13006
  const BOARD_ANALYZER_PROMPT_PREFIX = "You are a status analyzer for a task board of coding-agent sessions.";
12654
13007
  const VERY_HAPPY_ONE_SHOT_PROMPT_PREFIXES = [
@@ -15750,7 +16103,11 @@ class ApiMachineClient {
15750
16103
  bindRpcRequestHandler(socket, transport) {
15751
16104
  socket.on("rpc-request", async (data, callback) => {
15752
16105
  persistence.logger.debugLargeJson(`[API MACHINE] Received RPC request via ${transport}:`, data);
15753
- callback(await this.rpcHandlerManager.handleRequest(data));
16106
+ await answerSocketRequest(
16107
+ callback,
16108
+ () => this.rpcHandlerManager.handleRequest(data),
16109
+ (drop) => persistence.logger.debug(`[API MACHINE] RPC ${data?.method} via ${transport} unanswered \u2014 ${describeSocketAckDrop(drop)}`)
16110
+ );
15754
16111
  });
15755
16112
  }
15756
16113
  bindMachineCommandHandlers(socket) {
@@ -16954,6 +17311,7 @@ const RawJSONLinesSchema = z.z.discriminatedUnion("type", [
16954
17311
  }).passthrough()
16955
17312
  ]);
16956
17313
 
17314
+ exports.AGENT_HOME_ENV_NAMES = AGENT_HOME_ENV_NAMES;
16957
17315
  exports.AGENT_VERSION_SOURCES = AGENT_VERSION_SOURCES;
16958
17316
  exports.ApiClient = ApiClient;
16959
17317
  exports.ApiSessionClient = ApiSessionClient;
@@ -16971,6 +17329,7 @@ exports.RawJSONLinesSchema = RawJSONLinesSchema;
16971
17329
  exports.STREAM_DELTA_MAX_CHARS = STREAM_DELTA_MAX_CHARS;
16972
17330
  exports.TITLE_PROMPT_PREFIX = TITLE_PROMPT_PREFIX;
16973
17331
  exports.TurnActivityTracker = TurnActivityTracker;
17332
+ exports.agentHomeSpawnEnv = agentHomeSpawnEnv;
16974
17333
  exports.api = api;
16975
17334
  exports.checkIfDaemonRunningAndCleanupStaleState = checkIfDaemonRunningAndCleanupStaleState;
16976
17335
  exports.cleanupDaemonState = cleanupDaemonState;
@@ -16984,13 +17343,16 @@ exports.decideBackfill = decideBackfill;
16984
17343
  exports.decideMirrorBinding = decideMirrorBinding;
16985
17344
  exports.delay = delay;
16986
17345
  exports.deriveLocalCliUpdateSummary = deriveLocalCliUpdateSummary;
17346
+ exports.describeAgentHome = describeAgentHome;
16987
17347
  exports.detectCLIAvailability = detectCLIAvailability;
16988
17348
  exports.detectResumeSupport = detectResumeSupport;
16989
17349
  exports.errorLogMetadata = errorLogMetadata;
17350
+ exports.expandHomePath = expandHomePath;
16990
17351
  exports.extractCompleteLines = extractCompleteLines;
16991
17352
  exports.fetchCliUpdateState = fetchCliUpdateState;
16992
17353
  exports.getLocalHappyAgentCredentialPath = getLocalHappyAgentCredentialPath;
16993
17354
  exports.getProjectPath = getProjectPath;
17355
+ exports.index = index;
16994
17356
  exports.initializeSandbox = initializeSandbox;
16995
17357
  exports.isClaudeSessionId = isClaudeSessionId;
16996
17358
  exports.isDaemonRunningCurrentlyInstalledHappyVersion = isDaemonRunningCurrentlyInstalledHappyVersion;
@@ -16998,6 +17360,7 @@ exports.isValidSessionId = isValidSessionId;
16998
17360
  exports.isValidTerminalId = isValidTerminalId;
16999
17361
  exports.listDaemonSessions = listDaemonSessions;
17000
17362
  exports.listVhTerminals = listVhTerminals;
17363
+ exports.locateClaudeConversation = locateClaudeConversation;
17001
17364
  exports.mirrorLineKey = mirrorLineKey;
17002
17365
  exports.mirrorLocalId = mirrorLocalId;
17003
17366
  exports.notifyDaemonClaudeAuthFailed = notifyDaemonClaudeAuthFailed;
@@ -17005,10 +17368,13 @@ exports.notifyDaemonSessionEvent = notifyDaemonSessionEvent;
17005
17368
  exports.notifyDaemonSessionStarted = notifyDaemonSessionStarted;
17006
17369
  exports.parseExactVersion = parseExactVersion;
17007
17370
  exports.parseTerminalHookPayload = parseTerminalHookPayload;
17371
+ exports.probeLoginShellEnv = probeLoginShellEnv;
17008
17372
  exports.pushClipboardViaDaemon = pushClipboardViaDaemon;
17009
17373
  exports.pushFilePreviewViaDaemon = pushFilePreviewViaDaemon;
17010
17374
  exports.readLocalHappyAgentCredentials = readLocalHappyAgentCredentials;
17011
17375
  exports.readVhTerminal = readVhTerminal;
17376
+ exports.refreshAgentHomes = refreshAgentHomes;
17377
+ exports.resolveAgentHomes = resolveAgentHomes;
17012
17378
  exports.resolveCliUpdateCheckInterval = resolveCliUpdateCheckInterval;
17013
17379
  exports.scrubTmuxClientEnv = scrubTmuxClientEnv;
17014
17380
  exports.sendToVhTerminal = sendToVhTerminal;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "very-happy-cli",
3
- "version": "0.2.142",
3
+ "version": "0.2.144",
4
4
  "description": "Remote multi-agent workspace CLI with deep Claude integration, native terminal streaming, and self-hosting.",
5
5
  "author": "Kirill Dubovitskiy",
6
6
  "contributors": [
@@ -117,12 +117,12 @@
117
117
  "zod": "^4.0.0"
118
118
  },
119
119
  "optionalDependencies": {
120
- "very-happy-tools-arm64-darwin": "0.2.142",
121
- "very-happy-tools-x64-darwin": "0.2.142",
122
- "very-happy-tools-arm64-linux": "0.2.142",
123
- "very-happy-tools-x64-linux": "0.2.142",
124
- "very-happy-tools-arm64-win32": "0.2.142",
125
- "very-happy-tools-x64-win32": "0.2.142"
120
+ "very-happy-tools-arm64-darwin": "0.2.144",
121
+ "very-happy-tools-x64-darwin": "0.2.144",
122
+ "very-happy-tools-arm64-linux": "0.2.144",
123
+ "very-happy-tools-x64-linux": "0.2.144",
124
+ "very-happy-tools-arm64-win32": "0.2.144",
125
+ "very-happy-tools-x64-win32": "0.2.144"
126
126
  },
127
127
  "devDependencies": {
128
128
  "@slopus/happy-wire": "workspace:*",