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,8 +1,8 @@
1
1
  'use strict';
2
2
 
3
- var persistence = require('./limits-B3hngubn.cjs');
4
- var api = require('./types-Xd_LJRJN.cjs');
5
- var agentGuidance = require('./agentGuidance-Bi8iBjy3.cjs');
3
+ var persistence = require('./limits-C_Sklt--.cjs');
4
+ var index = require('./types-DZ5c-9f3.cjs');
5
+ var agentGuidance = require('./agentGuidance-D1PDVswF.cjs');
6
6
  require('node:fs/promises');
7
7
  require('node:fs');
8
8
  require('node:os');
@@ -42,7 +42,7 @@ async function authenticatedBuiltinTodoClient() {
42
42
  }
43
43
  const credentials = await persistence.readCredentialsForConfiguredRelay();
44
44
  if (!credentials) throw new Error("Sign in to Very Happy with `very-happy auth login` before accessing Todos.");
45
- return api.createBuiltinTodoClient(credentials, { serverUrl: persistence.configuration.serverUrl, clientId: "very-happy-cli-todo" });
45
+ return index.createBuiltinTodoClient(credentials, { serverUrl: persistence.configuration.serverUrl, clientId: "very-happy-cli-todo" });
46
46
  }
47
47
 
48
48
  const TODO_HELP = `very-happy todo \u2014 account-owned built-in Todos (JSON output)
@@ -106,7 +106,7 @@ async function handleTodoCommand(args) {
106
106
  return;
107
107
  }
108
108
  if (command.action === "skill") {
109
- console.log(api.BUILTIN_TODO_SKILL);
109
+ console.log(index.BUILTIN_TODO_SKILL);
110
110
  return;
111
111
  }
112
112
  const client = await authenticatedBuiltinTodoClient();
@@ -1,5 +1,5 @@
1
1
  import axios from 'axios';
2
- import { l as logger, g as encodeBase64, j as encrypt, k as decrypt, m as decodeBase64, c as configuration, o as readDaemonState, q as clearDaemonState, s as decryptBlob, t as prepareClipboardText, u as prepareClipboardHistoryText, f as readSettings, r as readPersistedSessions, v as credentialRelayProblem, p as packageJson, x as readTrackedClaudeSessionIds, y as readTrackedCodexThreadIds, z as libsodiumEncryptForPublicKey, A as libsodiumPublicKeyFromSecretKey, B as getRandomBytes, D as redactLogValue } from './limits-CHsz3Ba-.mjs';
2
+ import { l as logger, g as encodeBase64, j as encrypt, k as decrypt, m as decodeBase64, c as configuration, o as readDaemonState, q as clearDaemonState, s as decryptBlob, t as prepareClipboardText, v as prepareClipboardHistoryText, r as readSettings, d as readPersistedSessions, x as credentialRelayProblem, p as packageJson, y as readTrackedClaudeSessionIds, z as readTrackedCodexThreadIds, A as libsodiumEncryptForPublicKey, B as libsodiumPublicKeyFromSecretKey, D as getRandomBytes, E as redactLogValue } from './limits-DxArdmkZ.mjs';
3
3
  import { EventEmitter } from 'node:events';
4
4
  import { io } from 'socket.io-client';
5
5
  import * as z from 'zod';
@@ -19,7 +19,7 @@ import { join as join$1, isAbsolute, resolve as resolve$1 } from 'node:path';
19
19
  import os$1, { homedir } from 'node:os';
20
20
  import { spawn as spawn$2, spawnSync, execSync as execSync$1 } from 'node:child_process';
21
21
  import * as pty from 'node-pty';
22
- import { existsSync, statSync, writeFileSync, unlinkSync, readFileSync, mkdirSync, accessSync, constants, createReadStream, createWriteStream } from 'node:fs';
22
+ import { statSync, readdirSync, existsSync, writeFileSync, unlinkSync, readFileSync, mkdirSync, accessSync, constants, createReadStream, createWriteStream } from 'node:fs';
23
23
  import { existsSync as existsSync$1 } from 'fs';
24
24
  import tweetnacl from 'tweetnacl';
25
25
  import { createInterface } from 'node:readline';
@@ -1356,6 +1356,40 @@ class RpcHandlerManager {
1356
1356
  }
1357
1357
  }
1358
1358
 
1359
+ function describeSocketAckDrop(drop) {
1360
+ switch (drop.reason) {
1361
+ case "no-ack":
1362
+ return "no ack callback on the frame (re-delivered after a transport close?); response dropped";
1363
+ case "handler-threw":
1364
+ return `handler threw: ${drop.error instanceof Error ? drop.error.message : String(drop.error)}`;
1365
+ case "ack-threw":
1366
+ return `ack callback threw: ${drop.error instanceof Error ? drop.error.message : String(drop.error)}`;
1367
+ }
1368
+ }
1369
+ function safeAck(ack, onDrop) {
1370
+ return (value) => {
1371
+ if (typeof ack !== "function") {
1372
+ onDrop({ reason: "no-ack" });
1373
+ return;
1374
+ }
1375
+ try {
1376
+ ack(value);
1377
+ } catch (error) {
1378
+ onDrop({ reason: "ack-threw", error });
1379
+ }
1380
+ };
1381
+ }
1382
+ async function answerSocketRequest(ack, run, onDrop) {
1383
+ let value;
1384
+ try {
1385
+ value = await run();
1386
+ } catch (error) {
1387
+ onDrop({ reason: "handler-threw", error });
1388
+ return;
1389
+ }
1390
+ safeAck(ack, onDrop)(value);
1391
+ }
1392
+
1359
1393
  function run$1(args, options) {
1360
1394
  const RUNNER_PATH = resolve(join(projectPath(), "scripts", "ripgrep_launcher.cjs"));
1361
1395
  return new Promise((resolve2, reject) => {
@@ -3258,7 +3292,11 @@ class ApiSessionClient extends EventEmitter {
3258
3292
  void this.connectSessionRelay();
3259
3293
  });
3260
3294
  this.socket.on("rpc-request", async (data, callback) => {
3261
- callback(await this.rpcHandlerManager.handleRequest(data));
3295
+ await answerSocketRequest(
3296
+ callback,
3297
+ () => this.rpcHandlerManager.handleRequest(data),
3298
+ (drop) => logger.debug(`[API] RPC ${data?.method} unanswered \u2014 ${describeSocketAckDrop(drop)}`)
3299
+ );
3262
3300
  });
3263
3301
  this.socket.on("disconnect", (reason) => {
3264
3302
  logger.debug(`[API] Socket disconnected: ${reason}`);
@@ -3694,9 +3732,14 @@ class ApiSessionClient extends EventEmitter {
3694
3732
  logger.debug(`[API] Session connected to regional relay ${assignment.relayId}`);
3695
3733
  });
3696
3734
  relaySocket.on("rpc-request", async (data, callback) => {
3697
- callback(await this.rpcHandlerManager.handleRequest(data));
3735
+ await answerSocketRequest(
3736
+ callback,
3737
+ () => this.rpcHandlerManager.handleRequest(data),
3738
+ (drop) => logger.debug(`[API] Relay RPC ${data?.method} unanswered \u2014 ${describeSocketAckDrop(drop)}`)
3739
+ );
3698
3740
  });
3699
- relaySocket.on("session-message-deliver", async (data, callback) => {
3741
+ relaySocket.on("session-message-deliver", async (data, rawCallback) => {
3742
+ const callback = safeAck(rawCallback, (drop) => logger.debug(`[API] session-message-deliver unanswered \u2014 ${describeSocketAckDrop(drop)}`));
3700
3743
  if (data?.sessionId !== this.sessionId || !Array.isArray(data.messages) || data.messages.length === 0 || data.messages.length > 50) {
3701
3744
  callback({ ok: false, error: "Invalid session message request" });
3702
3745
  return;
@@ -4907,17 +4950,315 @@ function scrubTmuxClientEnv(env) {
4907
4950
  return env;
4908
4951
  }
4909
4952
 
4910
- function getClaudeConfigDir() {
4911
- return process.env.CLAUDE_CONFIG_DIR || join$1(homedir(), ".claude");
4953
+ const CLAUDE_CONFIG_DIR_ENV = "CLAUDE_CONFIG_DIR";
4954
+ const CODEX_HOME_ENV = "CODEX_HOME";
4955
+ const AGENT_HOME_ENV_NAMES = [CLAUDE_CONFIG_DIR_ENV, CODEX_HOME_ENV];
4956
+ function expandHomePath(value, homeDir) {
4957
+ const trimmed = value.trim();
4958
+ if (trimmed === "~") return homeDir;
4959
+ if (trimmed.startsWith("~/")) return join$1(homeDir, trimmed.slice(2));
4960
+ return isAbsolute(trimmed) ? trimmed : resolve$1(homeDir, trimmed);
4961
+ }
4962
+ function nonEmpty(value) {
4963
+ const trimmed = value?.trim();
4964
+ return trimmed ? trimmed : null;
4965
+ }
4966
+ function pick(envName, settingValue, input, defaultRelative) {
4967
+ const fromSettings = nonEmpty(settingValue);
4968
+ if (fromSettings) return { path: expandHomePath(fromSettings, input.homeDir), source: "settings" };
4969
+ const fromShell = nonEmpty(input.loginShellEnv?.[envName]);
4970
+ if (fromShell) return { path: expandHomePath(fromShell, input.homeDir), source: "login-shell" };
4971
+ const fromDaemon = nonEmpty(input.daemonEnv[envName]);
4972
+ if (fromDaemon) return { path: expandHomePath(fromDaemon, input.homeDir), source: "daemon-env" };
4973
+ return { path: join$1(input.homeDir, defaultRelative), source: "default" };
4974
+ }
4975
+ function resolveAgentHomes(input) {
4976
+ return {
4977
+ claudeConfigDir: pick(CLAUDE_CONFIG_DIR_ENV, input.settings.claudeConfigDir, input, ".claude"),
4978
+ codexHome: pick(CODEX_HOME_ENV, input.settings.codexHome, input, ".codex")
4979
+ };
4912
4980
  }
4913
- function getClaudeProjectsRoot() {
4914
- return join$1(getClaudeConfigDir(), "projects");
4981
+ function agentHomeEnv(homes) {
4982
+ const env = {};
4983
+ if (homes.claudeConfigDir.source !== "default") env[CLAUDE_CONFIG_DIR_ENV] = homes.claudeConfigDir.path;
4984
+ if (homes.codexHome.source !== "default") env[CODEX_HOME_ENV] = homes.codexHome.path;
4985
+ return env;
4915
4986
  }
4916
- function getProjectPath(workingDirectory) {
4917
- const projectId = resolve$1(workingDirectory).replace(/[^a-zA-Z0-9-]/g, "-");
4918
- return join$1(getClaudeProjectsRoot(), projectId);
4987
+ function claudeProjectDirName(workingDirectory) {
4988
+ return resolve$1(workingDirectory).replace(/[^a-zA-Z0-9-]/g, "-");
4989
+ }
4990
+ function claudeConversationPath(configDir, workingDirectory, claudeSessionId) {
4991
+ return join$1(configDir, "projects", claudeProjectDirName(workingDirectory), `${claudeSessionId}.jsonl`);
4992
+ }
4993
+ function agentHomeCandidates(kind, input, homes = resolveAgentHomes(input)) {
4994
+ const envName = kind === "claude" ? CLAUDE_CONFIG_DIR_ENV : CODEX_HOME_ENV;
4995
+ const resolved = kind === "claude" ? homes.claudeConfigDir : homes.codexHome;
4996
+ const raw = [
4997
+ resolved.path,
4998
+ nonEmpty(kind === "claude" ? input.settings.claudeConfigDir : input.settings.codexHome),
4999
+ nonEmpty(input.loginShellEnv?.[envName]),
5000
+ nonEmpty(input.daemonEnv[envName]),
5001
+ join$1(input.homeDir, kind === "claude" ? ".claude" : ".codex")
5002
+ ];
5003
+ const out = [];
5004
+ for (const value of raw) {
5005
+ if (!value) continue;
5006
+ const expanded = expandHomePath(value, input.homeDir);
5007
+ if (!out.includes(expanded)) out.push(expanded);
5008
+ }
5009
+ return out;
5010
+ }
5011
+ function findClaudeConversation(claudeSessionId, workingDirectory, candidates, fileSize) {
5012
+ let best = null;
5013
+ let bestSize = -1;
5014
+ for (let i = 0; i < candidates.length; i++) {
5015
+ const file = claudeConversationPath(candidates[i], workingDirectory, claudeSessionId);
5016
+ const size = fileSize(file);
5017
+ if (size === null || size <= bestSize) continue;
5018
+ best = { home: candidates[i], file, resolved: i === 0 };
5019
+ bestSize = size;
5020
+ }
5021
+ return best;
5022
+ }
5023
+ function codexRolloutFileMatches(fileName, threadId) {
5024
+ return fileName.startsWith("rollout-") && fileName.endsWith(`-${threadId}.jsonl`);
5025
+ }
5026
+ function findCodexThread(threadId, candidates, listDir) {
5027
+ const digits = /^\d+$/;
5028
+ for (let i = 0; i < candidates.length; i++) {
5029
+ const sessions = join$1(candidates[i], "sessions");
5030
+ for (const year of listDir(sessions).filter((name) => digits.test(name)).sort().reverse()) {
5031
+ for (const month of listDir(join$1(sessions, year)).filter((name) => digits.test(name)).sort().reverse()) {
5032
+ for (const day of listDir(join$1(sessions, year, month)).filter((name) => digits.test(name)).sort().reverse()) {
5033
+ const dayDir = join$1(sessions, year, month, day);
5034
+ const hit = listDir(dayDir).find((name) => codexRolloutFileMatches(name, threadId));
5035
+ if (hit) return { home: candidates[i], file: join$1(dayDir, hit), resolved: i === 0 };
5036
+ }
5037
+ }
5038
+ }
5039
+ }
5040
+ return null;
5041
+ }
5042
+ function describeAgentHome(choice) {
5043
+ const source = {
5044
+ settings: "settings.json",
5045
+ "login-shell": "login shell",
5046
+ "daemon-env": "daemon environment",
5047
+ default: "default"
5048
+ };
5049
+ return `${choice.path} (${source[choice.source]})`;
4919
5050
  }
4920
5051
 
5052
+ const LOGIN_SHELL_ENV_MARKER = "__VH_ENV__";
5053
+ const LOGIN_SHELL_PROBE_TIMEOUT_MS = 3e3;
5054
+ function loginShellProbeScript(names) {
5055
+ const pairs = names.map((name) => `${name} "$${name}"`).join(" ");
5056
+ return `printf '${LOGIN_SHELL_ENV_MARKER}%s=%s\\n' ${pairs}`;
5057
+ }
5058
+ function parseLoginShellEnv(output, names) {
5059
+ const wanted = new Set(names);
5060
+ const env = {};
5061
+ for (const rawLine of output.split(/\r?\n/)) {
5062
+ const at = rawLine.indexOf(LOGIN_SHELL_ENV_MARKER);
5063
+ if (at < 0) continue;
5064
+ const line = rawLine.slice(at + LOGIN_SHELL_ENV_MARKER.length);
5065
+ const eq = line.indexOf("=");
5066
+ if (eq <= 0) continue;
5067
+ const name = line.slice(0, eq);
5068
+ if (!wanted.has(name)) continue;
5069
+ const value = line.slice(eq + 1).trim();
5070
+ env[name] = value ? value : void 0;
5071
+ }
5072
+ return env;
5073
+ }
5074
+ function probeLoginShellEnv(names, options = {}) {
5075
+ const platform = options.platform ?? process.platform;
5076
+ if (platform === "win32") return Promise.resolve(null);
5077
+ const shell = (options.shell ?? process.env.SHELL ?? "").trim() || "/bin/sh";
5078
+ const timeoutMs = options.timeoutMs ?? LOGIN_SHELL_PROBE_TIMEOUT_MS;
5079
+ return new Promise((resolve) => {
5080
+ let stdout = "";
5081
+ let settled = false;
5082
+ const finish = (value) => {
5083
+ if (settled) return;
5084
+ settled = true;
5085
+ clearTimeout(timer);
5086
+ resolve(value);
5087
+ };
5088
+ let child;
5089
+ try {
5090
+ child = spawn$2(shell, ["-l", "-i", "-c", loginShellProbeScript(names)], {
5091
+ stdio: ["ignore", "pipe", "ignore"],
5092
+ env: options.env ?? process.env,
5093
+ windowsHide: true
5094
+ });
5095
+ } catch {
5096
+ resolve(null);
5097
+ return;
5098
+ }
5099
+ const timer = setTimeout(() => {
5100
+ try {
5101
+ child.kill("SIGKILL");
5102
+ } catch {
5103
+ }
5104
+ finish(null);
5105
+ }, timeoutMs);
5106
+ child.stdout?.on("data", (chunk) => {
5107
+ stdout += chunk.toString("utf8");
5108
+ });
5109
+ child.on("error", () => finish(null));
5110
+ child.on("close", () => {
5111
+ finish(stdout.includes(LOGIN_SHELL_ENV_MARKER) ? parseLoginShellEnv(stdout, names) : null);
5112
+ });
5113
+ });
5114
+ }
5115
+
5116
+ const AGENT_HOME_CACHE_MS = 6e4;
5117
+ const AGENT_HOME_FAILURE_CACHE_MS = 5 * 6e4;
5118
+ let cache = null;
5119
+ let inFlight = null;
5120
+ let originalDaemonEnv = null;
5121
+ function snapshotDaemonEnv() {
5122
+ if (!originalDaemonEnv) {
5123
+ originalDaemonEnv = {};
5124
+ for (const name of AGENT_HOME_ENV_NAMES) originalDaemonEnv[name] = process.env[name];
5125
+ }
5126
+ return originalDaemonEnv;
5127
+ }
5128
+ async function load(now) {
5129
+ const settings = await readSettings();
5130
+ const loginShellEnv = await probeLoginShellEnv(AGENT_HOME_ENV_NAMES);
5131
+ const input = {
5132
+ settings: { claudeConfigDir: settings.claudeConfigDir, codexHome: settings.codexHome },
5133
+ daemonEnv: snapshotDaemonEnv(),
5134
+ loginShellEnv,
5135
+ homeDir: homedir()
5136
+ };
5137
+ const homes = resolveAgentHomes(input);
5138
+ return {
5139
+ input,
5140
+ homes,
5141
+ expiresAt: now + (loginShellEnv ? AGENT_HOME_CACHE_MS : AGENT_HOME_FAILURE_CACHE_MS)
5142
+ };
5143
+ }
5144
+ async function refreshAgentHomes(now = Date.now()) {
5145
+ if (cache && cache.expiresAt > now) return cache.homes;
5146
+ if (!inFlight) {
5147
+ inFlight = load(now).finally(() => {
5148
+ inFlight = null;
5149
+ });
5150
+ }
5151
+ let entry;
5152
+ try {
5153
+ entry = await inFlight;
5154
+ } catch (error) {
5155
+ logger.debug("[AGENT HOME] resolve failed, falling back", error);
5156
+ if (cache) return cache.homes;
5157
+ const input = { settings: {}, daemonEnv: snapshotDaemonEnv(), loginShellEnv: null, homeDir: homedir() };
5158
+ return resolveAgentHomes(input);
5159
+ }
5160
+ const previous = cache?.homes;
5161
+ cache = entry;
5162
+ applyAgentHomesToProcessEnv(entry.homes);
5163
+ if (!previous || previous.claudeConfigDir.path !== entry.homes.claudeConfigDir.path || previous.codexHome.path !== entry.homes.codexHome.path) {
5164
+ logger.debug(`[AGENT HOME] Claude config dir: ${describeAgentHome(entry.homes.claudeConfigDir)}; Codex home: ${describeAgentHome(entry.homes.codexHome)}`);
5165
+ }
5166
+ return entry.homes;
5167
+ }
5168
+ function currentAgentHomes() {
5169
+ return cache?.homes ?? null;
5170
+ }
5171
+ function resetAgentHomesCache() {
5172
+ cache = null;
5173
+ inFlight = null;
5174
+ originalDaemonEnv = null;
5175
+ }
5176
+ function applyAgentHomesToProcessEnv(homes) {
5177
+ const overlay = agentHomeEnv(homes);
5178
+ for (const name of AGENT_HOME_ENV_NAMES) {
5179
+ const next = overlay[name];
5180
+ if (next === void 0) {
5181
+ const original = snapshotDaemonEnv()[name];
5182
+ if (original === void 0) delete process.env[name];
5183
+ else process.env[name] = original;
5184
+ } else if (process.env[name] !== next) {
5185
+ process.env[name] = next;
5186
+ }
5187
+ }
5188
+ }
5189
+ function listDirSafe(path) {
5190
+ try {
5191
+ return readdirSync(path);
5192
+ } catch {
5193
+ return [];
5194
+ }
5195
+ }
5196
+ function fileSizeSafe(path) {
5197
+ try {
5198
+ const st = statSync(path);
5199
+ return st.isFile() ? st.size : null;
5200
+ } catch {
5201
+ return null;
5202
+ }
5203
+ }
5204
+ function locateClaudeConversation(workingDirectory, claudeSessionId) {
5205
+ const entry = cache;
5206
+ if (!entry) {
5207
+ const input = { settings: {}, daemonEnv: process.env, loginShellEnv: null, homeDir: homedir() };
5208
+ return findClaudeConversation(claudeSessionId, workingDirectory, agentHomeCandidates("claude", input), fileSizeSafe);
5209
+ }
5210
+ return findClaudeConversation(claudeSessionId, workingDirectory, agentHomeCandidates("claude", entry.input, entry.homes), fileSizeSafe);
5211
+ }
5212
+ function locateCodexThread(codexThreadId) {
5213
+ const entry = cache;
5214
+ const input = entry?.input ?? { settings: {}, daemonEnv: process.env, loginShellEnv: null, homeDir: homedir() };
5215
+ return findCodexThread(codexThreadId, agentHomeCandidates("codex", input, entry?.homes), listDirSafe);
5216
+ }
5217
+ function agentHomeSpawnEnv(input) {
5218
+ const env = {};
5219
+ if (input.claudeSessionId) {
5220
+ const hit = locateClaudeConversation(input.workingDirectory, input.claudeSessionId);
5221
+ if (hit && !hit.resolved) {
5222
+ env[CLAUDE_CONFIG_DIR_ENV] = hit.home;
5223
+ logger.debug(`[AGENT HOME] Claude conversation ${input.claudeSessionId} found under ${hit.home}; overriding ${CLAUDE_CONFIG_DIR_ENV} for this spawn`);
5224
+ }
5225
+ }
5226
+ if (input.codexThreadId) {
5227
+ const hit = locateCodexThread(input.codexThreadId);
5228
+ if (hit && !hit.resolved) {
5229
+ env[CODEX_HOME_ENV] = hit.home;
5230
+ logger.debug(`[AGENT HOME] Codex thread ${input.codexThreadId} found under ${hit.home}; overriding ${CODEX_HOME_ENV} for this spawn`);
5231
+ }
5232
+ }
5233
+ return env;
5234
+ }
5235
+
5236
+ var index = /*#__PURE__*/Object.freeze({
5237
+ __proto__: null,
5238
+ AGENT_HOME_CACHE_MS: AGENT_HOME_CACHE_MS,
5239
+ AGENT_HOME_ENV_NAMES: AGENT_HOME_ENV_NAMES,
5240
+ AGENT_HOME_FAILURE_CACHE_MS: AGENT_HOME_FAILURE_CACHE_MS,
5241
+ CLAUDE_CONFIG_DIR_ENV: CLAUDE_CONFIG_DIR_ENV,
5242
+ CODEX_HOME_ENV: CODEX_HOME_ENV,
5243
+ agentHomeCandidates: agentHomeCandidates,
5244
+ agentHomeEnv: agentHomeEnv,
5245
+ agentHomeSpawnEnv: agentHomeSpawnEnv,
5246
+ claudeConversationPath: claudeConversationPath,
5247
+ claudeProjectDirName: claudeProjectDirName,
5248
+ codexRolloutFileMatches: codexRolloutFileMatches,
5249
+ currentAgentHomes: currentAgentHomes,
5250
+ describeAgentHome: describeAgentHome,
5251
+ expandHomePath: expandHomePath,
5252
+ findClaudeConversation: findClaudeConversation,
5253
+ findCodexThread: findCodexThread,
5254
+ locateClaudeConversation: locateClaudeConversation,
5255
+ locateCodexThread: locateCodexThread,
5256
+ probeLoginShellEnv: probeLoginShellEnv,
5257
+ refreshAgentHomes: refreshAgentHomes,
5258
+ resetAgentHomesCache: resetAgentHomesCache,
5259
+ resolveAgentHomes: resolveAgentHomes
5260
+ });
5261
+
4921
5262
  var xtermHeadless = {};
4922
5263
 
4923
5264
  var hasRequiredXtermHeadless;
@@ -11278,7 +11619,8 @@ class WebTerminalManager {
11278
11619
  return false;
11279
11620
  }
11280
11621
  },
11281
- conversationExists: (cwd, claudeSessionId) => existsSync(join$1(getProjectPath(cwd), `${claudeSessionId}.jsonl`)),
11622
+ // B-478: every Claude config dir the user might have pointed a shell at.
11623
+ conversationExists: (cwd, claudeSessionId) => locateClaudeConversation(cwd, claudeSessionId) !== null,
11282
11624
  // B-273: only consulted for records that were attach terminals.
11283
11625
  // Unbounded: the panel's 50-row cap must not hide a restore target.
11284
11626
  userSessions: record.attachTmux ? this.listUserTmuxSessions(Infinity) : [],
@@ -12628,6 +12970,17 @@ function detectResumeSupport(happyHomeDir = configuration.happyHomeDir) {
12628
12970
  };
12629
12971
  }
12630
12972
 
12973
+ function getClaudeConfigDir() {
12974
+ return process.env.CLAUDE_CONFIG_DIR || join$1(homedir(), ".claude");
12975
+ }
12976
+ function getClaudeProjectsRoot() {
12977
+ return join$1(getClaudeConfigDir(), "projects");
12978
+ }
12979
+ function getProjectPath(workingDirectory) {
12980
+ const projectId = resolve$1(workingDirectory).replace(/[^a-zA-Z0-9-]/g, "-");
12981
+ return join$1(getClaudeProjectsRoot(), projectId);
12982
+ }
12983
+
12631
12984
  const TITLE_PROMPT_PREFIX = "Summarize the SPECIFIC topic/request of this message into a 3-6 word title";
12632
12985
  const BOARD_ANALYZER_PROMPT_PREFIX = "You are a status analyzer for a task board of coding-agent sessions.";
12633
12986
  const VERY_HAPPY_ONE_SHOT_PROMPT_PREFIXES = [
@@ -15729,7 +16082,11 @@ class ApiMachineClient {
15729
16082
  bindRpcRequestHandler(socket, transport) {
15730
16083
  socket.on("rpc-request", async (data, callback) => {
15731
16084
  logger.debugLargeJson(`[API MACHINE] Received RPC request via ${transport}:`, data);
15732
- callback(await this.rpcHandlerManager.handleRequest(data));
16085
+ await answerSocketRequest(
16086
+ callback,
16087
+ () => this.rpcHandlerManager.handleRequest(data),
16088
+ (drop) => logger.debug(`[API MACHINE] RPC ${data?.method} via ${transport} unanswered \u2014 ${describeSocketAckDrop(drop)}`)
16089
+ );
15733
16090
  });
15734
16091
  }
15735
16092
  bindMachineCommandHandlers(socket) {
@@ -16933,4 +17290,4 @@ const RawJSONLinesSchema = z$1.discriminatedUnion("type", [
16933
17290
  }).passthrough()
16934
17291
  ]);
16935
17292
 
16936
- export { shellescape as $, ApiClient as A, BUILTIN_TODO_SKILL as B, getLocalHappyAgentCredentialPath as C, readLocalHappyAgentCredentials as D, parseExactVersion as E, compareExactVersions as F, extractCompleteLines as G, decideBackfill as H, InvalidateSync as I, parseTerminalHookPayload as J, tmuxArgs as K, scrubTmuxClientEnv as L, MAX_CHAT_ATTACHMENT_SOURCE_BYTES as M, decideMirrorBinding as N, MIRROR_BACKFILL_LINES_DEFAULT as O, mirrorLineKey as P, mirrorLocalId as Q, RawJSONLinesSchema as R, STREAM_DELTA_MAX_CHARS as S, listDaemonSessions as T, stopDaemonSession as U, detectCLIAvailability as V, detectResumeSupport as W, isDaemonRunningCurrentlyInstalledHappyVersion as X, stopDaemon as Y, TurnActivityTracker as Z, summarizeSpawnSessionForLog as _, ApiSessionClient as a, fetchCliUpdateState as a0, resolveCliUpdateCheckInterval as a1, DEFAULT_CLI_UPDATE_CHECK_INTERVAL_MS as a2, cleanupDaemonState as a3, listVhTerminals as a4, isValidTerminalId as a5, readVhTerminal as a6, sendToVhTerminal as a7, ContextUsageSchema as a8, TITLE_PROMPT_PREFIX as a9, BOARD_ANALYZER_PROMPT_PREFIX as aa, startOfflineReconnection as ab, CodexAppServerClient as ac, api as ad, streamKeyOf as b, checkIfDaemonRunningAndCleanupStaleState as c, createEnvelope as d, createBuiltinTodoClient as e, pushFilePreviewViaDaemon as f, setTerminalTitleViaDaemon as g, connectionState as h, isValidSessionId as i, BUILTIN_TODO_DISCOVERY as j, errorLogMetadata as k, contentLogMetadata as l, delay as m, notifyDaemonSessionStarted as n, notifyDaemonSessionEvent as o, pushClipboardViaDaemon as p, getProjectPath as q, initializeSandbox as r, spawnDaemonSession as s, AsyncLock as t, notifyDaemonClaudeAuthFailed as u, commandOnPath as v, wrapCommand as w, deriveLocalCliUpdateSummary as x, AGENT_VERSION_SOURCES as y, isClaudeSessionId as z };
17293
+ export { detectResumeSupport as $, ApiClient as A, BUILTIN_TODO_SKILL as B, notifyDaemonClaudeAuthFailed as C, commandOnPath as D, deriveLocalCliUpdateSummary as E, AGENT_VERSION_SOURCES as F, isClaudeSessionId as G, getLocalHappyAgentCredentialPath as H, InvalidateSync as I, readLocalHappyAgentCredentials as J, parseExactVersion as K, compareExactVersions as L, MAX_CHAT_ATTACHMENT_SOURCE_BYTES as M, extractCompleteLines as N, decideBackfill as O, parseTerminalHookPayload as P, tmuxArgs as Q, RawJSONLinesSchema as R, STREAM_DELTA_MAX_CHARS as S, scrubTmuxClientEnv as T, decideMirrorBinding as U, MIRROR_BACKFILL_LINES_DEFAULT as V, mirrorLineKey as W, mirrorLocalId as X, listDaemonSessions as Y, stopDaemonSession as Z, detectCLIAvailability as _, ApiSessionClient as a, refreshAgentHomes as a0, isDaemonRunningCurrentlyInstalledHappyVersion as a1, stopDaemon as a2, TurnActivityTracker as a3, summarizeSpawnSessionForLog as a4, locateClaudeConversation as a5, agentHomeSpawnEnv as a6, shellescape as a7, fetchCliUpdateState as a8, resolveCliUpdateCheckInterval as a9, DEFAULT_CLI_UPDATE_CHECK_INTERVAL_MS as aa, cleanupDaemonState as ab, listVhTerminals as ac, isValidTerminalId as ad, readVhTerminal as ae, sendToVhTerminal as af, ContextUsageSchema as ag, TITLE_PROMPT_PREFIX as ah, BOARD_ANALYZER_PROMPT_PREFIX as ai, startOfflineReconnection as aj, CodexAppServerClient as ak, index as al, api as am, AGENT_HOME_ENV_NAMES as b, checkIfDaemonRunningAndCleanupStaleState as c, describeAgentHome as d, expandHomePath as e, streamKeyOf as f, createEnvelope as g, createBuiltinTodoClient as h, isValidSessionId as i, pushClipboardViaDaemon as j, pushFilePreviewViaDaemon as k, setTerminalTitleViaDaemon as l, connectionState as m, notifyDaemonSessionStarted as n, BUILTIN_TODO_DISCOVERY as o, probeLoginShellEnv as p, errorLogMetadata as q, resolveAgentHomes as r, spawnDaemonSession as s, contentLogMetadata as t, delay as u, notifyDaemonSessionEvent as v, getProjectPath as w, initializeSandbox as x, wrapCommand as y, AsyncLock as z };