very-happy-cli 0.2.94 → 0.2.95
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-DoSXb9La.cjs → AcpBackend-BXsbwTbl.cjs} +1 -1
- package/dist/{AcpBackend-Ds4mP02F.mjs → AcpBackend-Cuiff4Nu.mjs} +1 -1
- package/dist/{AcpSessionManager-B6RqjyQS.mjs → AcpSessionManager-BU69q_vR.mjs} +1 -1
- package/dist/{AcpSessionManager-DQ6j5fp4.cjs → AcpSessionManager-BXGmMoe8.cjs} +1 -1
- package/dist/{config-yrZNEia7.mjs → config-2GD21yg_.mjs} +2 -2
- package/dist/{config-IdMPfmwy.cjs → config-BVOE0pni.cjs} +2 -2
- package/dist/{index-bqUSeHWU.cjs → index-BzbaMrIa.cjs} +212 -49
- package/dist/{index-BfCdbWQI.cjs → index-CbPc1iVx.cjs} +4 -4
- package/dist/{index-27948eGz.mjs → index-DVEdpWq0.mjs} +210 -47
- package/dist/{index-DXpQrR4U.mjs → index-DZ0uw6ef.mjs} +5 -5
- package/dist/index.cjs +2 -2
- package/dist/index.mjs +2 -2
- package/dist/{installTerminalHooks-D0gCqzZu.cjs → installTerminalHooks-BrrsyTMd.cjs} +2 -2
- package/dist/{installTerminalHooks-dVZoe8om.mjs → installTerminalHooks-FiujjEvb.mjs} +2 -2
- package/dist/lib.cjs +1 -1
- package/dist/lib.mjs +1 -1
- package/dist/{mcp-BvDgylsM.mjs → mcp-0mZcHPtz.mjs} +2 -2
- package/dist/{mcp-CRcmpUpX.cjs → mcp-ziyMk3eS.cjs} +2 -2
- package/dist/{runGemini-BoVDs_V6.cjs → runGemini-C91O1oxi.cjs} +4 -4
- package/dist/{runGemini-DIAChFOe.mjs → runGemini-D_InkOhk.mjs} +4 -4
- package/dist/{runOpenClaw-Cdsug1sI.cjs → runOpenClaw-B1RRfA1V.cjs} +3 -3
- package/dist/{runOpenClaw-DcC_uOjt.mjs → runOpenClaw-BjebGmV6.mjs} +3 -3
- package/dist/{send-DvDOKQ4V.mjs → send-CxLL0z9J.mjs} +2 -2
- package/dist/{send-DoFm4-OB.cjs → send-DgK6MtgT.cjs} +2 -2
- package/dist/{spawn-C7QRBKkQ.cjs → spawn-Dian7x_g.cjs} +2 -2
- package/dist/{spawn-CEWzROeD.mjs → spawn-uTPD3qOt.mjs} +2 -2
- package/dist/{types-CSOwbjq5.mjs → types-BLE8Hfmh.mjs} +7 -7
- package/dist/{types-CcaZTXxx.cjs → types-HRuZ13LS.cjs} +8 -8
- package/package.json +7 -7
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
var node_child_process = require('node:child_process');
|
|
4
4
|
var sdk = require('@agentclientprotocol/sdk');
|
|
5
5
|
var node_crypto = require('node:crypto');
|
|
6
|
-
var persistence = require('./types-
|
|
6
|
+
var persistence = require('./types-HRuZ13LS.cjs');
|
|
7
7
|
|
|
8
8
|
const DEFAULT_TIMEOUTS = {
|
|
9
9
|
/** Default initialization timeout: 60 seconds */
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { spawn } from 'node:child_process';
|
|
2
2
|
import { ndJsonStream, ClientSideConnection } from '@agentclientprotocol/sdk';
|
|
3
3
|
import { randomUUID } from 'node:crypto';
|
|
4
|
-
import { l as logger, d as contentLogMetadata, e as errorLogMetadata, f as packageJson, g as delay } from './types-
|
|
4
|
+
import { l as logger, d as contentLogMetadata, e as errorLogMetadata, f as packageJson, g as delay } from './types-BLE8Hfmh.mjs';
|
|
5
5
|
|
|
6
6
|
const DEFAULT_TIMEOUTS = {
|
|
7
7
|
/** Default initialization timeout: 60 seconds */
|
|
@@ -2,8 +2,8 @@ import { existsSync, readFileSync, mkdirSync, writeFileSync } from 'fs';
|
|
|
2
2
|
import { join } from 'path';
|
|
3
3
|
import { homedir } from 'os';
|
|
4
4
|
import { execSync } from 'child_process';
|
|
5
|
-
import { l as logger } from './types-
|
|
6
|
-
import { D as DEFAULT_GEMINI_MODEL, G as GEMINI_MODEL_ENV } from './index-
|
|
5
|
+
import { l as logger } from './types-BLE8Hfmh.mjs';
|
|
6
|
+
import { D as DEFAULT_GEMINI_MODEL, G as GEMINI_MODEL_ENV } from './index-DVEdpWq0.mjs';
|
|
7
7
|
import 'axios';
|
|
8
8
|
import 'chalk';
|
|
9
9
|
import 'node:util';
|
|
@@ -4,8 +4,8 @@ var fs = require('fs');
|
|
|
4
4
|
var path = require('path');
|
|
5
5
|
var os = require('os');
|
|
6
6
|
var child_process = require('child_process');
|
|
7
|
-
var persistence = require('./types-
|
|
8
|
-
var index = require('./index-
|
|
7
|
+
var persistence = require('./types-HRuZ13LS.cjs');
|
|
8
|
+
var index = require('./index-BzbaMrIa.cjs');
|
|
9
9
|
require('axios');
|
|
10
10
|
require('chalk');
|
|
11
11
|
require('node:util');
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
var chalk = require('chalk');
|
|
4
4
|
var os = require('node:os');
|
|
5
5
|
var node_crypto = require('node:crypto');
|
|
6
|
-
var persistence = require('./types-
|
|
6
|
+
var persistence = require('./types-HRuZ13LS.cjs');
|
|
7
7
|
var spawn = require('cross-spawn');
|
|
8
8
|
var path = require('node:path');
|
|
9
9
|
var node_readline = require('node:readline');
|
|
@@ -7233,6 +7233,144 @@ function recoverableSessionPid(metadata, liveHappyPids) {
|
|
|
7233
7233
|
const pid = metadata?.hostPid;
|
|
7234
7234
|
return typeof pid === "number" && Number.isInteger(pid) && pid > 0 && liveHappyPids.has(pid) ? pid : null;
|
|
7235
7235
|
}
|
|
7236
|
+
function escapeRegExp(value) {
|
|
7237
|
+
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
7238
|
+
}
|
|
7239
|
+
function sessionAgentConversationId(metadata) {
|
|
7240
|
+
if (!metadata) return null;
|
|
7241
|
+
if (metadata.flavor === "codex") return metadata.codexThreadId ?? null;
|
|
7242
|
+
return metadata.claudeSessionId ?? metadata.codexThreadId ?? null;
|
|
7243
|
+
}
|
|
7244
|
+
function isDaemonWrapperForConversation(command, conversationId) {
|
|
7245
|
+
if (!command || !conversationId) return false;
|
|
7246
|
+
const startedByDaemon = /(?:^|\s)--started-by\s+daemon(?:\s|$)/.test(command);
|
|
7247
|
+
if (!startedByDaemon) return false;
|
|
7248
|
+
const resume = new RegExp(`(?:^|\\s)--resume(?:\\s+|=)${escapeRegExp(conversationId)}(?:\\s|$)`);
|
|
7249
|
+
return resume.test(command);
|
|
7250
|
+
}
|
|
7251
|
+
function findSessionWrapperPids(metadata, liveHappyProcesses, options = {}) {
|
|
7252
|
+
const out = [];
|
|
7253
|
+
const livePids = new Set(liveHappyProcesses.map((p) => p.pid));
|
|
7254
|
+
const lockPid = options.lockPid ?? null;
|
|
7255
|
+
if (lockPid !== null && lockPid !== options.excludePid && livePids.has(lockPid)) out.push(lockPid);
|
|
7256
|
+
const persisted = recoverableSessionPid(metadata, livePids);
|
|
7257
|
+
if (persisted !== null && persisted !== options.excludePid && !out.includes(persisted)) out.push(persisted);
|
|
7258
|
+
const conversationId = sessionAgentConversationId(metadata);
|
|
7259
|
+
if (conversationId) {
|
|
7260
|
+
for (const proc of liveHappyProcesses) {
|
|
7261
|
+
if (proc.pid === options.excludePid || out.includes(proc.pid)) continue;
|
|
7262
|
+
if (isDaemonWrapperForConversation(proc.command, conversationId)) out.push(proc.pid);
|
|
7263
|
+
}
|
|
7264
|
+
}
|
|
7265
|
+
return out;
|
|
7266
|
+
}
|
|
7267
|
+
function mergeRestoreMetadata(stale, reported) {
|
|
7268
|
+
if (!reported) return stale;
|
|
7269
|
+
return { ...stale, ...processIdentityFields(reported) };
|
|
7270
|
+
}
|
|
7271
|
+
|
|
7272
|
+
const SESSION_LOCK_DIR = "session-locks";
|
|
7273
|
+
const defaultRuntime = () => ({
|
|
7274
|
+
dir: path.join(persistence.configuration.happyHomeDir, SESSION_LOCK_DIR),
|
|
7275
|
+
selfPid: process.pid,
|
|
7276
|
+
now: () => Date.now(),
|
|
7277
|
+
signal: (pid, signal) => process.kill(pid, signal),
|
|
7278
|
+
isAlive: (pid) => {
|
|
7279
|
+
try {
|
|
7280
|
+
process.kill(pid, 0);
|
|
7281
|
+
return true;
|
|
7282
|
+
} catch {
|
|
7283
|
+
return false;
|
|
7284
|
+
}
|
|
7285
|
+
},
|
|
7286
|
+
schedule: (callback, delayMs) => {
|
|
7287
|
+
setTimeout(callback, delayMs);
|
|
7288
|
+
}
|
|
7289
|
+
});
|
|
7290
|
+
function sessionLockPath(happySessionId, dir = path.join(persistence.configuration.happyHomeDir, SESSION_LOCK_DIR)) {
|
|
7291
|
+
return path.join(dir, `${happySessionId}.json`);
|
|
7292
|
+
}
|
|
7293
|
+
function readSessionLock(happySessionId, dir) {
|
|
7294
|
+
try {
|
|
7295
|
+
const path = sessionLockPath(happySessionId, dir);
|
|
7296
|
+
if (!node_fs.existsSync(path)) return null;
|
|
7297
|
+
const parsed = JSON.parse(node_fs.readFileSync(path, "utf-8"));
|
|
7298
|
+
if (typeof parsed?.pid !== "number" || !Number.isInteger(parsed.pid) || parsed.pid <= 0) return null;
|
|
7299
|
+
return {
|
|
7300
|
+
pid: parsed.pid,
|
|
7301
|
+
startedAt: typeof parsed.startedAt === "number" ? parsed.startedAt : 0,
|
|
7302
|
+
version: typeof parsed.version === "string" ? parsed.version : "",
|
|
7303
|
+
...typeof parsed.flavor === "string" ? { flavor: parsed.flavor } : {}
|
|
7304
|
+
};
|
|
7305
|
+
} catch {
|
|
7306
|
+
return null;
|
|
7307
|
+
}
|
|
7308
|
+
}
|
|
7309
|
+
function liveSessionLockHolder(happySessionId, runtime = defaultRuntime()) {
|
|
7310
|
+
const record = readSessionLock(happySessionId, runtime.dir);
|
|
7311
|
+
if (!record || record.pid === runtime.selfPid) return null;
|
|
7312
|
+
return runtime.isAlive(record.pid) ? record : null;
|
|
7313
|
+
}
|
|
7314
|
+
function writeSessionLock(happySessionId, record, dir) {
|
|
7315
|
+
node_fs.mkdirSync(dir, { recursive: true, mode: 448 });
|
|
7316
|
+
const path = sessionLockPath(happySessionId, dir);
|
|
7317
|
+
const tmp = `${path}.${record.pid}.tmp`;
|
|
7318
|
+
persistence.writePrivateFileSync(tmp, JSON.stringify(record));
|
|
7319
|
+
node_fs.renameSync(tmp, path);
|
|
7320
|
+
}
|
|
7321
|
+
function acquireSessionLock(happySessionId, options, runtime = defaultRuntime()) {
|
|
7322
|
+
const record = () => ({
|
|
7323
|
+
pid: runtime.selfPid,
|
|
7324
|
+
startedAt: runtime.now(),
|
|
7325
|
+
version: options.version,
|
|
7326
|
+
...options.flavor ? { flavor: options.flavor } : {}
|
|
7327
|
+
});
|
|
7328
|
+
const holder = liveSessionLockHolder(happySessionId, runtime);
|
|
7329
|
+
if (!holder) {
|
|
7330
|
+
writeSessionLock(happySessionId, record(), runtime.dir);
|
|
7331
|
+
return Promise.resolve({ ok: true, replaced: null });
|
|
7332
|
+
}
|
|
7333
|
+
if (!options.takeover) {
|
|
7334
|
+
return Promise.resolve({ ok: false, holder });
|
|
7335
|
+
}
|
|
7336
|
+
return new Promise((resolve) => {
|
|
7337
|
+
const requested = terminateProcess(holder.pid, (stopped) => {
|
|
7338
|
+
if (!stopped) {
|
|
7339
|
+
resolve({ ok: false, holder });
|
|
7340
|
+
return;
|
|
7341
|
+
}
|
|
7342
|
+
writeSessionLock(happySessionId, record(), runtime.dir);
|
|
7343
|
+
resolve({ ok: true, replaced: holder });
|
|
7344
|
+
}, runtime, options.graceMs ?? 2e3);
|
|
7345
|
+
if (!requested) resolve({ ok: false, holder });
|
|
7346
|
+
});
|
|
7347
|
+
}
|
|
7348
|
+
function releaseSessionLock(happySessionId, runtime = defaultRuntime()) {
|
|
7349
|
+
try {
|
|
7350
|
+
const record = readSessionLock(happySessionId, runtime.dir);
|
|
7351
|
+
if (record && record.pid === runtime.selfPid) {
|
|
7352
|
+
node_fs.unlinkSync(sessionLockPath(happySessionId, runtime.dir));
|
|
7353
|
+
}
|
|
7354
|
+
} catch {
|
|
7355
|
+
}
|
|
7356
|
+
}
|
|
7357
|
+
async function claimSessionOrExit(happySessionId, options) {
|
|
7358
|
+
const result = await acquireSessionLock(happySessionId, {
|
|
7359
|
+
takeover: options.takeover,
|
|
7360
|
+
version: persistence.configuration.currentCliVersion,
|
|
7361
|
+
flavor: options.flavor
|
|
7362
|
+
});
|
|
7363
|
+
if (!result.ok) {
|
|
7364
|
+
const message = `Session ${happySessionId} is already run by very-happy pid ${result.holder.pid} (v${result.holder.version || "?"}); this process yields.`;
|
|
7365
|
+
persistence.logger.debug(`[SESSION LOCK] ${message}`);
|
|
7366
|
+
console.error(message);
|
|
7367
|
+
process.exit(0);
|
|
7368
|
+
}
|
|
7369
|
+
if (result.replaced) {
|
|
7370
|
+
persistence.logger.debug(`[SESSION LOCK] Took over session ${happySessionId} from pid ${result.replaced.pid} (v${result.replaced.version || "?"})`);
|
|
7371
|
+
}
|
|
7372
|
+
process.on("exit", () => releaseSessionLock(happySessionId));
|
|
7373
|
+
}
|
|
7236
7374
|
|
|
7237
7375
|
function shellescape(s) {
|
|
7238
7376
|
return "'" + s.replace(/'/g, "'\\''") + "'";
|
|
@@ -7324,7 +7462,7 @@ async function startDaemon() {
|
|
|
7324
7462
|
const pidToTrackedSession = /* @__PURE__ */ new Map();
|
|
7325
7463
|
const sessionIdToFinishedSession = /* @__PURE__ */ new Map();
|
|
7326
7464
|
const persisted = persistence.readPersistedSessions();
|
|
7327
|
-
const
|
|
7465
|
+
const liveHappyProcesses = await findAllHappyProcesses();
|
|
7328
7466
|
for (const [id, s] of Object.entries(persisted)) {
|
|
7329
7467
|
const tracked = {
|
|
7330
7468
|
startedBy: "persisted",
|
|
@@ -7339,12 +7477,20 @@ async function startDaemon() {
|
|
|
7339
7477
|
},
|
|
7340
7478
|
pid: 0
|
|
7341
7479
|
};
|
|
7342
|
-
const
|
|
7343
|
-
if (
|
|
7480
|
+
const livePids = findSessionWrapperPids(s.metadata, liveHappyProcesses, { excludePid: process.pid, lockPid: readSessionLock(id)?.pid });
|
|
7481
|
+
if (livePids.length > 0) {
|
|
7482
|
+
const [livePid, ...duplicates] = livePids;
|
|
7344
7483
|
tracked.pid = livePid;
|
|
7345
7484
|
tracked.startedBy = "recovered after daemon restart";
|
|
7346
7485
|
pidToTrackedSession.set(livePid, tracked);
|
|
7347
|
-
|
|
7486
|
+
if (livePid !== s.metadata?.hostPid) {
|
|
7487
|
+
persistence.logger.debug(`[DAEMON RUN] Session ${id}: persisted hostPid ${s.metadata?.hostPid} is stale; adopted live wrapper ${livePid} by its --resume command line`);
|
|
7488
|
+
}
|
|
7489
|
+
for (const dup of duplicates) {
|
|
7490
|
+
persistence.logger.warn(`[DAEMON RUN] Session ${id} has a duplicate live wrapper ${dup} (kept ${livePid}); restart the session to collapse them`);
|
|
7491
|
+
pidToTrackedSession.set(dup, { ...tracked, pid: dup, startedBy: "recovered after daemon restart (duplicate wrapper)" });
|
|
7492
|
+
}
|
|
7493
|
+
persistence.persistSession(id, { ...s, metadata: { ...s.metadata, hostPid: livePid }, savedAt: Date.now() });
|
|
7348
7494
|
} else {
|
|
7349
7495
|
sessionIdToFinishedSession.set(id, tracked);
|
|
7350
7496
|
}
|
|
@@ -7374,6 +7520,11 @@ async function startDaemon() {
|
|
|
7374
7520
|
savedAt: Date.now()
|
|
7375
7521
|
});
|
|
7376
7522
|
}
|
|
7523
|
+
for (const [otherPid, other] of pidToTrackedSession.entries()) {
|
|
7524
|
+
if (other.happySessionId === sessionId && otherPid !== pid && isPidAlive(otherPid)) {
|
|
7525
|
+
persistence.logger.warn(`[DAEMON RUN] Session ${sessionId} now has two live wrappers (${otherPid} and ${pid}); restart the session to collapse them`);
|
|
7526
|
+
}
|
|
7527
|
+
}
|
|
7377
7528
|
const existingSession = pidToTrackedSession.get(pid);
|
|
7378
7529
|
if (existingSession && existingSession.startedBy === "daemon") {
|
|
7379
7530
|
existingSession.happySessionId = sessionId;
|
|
@@ -7801,6 +7952,21 @@ async function startDaemon() {
|
|
|
7801
7952
|
}
|
|
7802
7953
|
return sessionIdToFinishedSession.get(happySessionId);
|
|
7803
7954
|
};
|
|
7955
|
+
const persistRestoreRecord = (happySessionId, fallback, metadata) => {
|
|
7956
|
+
const candidates = [...pidToTrackedSession.values()].filter((s) => s.happySessionId === happySessionId && isPidAlive(s.pid));
|
|
7957
|
+
const live = candidates.find((s) => s.childProcess) ?? candidates[0];
|
|
7958
|
+
const encryption = live?.encryption ?? fallback.encryption;
|
|
7959
|
+
if (!encryption) return;
|
|
7960
|
+
persistence.persistSession(happySessionId, {
|
|
7961
|
+
encryptionKey: persistence.encodeBase64(encryption.encryptionKey),
|
|
7962
|
+
encryptionVariant: encryption.encryptionVariant,
|
|
7963
|
+
seq: encryption.seq,
|
|
7964
|
+
metadataVersion: encryption.metadataVersion,
|
|
7965
|
+
agentStateVersion: encryption.agentStateVersion,
|
|
7966
|
+
metadata: mergeRestoreMetadata(metadata, live?.happySessionMetadataFromLocalWebhook),
|
|
7967
|
+
savedAt: Date.now()
|
|
7968
|
+
});
|
|
7969
|
+
};
|
|
7804
7970
|
const fetchServerSessionMetadata = async (sessionId, encryptionKey, encryptionVariant) => {
|
|
7805
7971
|
try {
|
|
7806
7972
|
const byId = await axios.get(`${persistence.configuration.serverUrl}/v1/sessions/${encodeURIComponent(sessionId)}`, {
|
|
@@ -7857,6 +8023,14 @@ async function startDaemon() {
|
|
|
7857
8023
|
if (!tracked) {
|
|
7858
8024
|
return { type: "error", errorMessage: `resume-precheck:not-tracked: Session ${happySessionId} is not tracked by this daemon. It may have been started before the daemon, more than 14 days ago, or on another machine.` };
|
|
7859
8025
|
}
|
|
8026
|
+
const orphans = findSessionWrapperPids(tracked.happySessionMetadataFromLocalWebhook, await findAllHappyProcesses(), { excludePid: process.pid, lockPid: readSessionLock(happySessionId)?.pid }).filter((pid) => isPidAlive(pid) && !pidToTrackedSession.has(pid));
|
|
8027
|
+
if (orphans.length > 0) {
|
|
8028
|
+
for (const pid of orphans) {
|
|
8029
|
+
pidToTrackedSession.set(pid, { ...tracked, pid, startedBy: "adopted untracked wrapper" });
|
|
8030
|
+
}
|
|
8031
|
+
persistence.logger.debug(`[DAEMON RUN] resume ${happySessionId}: adopted untracked live wrapper(s) ${orphans.join(", ")} \u2014 idempotent success`);
|
|
8032
|
+
return { type: "success", sessionId: happySessionId };
|
|
8033
|
+
}
|
|
7860
8034
|
if (!tracked.happySessionMetadataFromLocalWebhook) {
|
|
7861
8035
|
return { type: "error", errorMessage: `resume-precheck:no-metadata: Session ${happySessionId} has no metadata. Cannot resume.` };
|
|
7862
8036
|
}
|
|
@@ -7904,15 +8078,7 @@ async function startDaemon() {
|
|
|
7904
8078
|
}
|
|
7905
8079
|
});
|
|
7906
8080
|
if (result.type === "success") {
|
|
7907
|
-
|
|
7908
|
-
encryptionKey: persistence.encodeBase64(tracked.encryption.encryptionKey),
|
|
7909
|
-
encryptionVariant: tracked.encryption.encryptionVariant,
|
|
7910
|
-
seq: tracked.encryption.seq,
|
|
7911
|
-
metadataVersion: tracked.encryption.metadataVersion,
|
|
7912
|
-
agentStateVersion: tracked.encryption.agentStateVersion,
|
|
7913
|
-
metadata,
|
|
7914
|
-
savedAt: Date.now()
|
|
7915
|
-
});
|
|
8081
|
+
persistRestoreRecord(happySessionId, tracked, metadata);
|
|
7916
8082
|
}
|
|
7917
8083
|
return result;
|
|
7918
8084
|
} catch (error) {
|
|
@@ -7925,17 +8091,18 @@ async function startDaemon() {
|
|
|
7925
8091
|
}
|
|
7926
8092
|
};
|
|
7927
8093
|
const restartCounts = /* @__PURE__ */ new Map();
|
|
7928
|
-
const stopSessionAndWait = (happySessionId, timeoutMs = 8e3) => {
|
|
7929
|
-
|
|
7930
|
-
for (const [
|
|
7931
|
-
if (s.happySessionId === happySessionId && isPidAlive(
|
|
7932
|
-
|
|
7933
|
-
|
|
7934
|
-
|
|
7935
|
-
|
|
7936
|
-
|
|
7937
|
-
|
|
7938
|
-
|
|
8094
|
+
const stopSessionAndWait = async (happySessionId, timeoutMs = 8e3) => {
|
|
8095
|
+
const targets = /* @__PURE__ */ new Set();
|
|
8096
|
+
for (const [pid, s] of pidToTrackedSession.entries()) {
|
|
8097
|
+
if (s.happySessionId === happySessionId && isPidAlive(pid)) targets.add(pid);
|
|
8098
|
+
}
|
|
8099
|
+
const known = findTrackedSessionById(happySessionId)?.happySessionMetadataFromLocalWebhook;
|
|
8100
|
+
for (const pid of findSessionWrapperPids(known, await findAllHappyProcesses(), { excludePid: process.pid, lockPid: readSessionLock(happySessionId)?.pid })) {
|
|
8101
|
+
if (isPidAlive(pid)) targets.add(pid);
|
|
8102
|
+
}
|
|
8103
|
+
if (targets.size === 0) return;
|
|
8104
|
+
persistence.logger.debug(`[DAEMON RUN] restart ${happySessionId}: stopping live wrapper(s) ${[...targets].join(", ")}`);
|
|
8105
|
+
await Promise.all([...targets].map((pid) => new Promise((resolve) => {
|
|
7939
8106
|
let settled = false;
|
|
7940
8107
|
const done = () => {
|
|
7941
8108
|
if (!settled) {
|
|
@@ -7955,7 +8122,7 @@ async function startDaemon() {
|
|
|
7955
8122
|
});
|
|
7956
8123
|
if (!requested) done();
|
|
7957
8124
|
setTimeout(done, timeoutMs).unref?.();
|
|
7958
|
-
});
|
|
8125
|
+
})));
|
|
7959
8126
|
};
|
|
7960
8127
|
const restartSession = async (happySessionId, options) => {
|
|
7961
8128
|
let gate = resumeGates.get(happySessionId);
|
|
@@ -8037,15 +8204,7 @@ async function startDaemon() {
|
|
|
8037
8204
|
}
|
|
8038
8205
|
});
|
|
8039
8206
|
if (result.type === "success") {
|
|
8040
|
-
|
|
8041
|
-
encryptionKey: persistence.encodeBase64(tracked.encryption.encryptionKey),
|
|
8042
|
-
encryptionVariant: tracked.encryption.encryptionVariant,
|
|
8043
|
-
seq: tracked.encryption.seq,
|
|
8044
|
-
metadataVersion: tracked.encryption.metadataVersion,
|
|
8045
|
-
agentStateVersion: tracked.encryption.agentStateVersion,
|
|
8046
|
-
metadata,
|
|
8047
|
-
savedAt: Date.now()
|
|
8048
|
-
});
|
|
8207
|
+
persistRestoreRecord(happySessionId, tracked, metadata);
|
|
8049
8208
|
}
|
|
8050
8209
|
return result;
|
|
8051
8210
|
} catch (error) {
|
|
@@ -9277,7 +9436,7 @@ const MAX_TITLE_CHARS = 60;
|
|
|
9277
9436
|
const GENERATION_TIMEOUT_MS = 3e4;
|
|
9278
9437
|
function resolveClaudeBinary() {
|
|
9279
9438
|
try {
|
|
9280
|
-
const require$1 = node_module.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index-
|
|
9439
|
+
const require$1 = node_module.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index-BzbaMrIa.cjs', document.baseURI).href)));
|
|
9281
9440
|
const utilsPath = path.resolve(path.join(persistence.projectPath(), "scripts", "claude_version_utils.cjs"));
|
|
9282
9441
|
const { getClaudeCliPath } = require$1(utilsPath);
|
|
9283
9442
|
const path$1 = getClaudeCliPath();
|
|
@@ -9814,6 +9973,7 @@ async function runClaude(credentials, options = {}) {
|
|
|
9814
9973
|
process.exit(0);
|
|
9815
9974
|
}
|
|
9816
9975
|
persistence.logger.debug(`Session created: ${response.id}`);
|
|
9976
|
+
await claimSessionOrExit(response.id, { takeover: !!reconnectSessionId, flavor: "claude" });
|
|
9817
9977
|
if (reconnectSessionId && !await api.reactivateSession(response.id)) {
|
|
9818
9978
|
throw new Error(`Failed to reactivate archived session ${response.id}`);
|
|
9819
9979
|
}
|
|
@@ -11471,9 +11631,9 @@ function resolveLocalSignupBootstrap(configuredMode, configuredInviteCodes, gene
|
|
|
11471
11631
|
};
|
|
11472
11632
|
}
|
|
11473
11633
|
|
|
11474
|
-
const __filename$1 = node_url.fileURLToPath((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index-
|
|
11634
|
+
const __filename$1 = node_url.fileURLToPath((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index-BzbaMrIa.cjs', document.baseURI).href)));
|
|
11475
11635
|
const __dirname$1 = path.dirname(__filename$1);
|
|
11476
|
-
const require_ = node_module.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index-
|
|
11636
|
+
const require_ = node_module.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index-BzbaMrIa.cjs', document.baseURI).href)));
|
|
11477
11637
|
const PRISMA_QUERY_ENGINE_FILES = {
|
|
11478
11638
|
"arm64-darwin": "libquery_engine-darwin-arm64.dylib.node",
|
|
11479
11639
|
"x64-darwin": "libquery_engine-darwin.dylib.node",
|
|
@@ -13328,6 +13488,9 @@ async function runCodex(opts) {
|
|
|
13328
13488
|
} else {
|
|
13329
13489
|
response = await api.getOrCreateSession({ tag: sessionTag, metadata, state });
|
|
13330
13490
|
}
|
|
13491
|
+
if (response) {
|
|
13492
|
+
await claimSessionOrExit(response.id, { takeover: !!reconnectSessionId, flavor: "codex" });
|
|
13493
|
+
}
|
|
13331
13494
|
if (reconnectSessionId && response && !await api.reactivateSession(response.id)) {
|
|
13332
13495
|
throw new Error(`Failed to reactivate archived session ${response.id}`);
|
|
13333
13496
|
}
|
|
@@ -14094,7 +14257,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
|
|
|
14094
14257
|
process.exit(0);
|
|
14095
14258
|
} else if (subcommand === "install-terminal-hooks") {
|
|
14096
14259
|
try {
|
|
14097
|
-
const { installTerminalHooks, parseTerminalHooksArgs, TERMINAL_HOOKS_HELP } = await Promise.resolve().then(function () { return require('./installTerminalHooks-
|
|
14260
|
+
const { installTerminalHooks, parseTerminalHooksArgs, TERMINAL_HOOKS_HELP } = await Promise.resolve().then(function () { return require('./installTerminalHooks-BrrsyTMd.cjs'); });
|
|
14098
14261
|
const command = parseTerminalHooksArgs(args.slice(1));
|
|
14099
14262
|
if (command.action === "help") {
|
|
14100
14263
|
console.log(TERMINAL_HOOKS_HELP);
|
|
@@ -14111,7 +14274,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
|
|
|
14111
14274
|
}
|
|
14112
14275
|
} else if (subcommand === "spawn") {
|
|
14113
14276
|
try {
|
|
14114
|
-
const { handleSpawnCommand } = await Promise.resolve().then(function () { return require('./spawn-
|
|
14277
|
+
const { handleSpawnCommand } = await Promise.resolve().then(function () { return require('./spawn-Dian7x_g.cjs'); });
|
|
14115
14278
|
await handleSpawnCommand(args.slice(1));
|
|
14116
14279
|
} catch (error) {
|
|
14117
14280
|
console.error(chalk.red("Error:"), error instanceof Error ? error.message : "Unknown error");
|
|
@@ -14123,7 +14286,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
|
|
|
14123
14286
|
return;
|
|
14124
14287
|
} else if (subcommand === "send") {
|
|
14125
14288
|
try {
|
|
14126
|
-
const { handleSendCommand } = await Promise.resolve().then(function () { return require('./send-
|
|
14289
|
+
const { handleSendCommand } = await Promise.resolve().then(function () { return require('./send-DgK6MtgT.cjs'); });
|
|
14127
14290
|
await handleSendCommand(args.slice(1));
|
|
14128
14291
|
} catch (error) {
|
|
14129
14292
|
console.error(chalk.red("Error:"), error instanceof Error ? error.message : "Unknown error");
|
|
@@ -14229,9 +14392,9 @@ Conversation history is preserved on the server, but in-flight tool calls are in
|
|
|
14229
14392
|
if (geminiSubcommand === "project" && args[2] === "set" && args[3]) {
|
|
14230
14393
|
const projectId = args[3];
|
|
14231
14394
|
try {
|
|
14232
|
-
const { saveGoogleCloudProjectToConfig } = await Promise.resolve().then(function () { return require('./config-
|
|
14233
|
-
const { readCredentialsForConfiguredRelay: readCredentialsForConfiguredRelay2 } = await Promise.resolve().then(function () { return require('./types-
|
|
14234
|
-
const { ApiClient: ApiClient2 } = await Promise.resolve().then(function () { return require('./types-
|
|
14395
|
+
const { saveGoogleCloudProjectToConfig } = await Promise.resolve().then(function () { return require('./config-BVOE0pni.cjs'); });
|
|
14396
|
+
const { readCredentialsForConfiguredRelay: readCredentialsForConfiguredRelay2 } = await Promise.resolve().then(function () { return require('./types-HRuZ13LS.cjs'); }).then(function (n) { return n.persistence; });
|
|
14397
|
+
const { ApiClient: ApiClient2 } = await Promise.resolve().then(function () { return require('./types-HRuZ13LS.cjs'); }).then(function (n) { return n.api; });
|
|
14235
14398
|
let userEmail = void 0;
|
|
14236
14399
|
try {
|
|
14237
14400
|
const credentials = await readCredentialsForConfiguredRelay2();
|
|
@@ -14262,7 +14425,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
|
|
|
14262
14425
|
}
|
|
14263
14426
|
if (geminiSubcommand === "project" && args[2] === "get") {
|
|
14264
14427
|
try {
|
|
14265
|
-
const { readGeminiLocalConfig } = await Promise.resolve().then(function () { return require('./config-
|
|
14428
|
+
const { readGeminiLocalConfig } = await Promise.resolve().then(function () { return require('./config-BVOE0pni.cjs'); });
|
|
14266
14429
|
const config = readGeminiLocalConfig();
|
|
14267
14430
|
if (config.googleCloudProject) {
|
|
14268
14431
|
console.log(`Current Google Cloud Project: ${config.googleCloudProject}`);
|
|
@@ -14302,7 +14465,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
|
|
|
14302
14465
|
process.exit(0);
|
|
14303
14466
|
}
|
|
14304
14467
|
try {
|
|
14305
|
-
const { runGemini } = await Promise.resolve().then(function () { return require('./runGemini-
|
|
14468
|
+
const { runGemini } = await Promise.resolve().then(function () { return require('./runGemini-C91O1oxi.cjs'); });
|
|
14306
14469
|
let startedBy = void 0;
|
|
14307
14470
|
for (let i = 1; i < args.length; i++) {
|
|
14308
14471
|
if (args[i] === "--started-by") {
|
|
@@ -14324,7 +14487,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
|
|
|
14324
14487
|
return;
|
|
14325
14488
|
} else if (subcommand === "acp") {
|
|
14326
14489
|
try {
|
|
14327
|
-
const { runAcp, resolveAcpAgentConfig } = await Promise.resolve().then(function () { return require('./index-
|
|
14490
|
+
const { runAcp, resolveAcpAgentConfig } = await Promise.resolve().then(function () { return require('./index-CbPc1iVx.cjs'); });
|
|
14328
14491
|
let startedBy = void 0;
|
|
14329
14492
|
let verbose = false;
|
|
14330
14493
|
const acpArgs = [];
|
|
@@ -14364,7 +14527,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
|
|
|
14364
14527
|
return;
|
|
14365
14528
|
} else if (subcommand === "openclaw") {
|
|
14366
14529
|
try {
|
|
14367
|
-
const { runOpenClaw } = await Promise.resolve().then(function () { return require('./runOpenClaw-
|
|
14530
|
+
const { runOpenClaw } = await Promise.resolve().then(function () { return require('./runOpenClaw-B1RRfA1V.cjs'); });
|
|
14368
14531
|
let startedBy = void 0;
|
|
14369
14532
|
let verbose = false;
|
|
14370
14533
|
let gatewayUrl;
|
|
@@ -14415,7 +14578,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
|
|
|
14415
14578
|
return;
|
|
14416
14579
|
} else if (subcommand === "mcp" && args.length === 1) {
|
|
14417
14580
|
try {
|
|
14418
|
-
const { handleMcpCommand } = await Promise.resolve().then(function () { return require('./mcp-
|
|
14581
|
+
const { handleMcpCommand } = await Promise.resolve().then(function () { return require('./mcp-ziyMk3eS.cjs'); });
|
|
14419
14582
|
await handleMcpCommand();
|
|
14420
14583
|
} catch (error) {
|
|
14421
14584
|
process.stderr.write(`[very-happy mcp] Fatal: ${error instanceof Error ? error.message : String(error)}
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var AcpBackend = require('./AcpBackend-
|
|
4
|
-
var persistence = require('./types-
|
|
5
|
-
var AcpSessionManager = require('./AcpSessionManager-
|
|
3
|
+
var AcpBackend = require('./AcpBackend-BXsbwTbl.cjs');
|
|
4
|
+
var persistence = require('./types-HRuZ13LS.cjs');
|
|
5
|
+
var AcpSessionManager = require('./AcpSessionManager-BXGmMoe8.cjs');
|
|
6
6
|
var node_crypto = require('node:crypto');
|
|
7
7
|
var path = require('node:path');
|
|
8
|
-
var index = require('./index-
|
|
8
|
+
var index = require('./index-BzbaMrIa.cjs');
|
|
9
9
|
require('node:child_process');
|
|
10
10
|
require('@agentclientprotocol/sdk');
|
|
11
11
|
require('axios');
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import{createRequire as _pkgrollCR}from"node:module";const require=_pkgrollCR(import.meta.url);import chalk from 'chalk';
|
|
2
2
|
import os, { homedir } from 'node:os';
|
|
3
3
|
import { randomUUID, randomBytes, createHash as createHash$1, timingSafeEqual } from 'node:crypto';
|
|
4
|
-
import { n as readDaemonState, l as logger, c as configuration, o as clearDaemonState, q as getProjectPath, p as projectPath, s as initializeSandbox, t as wrapCommand, d as contentLogMetadata, I as InvalidateSync, R as RawJSONLinesSchema, g as delay, u as AsyncLock, v as ensurePrivateDirectory, M as MAX_CHAT_ATTACHMENT_SOURCE_BYTES, x as hardenPrivateFile, f as packageJson, i as readSettings, y as readCredentials, z as credentialRelayProblem, B as deriveLocalCliUpdateSummary, j as encodeBase64, C as updateSettings, D as encodeBase64Url, E as decodeBase64, F as writeCredentialsLegacy, G as writeCredentialsDataKey, H as readCredentialsForConfiguredRelay, J as encrypt, r as readPersistedSessions, K as isClaudeSessionId, L as getLocalHappyAgentCredentialPath, N as readLocalHappyAgentCredentials, O as decryptWithDataKey, P as decryptLegacy, Q as extractCompleteLines, S as decideBackfill, T as parseTerminalHookPayload, U as tmuxArgs, V as scrubTmuxClientEnv, W as decideMirrorBinding, X as MIRROR_BACKFILL_LINES_DEFAULT, Y as persistSession, Z as mirrorLineKey, _ as mirrorLocalId, $ as detectResumeSupport, a0 as detectCLIAvailability, a1 as acquireDaemonLock, a2 as summarizeSpawnSessionForLog, a3 as deletePersistedSessions, a4 as decrypt, a5 as writeDaemonState, A as ApiClient, a6 as fetchCliUpdateState, a7 as resolveCliUpdateCheckInterval, a8 as DEFAULT_CLI_UPDATE_CHECK_INTERVAL_MS, a9 as releaseDaemonLock, aa as isValidSessionId, ab as listVhTerminals, ac as isValidTerminalId, ad as readVhTerminal, ae as sendToVhTerminal, h as connectionState, af as startOfflineReconnection, ag as clearCredentials, ah as clearMachineId, k as ensurePrivateDirectorySync,
|
|
4
|
+
import { n as readDaemonState, l as logger, c as configuration, o as clearDaemonState, q as getProjectPath, p as projectPath, s as initializeSandbox, t as wrapCommand, d as contentLogMetadata, I as InvalidateSync, R as RawJSONLinesSchema, g as delay, u as AsyncLock, v as ensurePrivateDirectory, M as MAX_CHAT_ATTACHMENT_SOURCE_BYTES, x as hardenPrivateFile, f as packageJson, i as readSettings, y as readCredentials, z as credentialRelayProblem, B as deriveLocalCliUpdateSummary, j as encodeBase64, C as updateSettings, D as encodeBase64Url, E as decodeBase64, F as writeCredentialsLegacy, G as writeCredentialsDataKey, H as readCredentialsForConfiguredRelay, J as encrypt, r as readPersistedSessions, K as isClaudeSessionId, L as getLocalHappyAgentCredentialPath, N as readLocalHappyAgentCredentials, O as decryptWithDataKey, P as decryptLegacy, Q as extractCompleteLines, S as decideBackfill, T as parseTerminalHookPayload, U as tmuxArgs, V as scrubTmuxClientEnv, W as decideMirrorBinding, X as MIRROR_BACKFILL_LINES_DEFAULT, Y as persistSession, Z as mirrorLineKey, _ as mirrorLocalId, w as writePrivateFileSync, $ as detectResumeSupport, a0 as detectCLIAvailability, a1 as acquireDaemonLock, a2 as summarizeSpawnSessionForLog, a3 as deletePersistedSessions, a4 as decrypt, a5 as writeDaemonState, A as ApiClient, a6 as fetchCliUpdateState, a7 as resolveCliUpdateCheckInterval, a8 as DEFAULT_CLI_UPDATE_CHECK_INTERVAL_MS, a9 as releaseDaemonLock, aa as isValidSessionId, ab as listVhTerminals, ac as isValidTerminalId, ad as readVhTerminal, ae as sendToVhTerminal, h as connectionState, af as startOfflineReconnection, ag as clearCredentials, ah as clearMachineId, k as ensurePrivateDirectorySync, ai as SandboxConfigSchema, b as createEnvelope, aj as CodexAppServerClient, ak as getLatestDaemonLog } from './types-BLE8Hfmh.mjs';
|
|
5
5
|
import spawn$1, { spawn } from 'cross-spawn';
|
|
6
6
|
import path, { join, resolve, basename, isAbsolute, normalize, sep, dirname } from 'node:path';
|
|
7
7
|
import { createInterface } from 'node:readline';
|
|
8
|
-
import { existsSync, readFileSync, readdirSync, statSync, mkdirSync, unlinkSync, writeFileSync, rmSync, chmodSync as chmodSync$1 } from 'node:fs';
|
|
8
|
+
import { existsSync, readFileSync, readdirSync, statSync, mkdirSync, unlinkSync, renameSync, writeFileSync, rmSync, chmodSync as chmodSync$1 } from 'node:fs';
|
|
9
9
|
import { t as trimIdent, A as AGENT_GUIDANCE, P as PREVIEW_TOOL_NAME, R as REPORT_PROGRESS_TOOL_NAME, a as PREVIEW_TOOL_TITLE, b as PREVIEW_TOOL_DESCRIPTION, c as REPORT_PROGRESS_TOOL_TITLE, d as REPORT_PROGRESS_TOOL_DESCRIPTION } from './agentGuidance-C2_pkgRI.mjs';
|
|
10
10
|
import { readFile, writeFile, rename, unlink, mkdir, stat, open as open$1, appendFile } from 'node:fs/promises';
|
|
11
11
|
import fs, { watch, access } from 'fs/promises';
|
|
@@ -7211,6 +7211,144 @@ function recoverableSessionPid(metadata, liveHappyPids) {
|
|
|
7211
7211
|
const pid = metadata?.hostPid;
|
|
7212
7212
|
return typeof pid === "number" && Number.isInteger(pid) && pid > 0 && liveHappyPids.has(pid) ? pid : null;
|
|
7213
7213
|
}
|
|
7214
|
+
function escapeRegExp(value) {
|
|
7215
|
+
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
7216
|
+
}
|
|
7217
|
+
function sessionAgentConversationId(metadata) {
|
|
7218
|
+
if (!metadata) return null;
|
|
7219
|
+
if (metadata.flavor === "codex") return metadata.codexThreadId ?? null;
|
|
7220
|
+
return metadata.claudeSessionId ?? metadata.codexThreadId ?? null;
|
|
7221
|
+
}
|
|
7222
|
+
function isDaemonWrapperForConversation(command, conversationId) {
|
|
7223
|
+
if (!command || !conversationId) return false;
|
|
7224
|
+
const startedByDaemon = /(?:^|\s)--started-by\s+daemon(?:\s|$)/.test(command);
|
|
7225
|
+
if (!startedByDaemon) return false;
|
|
7226
|
+
const resume = new RegExp(`(?:^|\\s)--resume(?:\\s+|=)${escapeRegExp(conversationId)}(?:\\s|$)`);
|
|
7227
|
+
return resume.test(command);
|
|
7228
|
+
}
|
|
7229
|
+
function findSessionWrapperPids(metadata, liveHappyProcesses, options = {}) {
|
|
7230
|
+
const out = [];
|
|
7231
|
+
const livePids = new Set(liveHappyProcesses.map((p) => p.pid));
|
|
7232
|
+
const lockPid = options.lockPid ?? null;
|
|
7233
|
+
if (lockPid !== null && lockPid !== options.excludePid && livePids.has(lockPid)) out.push(lockPid);
|
|
7234
|
+
const persisted = recoverableSessionPid(metadata, livePids);
|
|
7235
|
+
if (persisted !== null && persisted !== options.excludePid && !out.includes(persisted)) out.push(persisted);
|
|
7236
|
+
const conversationId = sessionAgentConversationId(metadata);
|
|
7237
|
+
if (conversationId) {
|
|
7238
|
+
for (const proc of liveHappyProcesses) {
|
|
7239
|
+
if (proc.pid === options.excludePid || out.includes(proc.pid)) continue;
|
|
7240
|
+
if (isDaemonWrapperForConversation(proc.command, conversationId)) out.push(proc.pid);
|
|
7241
|
+
}
|
|
7242
|
+
}
|
|
7243
|
+
return out;
|
|
7244
|
+
}
|
|
7245
|
+
function mergeRestoreMetadata(stale, reported) {
|
|
7246
|
+
if (!reported) return stale;
|
|
7247
|
+
return { ...stale, ...processIdentityFields(reported) };
|
|
7248
|
+
}
|
|
7249
|
+
|
|
7250
|
+
const SESSION_LOCK_DIR = "session-locks";
|
|
7251
|
+
const defaultRuntime = () => ({
|
|
7252
|
+
dir: join(configuration.happyHomeDir, SESSION_LOCK_DIR),
|
|
7253
|
+
selfPid: process.pid,
|
|
7254
|
+
now: () => Date.now(),
|
|
7255
|
+
signal: (pid, signal) => process.kill(pid, signal),
|
|
7256
|
+
isAlive: (pid) => {
|
|
7257
|
+
try {
|
|
7258
|
+
process.kill(pid, 0);
|
|
7259
|
+
return true;
|
|
7260
|
+
} catch {
|
|
7261
|
+
return false;
|
|
7262
|
+
}
|
|
7263
|
+
},
|
|
7264
|
+
schedule: (callback, delayMs) => {
|
|
7265
|
+
setTimeout(callback, delayMs);
|
|
7266
|
+
}
|
|
7267
|
+
});
|
|
7268
|
+
function sessionLockPath(happySessionId, dir = join(configuration.happyHomeDir, SESSION_LOCK_DIR)) {
|
|
7269
|
+
return join(dir, `${happySessionId}.json`);
|
|
7270
|
+
}
|
|
7271
|
+
function readSessionLock(happySessionId, dir) {
|
|
7272
|
+
try {
|
|
7273
|
+
const path = sessionLockPath(happySessionId, dir);
|
|
7274
|
+
if (!existsSync(path)) return null;
|
|
7275
|
+
const parsed = JSON.parse(readFileSync(path, "utf-8"));
|
|
7276
|
+
if (typeof parsed?.pid !== "number" || !Number.isInteger(parsed.pid) || parsed.pid <= 0) return null;
|
|
7277
|
+
return {
|
|
7278
|
+
pid: parsed.pid,
|
|
7279
|
+
startedAt: typeof parsed.startedAt === "number" ? parsed.startedAt : 0,
|
|
7280
|
+
version: typeof parsed.version === "string" ? parsed.version : "",
|
|
7281
|
+
...typeof parsed.flavor === "string" ? { flavor: parsed.flavor } : {}
|
|
7282
|
+
};
|
|
7283
|
+
} catch {
|
|
7284
|
+
return null;
|
|
7285
|
+
}
|
|
7286
|
+
}
|
|
7287
|
+
function liveSessionLockHolder(happySessionId, runtime = defaultRuntime()) {
|
|
7288
|
+
const record = readSessionLock(happySessionId, runtime.dir);
|
|
7289
|
+
if (!record || record.pid === runtime.selfPid) return null;
|
|
7290
|
+
return runtime.isAlive(record.pid) ? record : null;
|
|
7291
|
+
}
|
|
7292
|
+
function writeSessionLock(happySessionId, record, dir) {
|
|
7293
|
+
mkdirSync(dir, { recursive: true, mode: 448 });
|
|
7294
|
+
const path = sessionLockPath(happySessionId, dir);
|
|
7295
|
+
const tmp = `${path}.${record.pid}.tmp`;
|
|
7296
|
+
writePrivateFileSync(tmp, JSON.stringify(record));
|
|
7297
|
+
renameSync(tmp, path);
|
|
7298
|
+
}
|
|
7299
|
+
function acquireSessionLock(happySessionId, options, runtime = defaultRuntime()) {
|
|
7300
|
+
const record = () => ({
|
|
7301
|
+
pid: runtime.selfPid,
|
|
7302
|
+
startedAt: runtime.now(),
|
|
7303
|
+
version: options.version,
|
|
7304
|
+
...options.flavor ? { flavor: options.flavor } : {}
|
|
7305
|
+
});
|
|
7306
|
+
const holder = liveSessionLockHolder(happySessionId, runtime);
|
|
7307
|
+
if (!holder) {
|
|
7308
|
+
writeSessionLock(happySessionId, record(), runtime.dir);
|
|
7309
|
+
return Promise.resolve({ ok: true, replaced: null });
|
|
7310
|
+
}
|
|
7311
|
+
if (!options.takeover) {
|
|
7312
|
+
return Promise.resolve({ ok: false, holder });
|
|
7313
|
+
}
|
|
7314
|
+
return new Promise((resolve) => {
|
|
7315
|
+
const requested = terminateProcess(holder.pid, (stopped) => {
|
|
7316
|
+
if (!stopped) {
|
|
7317
|
+
resolve({ ok: false, holder });
|
|
7318
|
+
return;
|
|
7319
|
+
}
|
|
7320
|
+
writeSessionLock(happySessionId, record(), runtime.dir);
|
|
7321
|
+
resolve({ ok: true, replaced: holder });
|
|
7322
|
+
}, runtime, options.graceMs ?? 2e3);
|
|
7323
|
+
if (!requested) resolve({ ok: false, holder });
|
|
7324
|
+
});
|
|
7325
|
+
}
|
|
7326
|
+
function releaseSessionLock(happySessionId, runtime = defaultRuntime()) {
|
|
7327
|
+
try {
|
|
7328
|
+
const record = readSessionLock(happySessionId, runtime.dir);
|
|
7329
|
+
if (record && record.pid === runtime.selfPid) {
|
|
7330
|
+
unlinkSync(sessionLockPath(happySessionId, runtime.dir));
|
|
7331
|
+
}
|
|
7332
|
+
} catch {
|
|
7333
|
+
}
|
|
7334
|
+
}
|
|
7335
|
+
async function claimSessionOrExit(happySessionId, options) {
|
|
7336
|
+
const result = await acquireSessionLock(happySessionId, {
|
|
7337
|
+
takeover: options.takeover,
|
|
7338
|
+
version: configuration.currentCliVersion,
|
|
7339
|
+
flavor: options.flavor
|
|
7340
|
+
});
|
|
7341
|
+
if (!result.ok) {
|
|
7342
|
+
const message = `Session ${happySessionId} is already run by very-happy pid ${result.holder.pid} (v${result.holder.version || "?"}); this process yields.`;
|
|
7343
|
+
logger.debug(`[SESSION LOCK] ${message}`);
|
|
7344
|
+
console.error(message);
|
|
7345
|
+
process.exit(0);
|
|
7346
|
+
}
|
|
7347
|
+
if (result.replaced) {
|
|
7348
|
+
logger.debug(`[SESSION LOCK] Took over session ${happySessionId} from pid ${result.replaced.pid} (v${result.replaced.version || "?"})`);
|
|
7349
|
+
}
|
|
7350
|
+
process.on("exit", () => releaseSessionLock(happySessionId));
|
|
7351
|
+
}
|
|
7214
7352
|
|
|
7215
7353
|
function shellescape(s) {
|
|
7216
7354
|
return "'" + s.replace(/'/g, "'\\''") + "'";
|
|
@@ -7302,7 +7440,7 @@ async function startDaemon() {
|
|
|
7302
7440
|
const pidToTrackedSession = /* @__PURE__ */ new Map();
|
|
7303
7441
|
const sessionIdToFinishedSession = /* @__PURE__ */ new Map();
|
|
7304
7442
|
const persisted = readPersistedSessions();
|
|
7305
|
-
const
|
|
7443
|
+
const liveHappyProcesses = await findAllHappyProcesses();
|
|
7306
7444
|
for (const [id, s] of Object.entries(persisted)) {
|
|
7307
7445
|
const tracked = {
|
|
7308
7446
|
startedBy: "persisted",
|
|
@@ -7317,12 +7455,20 @@ async function startDaemon() {
|
|
|
7317
7455
|
},
|
|
7318
7456
|
pid: 0
|
|
7319
7457
|
};
|
|
7320
|
-
const
|
|
7321
|
-
if (
|
|
7458
|
+
const livePids = findSessionWrapperPids(s.metadata, liveHappyProcesses, { excludePid: process.pid, lockPid: readSessionLock(id)?.pid });
|
|
7459
|
+
if (livePids.length > 0) {
|
|
7460
|
+
const [livePid, ...duplicates] = livePids;
|
|
7322
7461
|
tracked.pid = livePid;
|
|
7323
7462
|
tracked.startedBy = "recovered after daemon restart";
|
|
7324
7463
|
pidToTrackedSession.set(livePid, tracked);
|
|
7325
|
-
|
|
7464
|
+
if (livePid !== s.metadata?.hostPid) {
|
|
7465
|
+
logger.debug(`[DAEMON RUN] Session ${id}: persisted hostPid ${s.metadata?.hostPid} is stale; adopted live wrapper ${livePid} by its --resume command line`);
|
|
7466
|
+
}
|
|
7467
|
+
for (const dup of duplicates) {
|
|
7468
|
+
logger.warn(`[DAEMON RUN] Session ${id} has a duplicate live wrapper ${dup} (kept ${livePid}); restart the session to collapse them`);
|
|
7469
|
+
pidToTrackedSession.set(dup, { ...tracked, pid: dup, startedBy: "recovered after daemon restart (duplicate wrapper)" });
|
|
7470
|
+
}
|
|
7471
|
+
persistSession(id, { ...s, metadata: { ...s.metadata, hostPid: livePid }, savedAt: Date.now() });
|
|
7326
7472
|
} else {
|
|
7327
7473
|
sessionIdToFinishedSession.set(id, tracked);
|
|
7328
7474
|
}
|
|
@@ -7352,6 +7498,11 @@ async function startDaemon() {
|
|
|
7352
7498
|
savedAt: Date.now()
|
|
7353
7499
|
});
|
|
7354
7500
|
}
|
|
7501
|
+
for (const [otherPid, other] of pidToTrackedSession.entries()) {
|
|
7502
|
+
if (other.happySessionId === sessionId && otherPid !== pid && isPidAlive(otherPid)) {
|
|
7503
|
+
logger.warn(`[DAEMON RUN] Session ${sessionId} now has two live wrappers (${otherPid} and ${pid}); restart the session to collapse them`);
|
|
7504
|
+
}
|
|
7505
|
+
}
|
|
7355
7506
|
const existingSession = pidToTrackedSession.get(pid);
|
|
7356
7507
|
if (existingSession && existingSession.startedBy === "daemon") {
|
|
7357
7508
|
existingSession.happySessionId = sessionId;
|
|
@@ -7779,6 +7930,21 @@ async function startDaemon() {
|
|
|
7779
7930
|
}
|
|
7780
7931
|
return sessionIdToFinishedSession.get(happySessionId);
|
|
7781
7932
|
};
|
|
7933
|
+
const persistRestoreRecord = (happySessionId, fallback, metadata) => {
|
|
7934
|
+
const candidates = [...pidToTrackedSession.values()].filter((s) => s.happySessionId === happySessionId && isPidAlive(s.pid));
|
|
7935
|
+
const live = candidates.find((s) => s.childProcess) ?? candidates[0];
|
|
7936
|
+
const encryption = live?.encryption ?? fallback.encryption;
|
|
7937
|
+
if (!encryption) return;
|
|
7938
|
+
persistSession(happySessionId, {
|
|
7939
|
+
encryptionKey: encodeBase64(encryption.encryptionKey),
|
|
7940
|
+
encryptionVariant: encryption.encryptionVariant,
|
|
7941
|
+
seq: encryption.seq,
|
|
7942
|
+
metadataVersion: encryption.metadataVersion,
|
|
7943
|
+
agentStateVersion: encryption.agentStateVersion,
|
|
7944
|
+
metadata: mergeRestoreMetadata(metadata, live?.happySessionMetadataFromLocalWebhook),
|
|
7945
|
+
savedAt: Date.now()
|
|
7946
|
+
});
|
|
7947
|
+
};
|
|
7782
7948
|
const fetchServerSessionMetadata = async (sessionId, encryptionKey, encryptionVariant) => {
|
|
7783
7949
|
try {
|
|
7784
7950
|
const byId = await axios.get(`${configuration.serverUrl}/v1/sessions/${encodeURIComponent(sessionId)}`, {
|
|
@@ -7835,6 +8001,14 @@ async function startDaemon() {
|
|
|
7835
8001
|
if (!tracked) {
|
|
7836
8002
|
return { type: "error", errorMessage: `resume-precheck:not-tracked: Session ${happySessionId} is not tracked by this daemon. It may have been started before the daemon, more than 14 days ago, or on another machine.` };
|
|
7837
8003
|
}
|
|
8004
|
+
const orphans = findSessionWrapperPids(tracked.happySessionMetadataFromLocalWebhook, await findAllHappyProcesses(), { excludePid: process.pid, lockPid: readSessionLock(happySessionId)?.pid }).filter((pid) => isPidAlive(pid) && !pidToTrackedSession.has(pid));
|
|
8005
|
+
if (orphans.length > 0) {
|
|
8006
|
+
for (const pid of orphans) {
|
|
8007
|
+
pidToTrackedSession.set(pid, { ...tracked, pid, startedBy: "adopted untracked wrapper" });
|
|
8008
|
+
}
|
|
8009
|
+
logger.debug(`[DAEMON RUN] resume ${happySessionId}: adopted untracked live wrapper(s) ${orphans.join(", ")} \u2014 idempotent success`);
|
|
8010
|
+
return { type: "success", sessionId: happySessionId };
|
|
8011
|
+
}
|
|
7838
8012
|
if (!tracked.happySessionMetadataFromLocalWebhook) {
|
|
7839
8013
|
return { type: "error", errorMessage: `resume-precheck:no-metadata: Session ${happySessionId} has no metadata. Cannot resume.` };
|
|
7840
8014
|
}
|
|
@@ -7882,15 +8056,7 @@ async function startDaemon() {
|
|
|
7882
8056
|
}
|
|
7883
8057
|
});
|
|
7884
8058
|
if (result.type === "success") {
|
|
7885
|
-
|
|
7886
|
-
encryptionKey: encodeBase64(tracked.encryption.encryptionKey),
|
|
7887
|
-
encryptionVariant: tracked.encryption.encryptionVariant,
|
|
7888
|
-
seq: tracked.encryption.seq,
|
|
7889
|
-
metadataVersion: tracked.encryption.metadataVersion,
|
|
7890
|
-
agentStateVersion: tracked.encryption.agentStateVersion,
|
|
7891
|
-
metadata,
|
|
7892
|
-
savedAt: Date.now()
|
|
7893
|
-
});
|
|
8059
|
+
persistRestoreRecord(happySessionId, tracked, metadata);
|
|
7894
8060
|
}
|
|
7895
8061
|
return result;
|
|
7896
8062
|
} catch (error) {
|
|
@@ -7903,17 +8069,18 @@ async function startDaemon() {
|
|
|
7903
8069
|
}
|
|
7904
8070
|
};
|
|
7905
8071
|
const restartCounts = /* @__PURE__ */ new Map();
|
|
7906
|
-
const stopSessionAndWait = (happySessionId, timeoutMs = 8e3) => {
|
|
7907
|
-
|
|
7908
|
-
for (const [
|
|
7909
|
-
if (s.happySessionId === happySessionId && isPidAlive(
|
|
7910
|
-
|
|
7911
|
-
|
|
7912
|
-
|
|
7913
|
-
|
|
7914
|
-
|
|
7915
|
-
|
|
7916
|
-
|
|
8072
|
+
const stopSessionAndWait = async (happySessionId, timeoutMs = 8e3) => {
|
|
8073
|
+
const targets = /* @__PURE__ */ new Set();
|
|
8074
|
+
for (const [pid, s] of pidToTrackedSession.entries()) {
|
|
8075
|
+
if (s.happySessionId === happySessionId && isPidAlive(pid)) targets.add(pid);
|
|
8076
|
+
}
|
|
8077
|
+
const known = findTrackedSessionById(happySessionId)?.happySessionMetadataFromLocalWebhook;
|
|
8078
|
+
for (const pid of findSessionWrapperPids(known, await findAllHappyProcesses(), { excludePid: process.pid, lockPid: readSessionLock(happySessionId)?.pid })) {
|
|
8079
|
+
if (isPidAlive(pid)) targets.add(pid);
|
|
8080
|
+
}
|
|
8081
|
+
if (targets.size === 0) return;
|
|
8082
|
+
logger.debug(`[DAEMON RUN] restart ${happySessionId}: stopping live wrapper(s) ${[...targets].join(", ")}`);
|
|
8083
|
+
await Promise.all([...targets].map((pid) => new Promise((resolve) => {
|
|
7917
8084
|
let settled = false;
|
|
7918
8085
|
const done = () => {
|
|
7919
8086
|
if (!settled) {
|
|
@@ -7933,7 +8100,7 @@ async function startDaemon() {
|
|
|
7933
8100
|
});
|
|
7934
8101
|
if (!requested) done();
|
|
7935
8102
|
setTimeout(done, timeoutMs).unref?.();
|
|
7936
|
-
});
|
|
8103
|
+
})));
|
|
7937
8104
|
};
|
|
7938
8105
|
const restartSession = async (happySessionId, options) => {
|
|
7939
8106
|
let gate = resumeGates.get(happySessionId);
|
|
@@ -8015,15 +8182,7 @@ async function startDaemon() {
|
|
|
8015
8182
|
}
|
|
8016
8183
|
});
|
|
8017
8184
|
if (result.type === "success") {
|
|
8018
|
-
|
|
8019
|
-
encryptionKey: encodeBase64(tracked.encryption.encryptionKey),
|
|
8020
|
-
encryptionVariant: tracked.encryption.encryptionVariant,
|
|
8021
|
-
seq: tracked.encryption.seq,
|
|
8022
|
-
metadataVersion: tracked.encryption.metadataVersion,
|
|
8023
|
-
agentStateVersion: tracked.encryption.agentStateVersion,
|
|
8024
|
-
metadata,
|
|
8025
|
-
savedAt: Date.now()
|
|
8026
|
-
});
|
|
8185
|
+
persistRestoreRecord(happySessionId, tracked, metadata);
|
|
8027
8186
|
}
|
|
8028
8187
|
return result;
|
|
8029
8188
|
} catch (error) {
|
|
@@ -9792,6 +9951,7 @@ async function runClaude(credentials, options = {}) {
|
|
|
9792
9951
|
process.exit(0);
|
|
9793
9952
|
}
|
|
9794
9953
|
logger.debug(`Session created: ${response.id}`);
|
|
9954
|
+
await claimSessionOrExit(response.id, { takeover: !!reconnectSessionId, flavor: "claude" });
|
|
9795
9955
|
if (reconnectSessionId && !await api.reactivateSession(response.id)) {
|
|
9796
9956
|
throw new Error(`Failed to reactivate archived session ${response.id}`);
|
|
9797
9957
|
}
|
|
@@ -13306,6 +13466,9 @@ async function runCodex(opts) {
|
|
|
13306
13466
|
} else {
|
|
13307
13467
|
response = await api.getOrCreateSession({ tag: sessionTag, metadata, state });
|
|
13308
13468
|
}
|
|
13469
|
+
if (response) {
|
|
13470
|
+
await claimSessionOrExit(response.id, { takeover: !!reconnectSessionId, flavor: "codex" });
|
|
13471
|
+
}
|
|
13309
13472
|
if (reconnectSessionId && response && !await api.reactivateSession(response.id)) {
|
|
13310
13473
|
throw new Error(`Failed to reactivate archived session ${response.id}`);
|
|
13311
13474
|
}
|
|
@@ -14072,7 +14235,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
|
|
|
14072
14235
|
process.exit(0);
|
|
14073
14236
|
} else if (subcommand === "install-terminal-hooks") {
|
|
14074
14237
|
try {
|
|
14075
|
-
const { installTerminalHooks, parseTerminalHooksArgs, TERMINAL_HOOKS_HELP } = await import('./installTerminalHooks-
|
|
14238
|
+
const { installTerminalHooks, parseTerminalHooksArgs, TERMINAL_HOOKS_HELP } = await import('./installTerminalHooks-FiujjEvb.mjs');
|
|
14076
14239
|
const command = parseTerminalHooksArgs(args.slice(1));
|
|
14077
14240
|
if (command.action === "help") {
|
|
14078
14241
|
console.log(TERMINAL_HOOKS_HELP);
|
|
@@ -14089,7 +14252,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
|
|
|
14089
14252
|
}
|
|
14090
14253
|
} else if (subcommand === "spawn") {
|
|
14091
14254
|
try {
|
|
14092
|
-
const { handleSpawnCommand } = await import('./spawn-
|
|
14255
|
+
const { handleSpawnCommand } = await import('./spawn-uTPD3qOt.mjs');
|
|
14093
14256
|
await handleSpawnCommand(args.slice(1));
|
|
14094
14257
|
} catch (error) {
|
|
14095
14258
|
console.error(chalk.red("Error:"), error instanceof Error ? error.message : "Unknown error");
|
|
@@ -14101,7 +14264,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
|
|
|
14101
14264
|
return;
|
|
14102
14265
|
} else if (subcommand === "send") {
|
|
14103
14266
|
try {
|
|
14104
|
-
const { handleSendCommand } = await import('./send-
|
|
14267
|
+
const { handleSendCommand } = await import('./send-CxLL0z9J.mjs');
|
|
14105
14268
|
await handleSendCommand(args.slice(1));
|
|
14106
14269
|
} catch (error) {
|
|
14107
14270
|
console.error(chalk.red("Error:"), error instanceof Error ? error.message : "Unknown error");
|
|
@@ -14207,9 +14370,9 @@ Conversation history is preserved on the server, but in-flight tool calls are in
|
|
|
14207
14370
|
if (geminiSubcommand === "project" && args[2] === "set" && args[3]) {
|
|
14208
14371
|
const projectId = args[3];
|
|
14209
14372
|
try {
|
|
14210
|
-
const { saveGoogleCloudProjectToConfig } = await import('./config-
|
|
14211
|
-
const { readCredentialsForConfiguredRelay: readCredentialsForConfiguredRelay2 } = await import('./types-
|
|
14212
|
-
const { ApiClient: ApiClient2 } = await import('./types-
|
|
14373
|
+
const { saveGoogleCloudProjectToConfig } = await import('./config-2GD21yg_.mjs');
|
|
14374
|
+
const { readCredentialsForConfiguredRelay: readCredentialsForConfiguredRelay2 } = await import('./types-BLE8Hfmh.mjs').then(function (n) { return n.al; });
|
|
14375
|
+
const { ApiClient: ApiClient2 } = await import('./types-BLE8Hfmh.mjs').then(function (n) { return n.am; });
|
|
14213
14376
|
let userEmail = void 0;
|
|
14214
14377
|
try {
|
|
14215
14378
|
const credentials = await readCredentialsForConfiguredRelay2();
|
|
@@ -14240,7 +14403,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
|
|
|
14240
14403
|
}
|
|
14241
14404
|
if (geminiSubcommand === "project" && args[2] === "get") {
|
|
14242
14405
|
try {
|
|
14243
|
-
const { readGeminiLocalConfig } = await import('./config-
|
|
14406
|
+
const { readGeminiLocalConfig } = await import('./config-2GD21yg_.mjs');
|
|
14244
14407
|
const config = readGeminiLocalConfig();
|
|
14245
14408
|
if (config.googleCloudProject) {
|
|
14246
14409
|
console.log(`Current Google Cloud Project: ${config.googleCloudProject}`);
|
|
@@ -14280,7 +14443,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
|
|
|
14280
14443
|
process.exit(0);
|
|
14281
14444
|
}
|
|
14282
14445
|
try {
|
|
14283
|
-
const { runGemini } = await import('./runGemini-
|
|
14446
|
+
const { runGemini } = await import('./runGemini-D_InkOhk.mjs');
|
|
14284
14447
|
let startedBy = void 0;
|
|
14285
14448
|
for (let i = 1; i < args.length; i++) {
|
|
14286
14449
|
if (args[i] === "--started-by") {
|
|
@@ -14302,7 +14465,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
|
|
|
14302
14465
|
return;
|
|
14303
14466
|
} else if (subcommand === "acp") {
|
|
14304
14467
|
try {
|
|
14305
|
-
const { runAcp, resolveAcpAgentConfig } = await import('./index-
|
|
14468
|
+
const { runAcp, resolveAcpAgentConfig } = await import('./index-DZ0uw6ef.mjs');
|
|
14306
14469
|
let startedBy = void 0;
|
|
14307
14470
|
let verbose = false;
|
|
14308
14471
|
const acpArgs = [];
|
|
@@ -14342,7 +14505,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
|
|
|
14342
14505
|
return;
|
|
14343
14506
|
} else if (subcommand === "openclaw") {
|
|
14344
14507
|
try {
|
|
14345
|
-
const { runOpenClaw } = await import('./runOpenClaw-
|
|
14508
|
+
const { runOpenClaw } = await import('./runOpenClaw-BjebGmV6.mjs');
|
|
14346
14509
|
let startedBy = void 0;
|
|
14347
14510
|
let verbose = false;
|
|
14348
14511
|
let gatewayUrl;
|
|
@@ -14393,7 +14556,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
|
|
|
14393
14556
|
return;
|
|
14394
14557
|
} else if (subcommand === "mcp" && args.length === 1) {
|
|
14395
14558
|
try {
|
|
14396
|
-
const { handleMcpCommand } = await import('./mcp-
|
|
14559
|
+
const { handleMcpCommand } = await import('./mcp-0mZcHPtz.mjs');
|
|
14397
14560
|
await handleMcpCommand();
|
|
14398
14561
|
} catch (error) {
|
|
14399
14562
|
process.stderr.write(`[very-happy mcp] Fatal: ${error instanceof Error ? error.message : String(error)}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { D as DefaultTransport, A as AcpBackend } from './AcpBackend-
|
|
2
|
-
export { a as DEFAULT_IDLE_TIMEOUT_MS, b as DEFAULT_TOOL_CALL_TIMEOUT_MS, e as extractErrorDetail, f as formatDuration, c as formatDurationMinutes, h as handleAgentMessageChunk, d as handleAgentThoughtChunk, g as handleLegacyMessageChunk, i as handlePlanUpdate, j as handleThinkingUpdate, k as handleToolCall, l as handleToolCallUpdate, p as parseArgsFromContent } from './AcpBackend-
|
|
3
|
-
import { h as connectionState, A as ApiClient, i as readSettings, j as encodeBase64, l as logger, p as projectPath } from './types-
|
|
4
|
-
import { A as AcpSessionManager } from './AcpSessionManager-
|
|
1
|
+
import { D as DefaultTransport, A as AcpBackend } from './AcpBackend-Cuiff4Nu.mjs';
|
|
2
|
+
export { a as DEFAULT_IDLE_TIMEOUT_MS, b as DEFAULT_TOOL_CALL_TIMEOUT_MS, e as extractErrorDetail, f as formatDuration, c as formatDurationMinutes, h as handleAgentMessageChunk, d as handleAgentThoughtChunk, g as handleLegacyMessageChunk, i as handlePlanUpdate, j as handleThinkingUpdate, k as handleToolCall, l as handleToolCallUpdate, p as parseArgsFromContent } from './AcpBackend-Cuiff4Nu.mjs';
|
|
3
|
+
import { h as connectionState, A as ApiClient, i as readSettings, j as encodeBase64, l as logger, p as projectPath } from './types-BLE8Hfmh.mjs';
|
|
4
|
+
import { A as AcpSessionManager } from './AcpSessionManager-BU69q_vR.mjs';
|
|
5
5
|
import { randomUUID } from 'node:crypto';
|
|
6
6
|
import { join } from 'node:path';
|
|
7
|
-
import { i as initialMachineMetadata, d as createSessionMetadata, e as setupOfflineReconnection, n as notifyDaemonSessionStarted, M as MessageQueue2, h as hashObject, f as startHappyServer, r as registerKillSessionHandler, B as BasePermissionHandler } from './index-
|
|
7
|
+
import { i as initialMachineMetadata, d as createSessionMetadata, e as setupOfflineReconnection, n as notifyDaemonSessionStarted, M as MessageQueue2, h as hashObject, f as startHappyServer, r as registerKillSessionHandler, B as BasePermissionHandler } from './index-DVEdpWq0.mjs';
|
|
8
8
|
import 'node:child_process';
|
|
9
9
|
import '@agentclientprotocol/sdk';
|
|
10
10
|
import 'axios';
|
package/dist/index.cjs
CHANGED
package/dist/index.mjs
CHANGED
|
@@ -5,8 +5,8 @@ var path = require('node:path');
|
|
|
5
5
|
var os = require('node:os');
|
|
6
6
|
var node_child_process = require('node:child_process');
|
|
7
7
|
var chalk = require('chalk');
|
|
8
|
-
var persistence = require('./types-
|
|
9
|
-
var index = require('./index-
|
|
8
|
+
var persistence = require('./types-HRuZ13LS.cjs');
|
|
9
|
+
var index = require('./index-BzbaMrIa.cjs');
|
|
10
10
|
require('axios');
|
|
11
11
|
require('node:util');
|
|
12
12
|
require('node:fs/promises');
|
|
@@ -3,8 +3,8 @@ import { join, resolve } from 'node:path';
|
|
|
3
3
|
import { homedir } from 'node:os';
|
|
4
4
|
import { spawnSync } from 'node:child_process';
|
|
5
5
|
import chalk from 'chalk';
|
|
6
|
-
import { p as projectPath } from './types-
|
|
7
|
-
import { t as tmuxSupportsSessionEnv } from './index-
|
|
6
|
+
import { p as projectPath } from './types-BLE8Hfmh.mjs';
|
|
7
|
+
import { t as tmuxSupportsSessionEnv } from './index-DVEdpWq0.mjs';
|
|
8
8
|
import 'axios';
|
|
9
9
|
import 'node:util';
|
|
10
10
|
import 'node:fs/promises';
|
package/dist/lib.cjs
CHANGED
package/dist/lib.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { A as ApiClient, a as ApiSessionClient, R as RawJSONLinesSchema, c as configuration, l as logger } from './types-
|
|
1
|
+
export { A as ApiClient, a as ApiSessionClient, R as RawJSONLinesSchema, c as configuration, l as logger } from './types-BLE8Hfmh.mjs';
|
|
2
2
|
import 'axios';
|
|
3
3
|
import 'chalk';
|
|
4
4
|
import 'node:util';
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
2
2
|
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
3
3
|
import { z } from 'zod';
|
|
4
|
-
import { p as pushClipboardViaDaemon } from './index-
|
|
4
|
+
import { p as pushClipboardViaDaemon } from './index-DVEdpWq0.mjs';
|
|
5
5
|
import { C as CLIPBOARD_TOOL_NAME, a as CLIPBOARD_TOOL_TITLE, b as CLIPBOARD_TOOL_DESCRIPTION, c as CLIPBOARD_MAX_BYTES } from './limits-CwFb5S2b.mjs';
|
|
6
|
-
import { l as logger } from './types-
|
|
6
|
+
import { l as logger } from './types-BLE8Hfmh.mjs';
|
|
7
7
|
import 'chalk';
|
|
8
8
|
import 'node:os';
|
|
9
9
|
import 'node:crypto';
|
|
@@ -3,9 +3,9 @@
|
|
|
3
3
|
var mcp_js = require('@modelcontextprotocol/sdk/server/mcp.js');
|
|
4
4
|
var stdio_js = require('@modelcontextprotocol/sdk/server/stdio.js');
|
|
5
5
|
var z = require('zod');
|
|
6
|
-
var index = require('./index-
|
|
6
|
+
var index = require('./index-BzbaMrIa.cjs');
|
|
7
7
|
var limits = require('./limits-KdWKmwtH.cjs');
|
|
8
|
-
var persistence = require('./types-
|
|
8
|
+
var persistence = require('./types-HRuZ13LS.cjs');
|
|
9
9
|
require('chalk');
|
|
10
10
|
require('node:os');
|
|
11
11
|
require('node:crypto');
|
|
@@ -4,10 +4,10 @@ var ink = require('ink');
|
|
|
4
4
|
var React = require('react');
|
|
5
5
|
var node_crypto = require('node:crypto');
|
|
6
6
|
var path = require('node:path');
|
|
7
|
-
var persistence = require('./types-
|
|
8
|
-
var index = require('./index-
|
|
9
|
-
var AcpBackend = require('./AcpBackend-
|
|
10
|
-
var config = require('./config-
|
|
7
|
+
var persistence = require('./types-HRuZ13LS.cjs');
|
|
8
|
+
var index = require('./index-BzbaMrIa.cjs');
|
|
9
|
+
var AcpBackend = require('./AcpBackend-BXsbwTbl.cjs');
|
|
10
|
+
var config = require('./config-BVOE0pni.cjs');
|
|
11
11
|
require('axios');
|
|
12
12
|
require('chalk');
|
|
13
13
|
require('node:util');
|
|
@@ -2,10 +2,10 @@ import { useStdout, useInput, Box, Text, render } from 'ink';
|
|
|
2
2
|
import React, { useState, useRef, useEffect, useCallback } from 'react';
|
|
3
3
|
import { randomUUID } from 'node:crypto';
|
|
4
4
|
import { join } from 'node:path';
|
|
5
|
-
import { l as logger, h as connectionState, A as ApiClient, i as readSettings, e as errorLogMetadata, j as encodeBase64, p as projectPath, d as contentLogMetadata } from './types-
|
|
6
|
-
import { g as GEMINI_API_KEY_ENV, j as GOOGLE_API_KEY_ENV, G as GEMINI_MODEL_ENV, B as BasePermissionHandler, k as BaseReasoningProcessor, i as initialMachineMetadata, d as createSessionMetadata, e as setupOfflineReconnection, n as notifyDaemonSessionStarted, M as MessageQueue2, h as hashObject, l as MessageBuffer, C as CHANGE_TITLE_INSTRUCTION, r as registerKillSessionHandler, f as startHappyServer } from './index-
|
|
7
|
-
import { A as AcpBackend } from './AcpBackend-
|
|
8
|
-
import { readGeminiLocalConfig, determineGeminiModel, getGeminiModelSource, getInitialGeminiModel, saveGeminiModelToConfig } from './config-
|
|
5
|
+
import { l as logger, h as connectionState, A as ApiClient, i as readSettings, e as errorLogMetadata, j as encodeBase64, p as projectPath, d as contentLogMetadata } from './types-BLE8Hfmh.mjs';
|
|
6
|
+
import { g as GEMINI_API_KEY_ENV, j as GOOGLE_API_KEY_ENV, G as GEMINI_MODEL_ENV, B as BasePermissionHandler, k as BaseReasoningProcessor, i as initialMachineMetadata, d as createSessionMetadata, e as setupOfflineReconnection, n as notifyDaemonSessionStarted, M as MessageQueue2, h as hashObject, l as MessageBuffer, C as CHANGE_TITLE_INSTRUCTION, r as registerKillSessionHandler, f as startHappyServer } from './index-DVEdpWq0.mjs';
|
|
7
|
+
import { A as AcpBackend } from './AcpBackend-Cuiff4Nu.mjs';
|
|
8
|
+
import { readGeminiLocalConfig, determineGeminiModel, getGeminiModelSource, getInitialGeminiModel, saveGeminiModelToConfig } from './config-2GD21yg_.mjs';
|
|
9
9
|
import 'axios';
|
|
10
10
|
import 'chalk';
|
|
11
11
|
import 'node:util';
|
|
@@ -5,9 +5,9 @@ var node_child_process = require('node:child_process');
|
|
|
5
5
|
var os = require('node:os');
|
|
6
6
|
var node_fs = require('node:fs');
|
|
7
7
|
var path = require('node:path');
|
|
8
|
-
var persistence = require('./types-
|
|
9
|
-
var AcpSessionManager = require('./AcpSessionManager-
|
|
10
|
-
var index = require('./index-
|
|
8
|
+
var persistence = require('./types-HRuZ13LS.cjs');
|
|
9
|
+
var AcpSessionManager = require('./AcpSessionManager-BXGmMoe8.cjs');
|
|
10
|
+
var index = require('./index-BzbaMrIa.cjs');
|
|
11
11
|
var WebSocket = require('ws');
|
|
12
12
|
var ed = require('@noble/ed25519');
|
|
13
13
|
var sha2_js = require('@noble/hashes/sha2.js');
|
|
@@ -3,9 +3,9 @@ import { execFileSync } from 'node:child_process';
|
|
|
3
3
|
import os from 'node:os';
|
|
4
4
|
import { existsSync, readFileSync } from 'node:fs';
|
|
5
5
|
import { join } from 'node:path';
|
|
6
|
-
import { k as ensurePrivateDirectorySync, m as hardenPrivateFileSync, w as writePrivateFileSync, e as errorLogMetadata, d as contentLogMetadata, h as connectionState, A as ApiClient, i as readSettings, j as encodeBase64, l as logger, c as configuration } from './types-
|
|
7
|
-
import { A as AcpSessionManager } from './AcpSessionManager-
|
|
8
|
-
import { i as initialMachineMetadata, d as createSessionMetadata, e as setupOfflineReconnection, n as notifyDaemonSessionStarted, M as MessageQueue2, r as registerKillSessionHandler } from './index-
|
|
6
|
+
import { k as ensurePrivateDirectorySync, m as hardenPrivateFileSync, w as writePrivateFileSync, e as errorLogMetadata, d as contentLogMetadata, h as connectionState, A as ApiClient, i as readSettings, j as encodeBase64, l as logger, c as configuration } from './types-BLE8Hfmh.mjs';
|
|
7
|
+
import { A as AcpSessionManager } from './AcpSessionManager-BU69q_vR.mjs';
|
|
8
|
+
import { i as initialMachineMetadata, d as createSessionMetadata, e as setupOfflineReconnection, n as notifyDaemonSessionStarted, M as MessageQueue2, r as registerKillSessionHandler } from './index-DVEdpWq0.mjs';
|
|
9
9
|
import WebSocket from 'ws';
|
|
10
10
|
import * as ed from '@noble/ed25519';
|
|
11
11
|
import { sha512 } from '@noble/hashes/sha2.js';
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import chalk from 'chalk';
|
|
2
2
|
import { readFileSync } from 'node:fs';
|
|
3
3
|
import { resolve } from 'node:path';
|
|
4
|
-
import { r as readPersistedSessions, c as configuration } from './types-
|
|
5
|
-
import { b as sendUserMessage, a as sessionWebUrl } from './index-
|
|
4
|
+
import { r as readPersistedSessions, c as configuration } from './types-BLE8Hfmh.mjs';
|
|
5
|
+
import { b as sendUserMessage, a as sessionWebUrl } from './index-DVEdpWq0.mjs';
|
|
6
6
|
import 'axios';
|
|
7
7
|
import 'node:util';
|
|
8
8
|
import 'node:os';
|
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
var chalk = require('chalk');
|
|
4
4
|
var node_fs = require('node:fs');
|
|
5
5
|
var path = require('node:path');
|
|
6
|
-
var persistence = require('./types-
|
|
7
|
-
var index = require('./index-
|
|
6
|
+
var persistence = require('./types-HRuZ13LS.cjs');
|
|
7
|
+
var index = require('./index-BzbaMrIa.cjs');
|
|
8
8
|
require('axios');
|
|
9
9
|
require('node:util');
|
|
10
10
|
require('node:os');
|
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
var chalk = require('chalk');
|
|
4
4
|
var node_fs = require('node:fs');
|
|
5
5
|
var path = require('node:path');
|
|
6
|
-
var index = require('./index-
|
|
7
|
-
var persistence = require('./types-
|
|
6
|
+
var index = require('./index-BzbaMrIa.cjs');
|
|
7
|
+
var persistence = require('./types-HRuZ13LS.cjs');
|
|
8
8
|
require('node:os');
|
|
9
9
|
require('node:crypto');
|
|
10
10
|
require('cross-spawn');
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import chalk from 'chalk';
|
|
2
2
|
import { readFileSync, statSync } from 'node:fs';
|
|
3
3
|
import { resolve } from 'node:path';
|
|
4
|
-
import { c as checkIfDaemonRunningAndCleanupStaleState, s as spawnDaemonSession, a as sessionWebUrl, w as waitForSessionKey, b as sendUserMessage } from './index-
|
|
5
|
-
import { l as logger } from './types-
|
|
4
|
+
import { c as checkIfDaemonRunningAndCleanupStaleState, s as spawnDaemonSession, a as sessionWebUrl, w as waitForSessionKey, b as sendUserMessage } from './index-DVEdpWq0.mjs';
|
|
5
|
+
import { l as logger } from './types-BLE8Hfmh.mjs';
|
|
6
6
|
import 'node:os';
|
|
7
7
|
import 'node:crypto';
|
|
8
8
|
import 'cross-spawn';
|
|
@@ -29,7 +29,7 @@ import { SandboxManager } from '@anthropic-ai/sandbox-runtime';
|
|
|
29
29
|
import { Expo } from 'expo-server-sdk';
|
|
30
30
|
|
|
31
31
|
var name = "very-happy-cli";
|
|
32
|
-
var version = "0.2.
|
|
32
|
+
var version = "0.2.95";
|
|
33
33
|
var description = "Remote multi-agent workspace CLI with deep Claude integration, native terminal streaming, and self-hosting.";
|
|
34
34
|
var author = "Kirill Dubovitskiy";
|
|
35
35
|
var contributors = [
|
|
@@ -142,12 +142,12 @@ var dependencies = {
|
|
|
142
142
|
zod: "^4.0.0"
|
|
143
143
|
};
|
|
144
144
|
var optionalDependencies = {
|
|
145
|
-
"very-happy-tools-arm64-darwin": "0.2.
|
|
146
|
-
"very-happy-tools-x64-darwin": "0.2.
|
|
147
|
-
"very-happy-tools-arm64-linux": "0.2.
|
|
148
|
-
"very-happy-tools-x64-linux": "0.2.
|
|
149
|
-
"very-happy-tools-arm64-win32": "0.2.
|
|
150
|
-
"very-happy-tools-x64-win32": "0.2.
|
|
145
|
+
"very-happy-tools-arm64-darwin": "0.2.95",
|
|
146
|
+
"very-happy-tools-x64-darwin": "0.2.95",
|
|
147
|
+
"very-happy-tools-arm64-linux": "0.2.95",
|
|
148
|
+
"very-happy-tools-x64-linux": "0.2.95",
|
|
149
|
+
"very-happy-tools-arm64-win32": "0.2.95",
|
|
150
|
+
"very-happy-tools-x64-win32": "0.2.95"
|
|
151
151
|
};
|
|
152
152
|
var devDependencies = {
|
|
153
153
|
"@slopus/happy-wire": "workspace:*",
|
|
@@ -51,7 +51,7 @@ var z__namespace = /*#__PURE__*/_interopNamespaceDefault(z);
|
|
|
51
51
|
var pty__namespace = /*#__PURE__*/_interopNamespaceDefault(pty);
|
|
52
52
|
|
|
53
53
|
var name = "very-happy-cli";
|
|
54
|
-
var version = "0.2.
|
|
54
|
+
var version = "0.2.95";
|
|
55
55
|
var description = "Remote multi-agent workspace CLI with deep Claude integration, native terminal streaming, and self-hosting.";
|
|
56
56
|
var author = "Kirill Dubovitskiy";
|
|
57
57
|
var contributors = [
|
|
@@ -164,12 +164,12 @@ var dependencies = {
|
|
|
164
164
|
zod: "^4.0.0"
|
|
165
165
|
};
|
|
166
166
|
var optionalDependencies = {
|
|
167
|
-
"very-happy-tools-arm64-darwin": "0.2.
|
|
168
|
-
"very-happy-tools-x64-darwin": "0.2.
|
|
169
|
-
"very-happy-tools-arm64-linux": "0.2.
|
|
170
|
-
"very-happy-tools-x64-linux": "0.2.
|
|
171
|
-
"very-happy-tools-arm64-win32": "0.2.
|
|
172
|
-
"very-happy-tools-x64-win32": "0.2.
|
|
167
|
+
"very-happy-tools-arm64-darwin": "0.2.95",
|
|
168
|
+
"very-happy-tools-x64-darwin": "0.2.95",
|
|
169
|
+
"very-happy-tools-arm64-linux": "0.2.95",
|
|
170
|
+
"very-happy-tools-x64-linux": "0.2.95",
|
|
171
|
+
"very-happy-tools-arm64-win32": "0.2.95",
|
|
172
|
+
"very-happy-tools-x64-win32": "0.2.95"
|
|
173
173
|
};
|
|
174
174
|
var devDependencies = {
|
|
175
175
|
"@slopus/happy-wire": "workspace:*",
|
|
@@ -1545,7 +1545,7 @@ class RpcHandlerManager {
|
|
|
1545
1545
|
}
|
|
1546
1546
|
}
|
|
1547
1547
|
|
|
1548
|
-
const __dirname$1 = path$1.dirname(url.fileURLToPath((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('types-
|
|
1548
|
+
const __dirname$1 = path$1.dirname(url.fileURLToPath((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('types-HRuZ13LS.cjs', document.baseURI).href))));
|
|
1549
1549
|
function projectPath() {
|
|
1550
1550
|
const path = path$1.resolve(__dirname$1, "..");
|
|
1551
1551
|
return path;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "very-happy-cli",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.95",
|
|
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": [
|
|
@@ -113,12 +113,12 @@
|
|
|
113
113
|
"zod": "^4.0.0"
|
|
114
114
|
},
|
|
115
115
|
"optionalDependencies": {
|
|
116
|
-
"very-happy-tools-arm64-darwin": "0.2.
|
|
117
|
-
"very-happy-tools-x64-darwin": "0.2.
|
|
118
|
-
"very-happy-tools-arm64-linux": "0.2.
|
|
119
|
-
"very-happy-tools-x64-linux": "0.2.
|
|
120
|
-
"very-happy-tools-arm64-win32": "0.2.
|
|
121
|
-
"very-happy-tools-x64-win32": "0.2.
|
|
116
|
+
"very-happy-tools-arm64-darwin": "0.2.95",
|
|
117
|
+
"very-happy-tools-x64-darwin": "0.2.95",
|
|
118
|
+
"very-happy-tools-arm64-linux": "0.2.95",
|
|
119
|
+
"very-happy-tools-x64-linux": "0.2.95",
|
|
120
|
+
"very-happy-tools-arm64-win32": "0.2.95",
|
|
121
|
+
"very-happy-tools-x64-win32": "0.2.95"
|
|
122
122
|
},
|
|
123
123
|
"devDependencies": {
|
|
124
124
|
"@slopus/happy-wire": "workspace:*",
|