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.
- package/dist/{AcpBackend-D2LqY2to.mjs → AcpBackend-DLsPpWnc.mjs} +2 -2
- package/dist/{AcpBackend-DJsqfgjD.cjs → AcpBackend-DssrjZDS.cjs} +30 -30
- package/dist/{AcpSessionManager-CdeM5KD9.mjs → AcpSessionManager-1pAH8SdV.mjs} +1 -1
- package/dist/{AcpSessionManager-CTfDxziP.cjs → AcpSessionManager-DkBV80Rr.cjs} +9 -9
- package/dist/{agentGuidance-Cz8QVcX3.mjs → agentGuidance-CupQ9Lve.mjs} +1 -1
- package/dist/{agentGuidance-Bi8iBjy3.cjs → agentGuidance-D1PDVswF.cjs} +1 -1
- package/dist/agentHome-BaSxP7lQ.mjs +107 -0
- package/dist/agentHome-uf1zs2Fi.cjs +113 -0
- package/dist/codex/happyMcpStdioBridge.cjs +2 -2
- package/dist/codex/happyMcpStdioBridge.mjs +2 -2
- package/dist/{config-ZsBeq10u.mjs → config-CxHoQo52.mjs} +4 -4
- package/dist/{config-BIbYBmTd.cjs → config-kx4y9oAI.cjs} +4 -4
- package/dist/{index-Bom8mTuS.cjs → index-DIoSNgtt.cjs} +4 -4
- package/dist/{index-CYFendNf.mjs → index-Diu81aSC.mjs} +77 -28
- package/dist/{index-CSQZhQ0C.cjs → index-Dn0JMM8l.cjs} +250 -201
- package/dist/{index-BPTPrjhL.cjs → index-Dox9iD5R.cjs} +31 -31
- package/dist/{index-CNARLBax.mjs → index-DxEaiVzX.mjs} +4 -4
- package/dist/{index-CY0zmhIp.mjs → index-J6a8OHS6.mjs} +8 -8
- package/dist/index.cjs +4 -4
- package/dist/index.mjs +4 -4
- package/dist/{installTerminalHooks-BPJu2WVz.mjs → installTerminalHooks-BBMGk3q5.mjs} +4 -4
- package/dist/{installTerminalHooks-DA7SyFYW.cjs → installTerminalHooks-De7_iOOC.cjs} +4 -4
- package/dist/lib.cjs +5 -5
- package/dist/lib.mjs +2 -2
- package/dist/{limits-B3hngubn.cjs → limits-C_Sklt--.cjs} +7 -7
- package/dist/{limits-CHsz3Ba-.mjs → limits-DxArdmkZ.mjs} +8 -8
- package/dist/{mcp-BkWBRWFe.mjs → mcp-C1oNnlw5.mjs} +4 -4
- package/dist/{mcp-ySrfNOYl.cjs → mcp-xyb8dYIQ.cjs} +9 -9
- package/dist/{piRuntime-uX0WHVr4.cjs → piRuntime-3Vbdgv6X.cjs} +2 -2
- package/dist/{piRuntime-DBLUyXFr.mjs → piRuntime-CzJdE4z4.mjs} +2 -2
- package/dist/{piTerminal-DNr3hkzY.cjs → piTerminal-BFpwVGWr.cjs} +6 -6
- package/dist/{piTerminal-Bc3jSCnY.mjs → piTerminal-Do2GiKMN.mjs} +6 -6
- package/dist/{runGemini-eJ08cXk7.cjs → runGemini-CCdGxTF2.cjs} +24 -24
- package/dist/{runGemini-rgFHTnG7.mjs → runGemini-De5NRMT9.mjs} +6 -6
- package/dist/{runOpenClaw-GjLWwjas.mjs → runOpenClaw-C2t4DRyi.mjs} +5 -5
- package/dist/{runOpenClaw-D0LVzxqM.cjs → runOpenClaw-CRMUfrWk.cjs} +26 -26
- package/dist/{send-Bg2oqt7f.cjs → send-BA1Dgpgn.cjs} +4 -4
- package/dist/{send-DV8liaRN.mjs → send-l6Rj09c0.mjs} +4 -4
- package/dist/{sessions-DPimBZ8H.cjs → sessions-CtVcoXvG.cjs} +5 -5
- package/dist/{sessions-JiL4aJkC.mjs → sessions-MWLDqQk-.mjs} +4 -4
- package/dist/{spawn-COOcUwkG.cjs → spawn-Be4nsNuQ.cjs} +6 -6
- package/dist/{spawn-CnMk3LFG.mjs → spawn-DKWR-6Qc.mjs} +4 -4
- package/dist/{teams-DSQgHBLE.cjs → teams-CcjjNLi8.cjs} +4 -4
- package/dist/{teams-uHZcdX9j.mjs → teams-DMf9GNGE.mjs} +4 -4
- package/dist/{todo-oHWNpEx_.mjs → todo-BEXZRm1A.mjs} +3 -3
- package/dist/{todo-DeauuUd6.cjs → todo-EffYAnre.cjs} +5 -5
- package/dist/{types-Dnoxgb7G.mjs → types-D6YKR7wo.mjs} +372 -15
- package/dist/{types-Xd_LJRJN.cjs → types-DZ5c-9f3.cjs} +379 -13
- 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-
|
|
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
|
-
|
|
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
|
-
|
|
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,
|
|
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
|
-
|
|
4932
|
-
|
|
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
|
|
4935
|
-
|
|
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
|
|
4938
|
-
|
|
4939
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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.
|
|
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.
|
|
121
|
-
"very-happy-tools-x64-darwin": "0.2.
|
|
122
|
-
"very-happy-tools-arm64-linux": "0.2.
|
|
123
|
-
"very-happy-tools-x64-linux": "0.2.
|
|
124
|
-
"very-happy-tools-arm64-win32": "0.2.
|
|
125
|
-
"very-happy-tools-x64-win32": "0.2.
|
|
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:*",
|