very-happy-cli 0.2.149 → 0.2.151
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-Baqb8dNm.mjs → AcpBackend-BjTA5gUB.mjs} +2 -2
- package/dist/{AcpBackend-CnZpEfGd.cjs → AcpBackend-blE9IEod.cjs} +2 -2
- package/dist/{AcpSessionManager-CC6mdFXs.mjs → AcpSessionManager-D-9mrp40.mjs} +1 -1
- package/dist/{AcpSessionManager-e2vxmIbj.cjs → AcpSessionManager-bF8PYu_B.cjs} +1 -1
- package/dist/{agentGuidance--QIi_rZ2.cjs → agentGuidance-BXa9ikrZ.cjs} +1 -1
- package/dist/{agentGuidance-oMVJvUl7.mjs → agentGuidance-Dvo3cZMW.mjs} +1 -1
- package/dist/{agentHome-CKSPsS8d.mjs → agentHome-CeFDNzvq.mjs} +2 -2
- package/dist/{agentHome-3kRCtzOL.cjs → agentHome-D6MSfwnp.cjs} +2 -2
- package/dist/codex/happyMcpStdioBridge.cjs +2 -2
- package/dist/codex/happyMcpStdioBridge.mjs +2 -2
- package/dist/{config-C8jpk6IA.mjs → config-C-A1XF62.mjs} +4 -4
- package/dist/{config-CzJZcvTO.cjs → config-Cadw1sAk.cjs} +4 -4
- package/dist/{index-DgK4KX-Z.cjs → index-BKGspSWk.cjs} +7 -7
- package/dist/{index-Dfkyar7S.mjs → index-CIyjJy8D.mjs} +338 -76
- package/dist/{index-CyfXsCXl.cjs → index-CqtfRzug.cjs} +338 -73
- package/dist/{index-DrVq0CqK.mjs → index-DEp6CmmS.mjs} +8 -8
- package/dist/{index-BPCXUrEe.mjs → index-DYQgcgL2.mjs} +4 -4
- package/dist/{index-DBN2Zpqc.cjs → index-vyRqLjDv.cjs} +4 -4
- package/dist/index.cjs +4 -4
- package/dist/index.mjs +4 -4
- package/dist/{installTerminalHooks-kdAoTfNT.cjs → installTerminalHooks-Bf_adbl3.cjs} +4 -4
- package/dist/{installTerminalHooks-COqkLz6f.mjs → installTerminalHooks-Ch_yTtEA.mjs} +4 -4
- package/dist/lib.cjs +2 -2
- package/dist/lib.mjs +2 -2
- package/dist/{limits-BXI1Gzvd.mjs → limits-DS-bnYYp.mjs} +7 -7
- package/dist/{limits-FZWhlsBu.cjs → limits-DwcY3kyi.cjs} +7 -7
- package/dist/{mcp-DoLZbbZp.cjs → mcp-CMxEZ6-0.cjs} +4 -4
- package/dist/{mcp-Dfnoirpi.mjs → mcp-zu8n8TkR.mjs} +4 -4
- package/dist/{piRuntime-BK6YZm2X.mjs → piRuntime-Cu6cXZ6N.mjs} +2 -2
- package/dist/{piRuntime-DmE4ysfG.cjs → piRuntime-D3ny0mVg.cjs} +2 -2
- package/dist/{piTerminal-Bczubq2n.mjs → piTerminal-M677UP7y.mjs} +6 -6
- package/dist/{piTerminal-qQAzQwIU.cjs → piTerminal-kDSd_r9X.cjs} +6 -6
- package/dist/{runGemini-ComTu0EB.cjs → runGemini-DuwdVV1O.cjs} +6 -6
- package/dist/{runGemini-Cce_pjTs.mjs → runGemini-DvJwQVGp.mjs} +6 -6
- package/dist/{runOpenClaw-DXP5_chb.mjs → runOpenClaw-BG82bF18.mjs} +5 -5
- package/dist/{runOpenClaw-M3YlDt8z.cjs → runOpenClaw-BsvtCE_H.cjs} +5 -5
- package/dist/{send-0LrSwGgr.cjs → send-aUkjhey7.cjs} +20 -6
- package/dist/{send-DDD57Cr_.mjs → send-o6WM-1G8.mjs} +20 -6
- package/dist/{sessions-2Bkau9T4.cjs → sessions-B3vP18kz.cjs} +56 -10
- package/dist/{sessions-ClBPEtz2.mjs → sessions-DlU3foY_.mjs} +56 -10
- package/dist/{spawn-Cm3Da8Ge.cjs → spawn-DH6_p4-f.cjs} +166 -27
- package/dist/spawn-DxHIIqhi.mjs +397 -0
- package/dist/{teams-DKKeIG-u.cjs → teams-BW8D1n3o.cjs} +4 -4
- package/dist/{teams-DyBjdXI3.mjs → teams-DoAA_CcN.mjs} +4 -4
- package/dist/{todo-8RgCTDxH.cjs → todo-Bcc2XxGh.cjs} +3 -3
- package/dist/{todo-jXHGGH89.mjs → todo-BhJbG5eq.mjs} +3 -3
- package/dist/{types-ipzMqciq.mjs → types-BN3eiipi.mjs} +46 -3
- package/dist/{types-t1gxALVE.cjs → types-CPubg05Z.cjs} +52 -2
- package/package.json +7 -7
- package/dist/spawn-7lLymdT1.mjs +0 -258
|
@@ -3,14 +3,14 @@
|
|
|
3
3
|
var chalk = require('chalk');
|
|
4
4
|
var os = require('node:os');
|
|
5
5
|
var node_crypto = require('node:crypto');
|
|
6
|
-
var index = require('./types-
|
|
7
|
-
var persistence = require('./limits-
|
|
6
|
+
var index = require('./types-CPubg05Z.cjs');
|
|
7
|
+
var persistence = require('./limits-DwcY3kyi.cjs');
|
|
8
8
|
var spawn = require('cross-spawn');
|
|
9
9
|
var path = require('node:path');
|
|
10
10
|
var node_readline = require('node:readline');
|
|
11
11
|
var node_fs = require('node:fs');
|
|
12
12
|
var projectPath = require('./projectPath-ChLhdOyt.cjs');
|
|
13
|
-
var agentGuidance = require('./agentGuidance
|
|
13
|
+
var agentGuidance = require('./agentGuidance-BXa9ikrZ.cjs');
|
|
14
14
|
var promises = require('node:fs/promises');
|
|
15
15
|
var fs = require('fs/promises');
|
|
16
16
|
var ink = require('ink');
|
|
@@ -478,17 +478,23 @@ function readClaudeSettings() {
|
|
|
478
478
|
}
|
|
479
479
|
function shouldIncludeCoAuthoredBy() {
|
|
480
480
|
const settings = readClaudeSettings();
|
|
481
|
-
if (!settings
|
|
481
|
+
if (!settings) {
|
|
482
|
+
return true;
|
|
483
|
+
}
|
|
484
|
+
if (settings.attribution?.commit === "") {
|
|
485
|
+
return false;
|
|
486
|
+
}
|
|
487
|
+
if (settings.includeCoAuthoredBy === void 0) {
|
|
482
488
|
return true;
|
|
483
489
|
}
|
|
484
490
|
return settings.includeCoAuthoredBy;
|
|
485
491
|
}
|
|
486
492
|
|
|
487
493
|
const BASE_SYSTEM_PROMPT = (() => agentGuidance.trimIdent(`
|
|
488
|
-
|
|
494
|
+
This chat is titled automatically from the user's first message. Call "mcp__happy__change_title" only when the topic has clearly moved on or the current title is too generic to find this chat later. Do not call it as a ritual at the start of a chat, and not for a quick question you can just answer.
|
|
489
495
|
`))() + "\n\n" + agentGuidance.AGENT_GUIDANCE + "\n\n" + index.BUILTIN_TODO_DISCOVERY;
|
|
490
496
|
const CO_AUTHORED_CREDITS = (() => agentGuidance.trimIdent(`
|
|
491
|
-
When
|
|
497
|
+
When you yourself create a git commit, instead of just giving co-credit to Claude, also give credit to Happy like so:
|
|
492
498
|
|
|
493
499
|
<main commit message>
|
|
494
500
|
|
|
@@ -496,6 +502,8 @@ const CO_AUTHORED_CREDITS = (() => agentGuidance.trimIdent(`
|
|
|
496
502
|
via [Very Happy](https://github.com/Mereithhh/very-happy)
|
|
497
503
|
|
|
498
504
|
Co-Authored-By: Claude <noreply@anthropic.com>
|
|
505
|
+
|
|
506
|
+
Do not add these lines to commit message text you only draft for the user.
|
|
499
507
|
`))();
|
|
500
508
|
const systemPrompt = (() => {
|
|
501
509
|
const includeCoAuthored = shouldIncludeCoAuthoredBy();
|
|
@@ -892,7 +900,7 @@ async function createSessionScanner(opts) {
|
|
|
892
900
|
let processedMessageKeys = /* @__PURE__ */ new Set();
|
|
893
901
|
let deadSessions = /* @__PURE__ */ new Set();
|
|
894
902
|
if (opts.sessionId) {
|
|
895
|
-
let messages = await readSessionLog(projectDir, opts.sessionId);
|
|
903
|
+
let messages = await readSessionLog$1(projectDir, opts.sessionId);
|
|
896
904
|
persistence.logger.debug(`[SESSION_SCANNER] Marking ${messages.length} existing messages as processed from session ${opts.sessionId}`);
|
|
897
905
|
for (let m of messages) {
|
|
898
906
|
processedMessageKeys.add(messageKey(m));
|
|
@@ -915,7 +923,7 @@ async function createSessionScanner(opts) {
|
|
|
915
923
|
}
|
|
916
924
|
}
|
|
917
925
|
for (let session of sessions) {
|
|
918
|
-
const sessionMessages = await readSessionLog(projectDir, session);
|
|
926
|
+
const sessionMessages = await readSessionLog$1(projectDir, session);
|
|
919
927
|
let skipped = 0;
|
|
920
928
|
let sent = 0;
|
|
921
929
|
for (let file of sessionMessages) {
|
|
@@ -992,7 +1000,7 @@ async function createSessionScanner(opts) {
|
|
|
992
1000
|
return;
|
|
993
1001
|
}
|
|
994
1002
|
if (options?.treatExistingAsProcessed) {
|
|
995
|
-
const existing = await readSessionLog(projectDir, sessionId);
|
|
1003
|
+
const existing = await readSessionLog$1(projectDir, sessionId);
|
|
996
1004
|
persistence.logger.debug(`[SESSION_SCANNER] Pre-marking ${existing.length} existing messages as processed for new session ${sessionId}`);
|
|
997
1005
|
for (const m of existing) {
|
|
998
1006
|
processedMessageKeys.add(messageKey(m));
|
|
@@ -1020,7 +1028,7 @@ function messageKey(message) {
|
|
|
1020
1028
|
throw Error();
|
|
1021
1029
|
}
|
|
1022
1030
|
}
|
|
1023
|
-
async function readSessionLog(projectDir, sessionId) {
|
|
1031
|
+
async function readSessionLog$1(projectDir, sessionId) {
|
|
1024
1032
|
const expectedSessionFile = path.join(projectDir, `${sessionId}.jsonl`);
|
|
1025
1033
|
persistence.logger.debug(`[SESSION_SCANNER] Reading session file: ${expectedSessionFile}`);
|
|
1026
1034
|
let file;
|
|
@@ -5126,6 +5134,61 @@ function shareSafeEnvironmentInfo(env = process.env, runtime = process) {
|
|
|
5126
5134
|
};
|
|
5127
5135
|
}
|
|
5128
5136
|
|
|
5137
|
+
const NPM_SAFE_ARG = /^[A-Za-z0-9@=.,+/_-]+$/;
|
|
5138
|
+
function globalPrefixForPackage(packageDir) {
|
|
5139
|
+
if (!path.isAbsolute(packageDir)) return null;
|
|
5140
|
+
const dir = path.resolve(packageDir);
|
|
5141
|
+
const nodeModules = path.dirname(dir);
|
|
5142
|
+
const lib = path.dirname(nodeModules);
|
|
5143
|
+
const prefix = path.dirname(lib);
|
|
5144
|
+
if (path.basename(dir) !== "very-happy-cli" || path.basename(nodeModules) !== "node_modules" || path.basename(lib) !== "lib") return null;
|
|
5145
|
+
if (prefix === lib || path.resolve(prefix) === "/" || !NPM_SAFE_ARG.test(prefix)) return null;
|
|
5146
|
+
return prefix;
|
|
5147
|
+
}
|
|
5148
|
+
function packageDirForBin(realBin) {
|
|
5149
|
+
const packageDir = path.dirname(path.dirname(realBin));
|
|
5150
|
+
return path.basename(path.dirname(realBin)) === "bin" && path.basename(packageDir) === "very-happy-cli" ? packageDir : null;
|
|
5151
|
+
}
|
|
5152
|
+
function installLocationWarnings(facts, version) {
|
|
5153
|
+
const warnings = [];
|
|
5154
|
+
const running = path.resolve(facts.runningPackageDir);
|
|
5155
|
+
const packages = [...new Set(facts.onPath.map(packageDirForBin).filter((dir) => Boolean(dir)).map((dir) => path.resolve(dir)))];
|
|
5156
|
+
if (packages.length > 1) {
|
|
5157
|
+
warnings.push(`Found ${packages.length} very-happy installs on PATH (first one wins): ${packages.join(", ")}. Updating one does not update the others; remove the ones you do not use.`);
|
|
5158
|
+
}
|
|
5159
|
+
if (packages[0] && packages[0] !== running) {
|
|
5160
|
+
warnings.push(`The very-happy command runs ${packages[0]}, but this CLI runs from ${running}.`);
|
|
5161
|
+
}
|
|
5162
|
+
const prefix = globalPrefixForPackage(running);
|
|
5163
|
+
if (prefix && facts.npmGlobalPrefix && path.resolve(facts.npmGlobalPrefix) !== path.resolve(prefix)) {
|
|
5164
|
+
const target = version ? `very-happy-cli@${version}` : "very-happy-cli@latest";
|
|
5165
|
+
warnings.push(`npm install -g writes to ${facts.npmGlobalPrefix}, but this CLI runs from ${prefix}; a plain update will not take effect. Update with: npm install -g --prefix ${prefix} --allow-scripts=very-happy-cli,node-pty ${target} && very-happy daemon start`);
|
|
5166
|
+
}
|
|
5167
|
+
return warnings;
|
|
5168
|
+
}
|
|
5169
|
+
function gatherInstallLocationFacts(runningPackageDir, env = process.env) {
|
|
5170
|
+
if (process.platform === "win32") return null;
|
|
5171
|
+
const onPath = [];
|
|
5172
|
+
for (const dir of (env.PATH ?? "").split(path.delimiter)) {
|
|
5173
|
+
if (!dir) continue;
|
|
5174
|
+
try {
|
|
5175
|
+
const candidate = path.join(dir, "very-happy");
|
|
5176
|
+
if (!node_fs.statSync(candidate).isFile()) continue;
|
|
5177
|
+
const real = node_fs.realpathSync(candidate);
|
|
5178
|
+
if (!onPath.includes(real)) onPath.push(real);
|
|
5179
|
+
} catch {
|
|
5180
|
+
}
|
|
5181
|
+
}
|
|
5182
|
+
let npmGlobalPrefix = null;
|
|
5183
|
+
try {
|
|
5184
|
+
const result = node_child_process.spawnSync("npm", ["prefix", "-g"], { encoding: "utf8", timeout: 5e3, env });
|
|
5185
|
+
const out = result.status === 0 ? result.stdout.trim() : "";
|
|
5186
|
+
npmGlobalPrefix = out && path.isAbsolute(out) && !out.includes("\n") ? out : null;
|
|
5187
|
+
} catch {
|
|
5188
|
+
}
|
|
5189
|
+
return { runningPackageDir, onPath, npmGlobalPrefix };
|
|
5190
|
+
}
|
|
5191
|
+
|
|
5129
5192
|
function printCliUpdateStatus(state) {
|
|
5130
5193
|
const installed = persistence.configuration.currentCliVersion;
|
|
5131
5194
|
const running = state?.startedWithCliVersion ?? null;
|
|
@@ -5143,6 +5206,10 @@ function printCliUpdateStatus(state) {
|
|
|
5143
5206
|
console.log(chalk.yellow(" \u25B3 A newer CLI is available."));
|
|
5144
5207
|
}
|
|
5145
5208
|
if (summary.installCommand) console.log(` Update: ${summary.installCommand}`);
|
|
5209
|
+
const facts = gatherInstallLocationFacts(projectPath.projectPath());
|
|
5210
|
+
for (const warning of facts ? installLocationWarnings(facts, state?.cliUpdate?.recommendedVersion ?? void 0) : []) {
|
|
5211
|
+
console.log(chalk.yellow(` \u26A0 ${warning}`));
|
|
5212
|
+
}
|
|
5146
5213
|
}
|
|
5147
5214
|
function getEnvironmentInfo() {
|
|
5148
5215
|
return shareSafeEnvironmentInfo();
|
|
@@ -5335,8 +5402,8 @@ ${typeLabels[type] || type}:`));
|
|
|
5335
5402
|
}
|
|
5336
5403
|
console.log(chalk.gray(" An external claude command is only needed for native terminal/mirror use."));
|
|
5337
5404
|
try {
|
|
5338
|
-
const { resolveAgentHomesForCli } = await Promise.resolve().then(function () { return require('./agentHome-
|
|
5339
|
-
const { describeAgentHome } = await Promise.resolve().then(function () { return require('./types-
|
|
5405
|
+
const { resolveAgentHomesForCli } = await Promise.resolve().then(function () { return require('./agentHome-D6MSfwnp.cjs'); });
|
|
5406
|
+
const { describeAgentHome } = await Promise.resolve().then(function () { return require('./types-CPubg05Z.cjs'); }).then(function (n) { return n.index; });
|
|
5340
5407
|
const homes = await resolveAgentHomesForCli();
|
|
5341
5408
|
console.log(chalk.green(`\u2713 Claude config dir: ${describeAgentHome(homes.claudeConfigDir)}`));
|
|
5342
5409
|
console.log(chalk.green(`\u2713 Codex home: ${describeAgentHome(homes.codexHome)}`));
|
|
@@ -6047,7 +6114,9 @@ async function sendUserMessage(sessionId, persisted, text, client, options = {})
|
|
|
6047
6114
|
},
|
|
6048
6115
|
meta: {
|
|
6049
6116
|
sentFrom: options.sentFrom ?? "cli",
|
|
6050
|
-
...options.model ? { model: options.model } : {}
|
|
6117
|
+
...options.model !== void 0 ? { model: options.model } : {},
|
|
6118
|
+
...options.permissionMode !== void 0 ? { permissionMode: options.permissionMode } : {},
|
|
6119
|
+
...options.effort !== void 0 ? { effort: options.effort } : {}
|
|
6051
6120
|
}
|
|
6052
6121
|
};
|
|
6053
6122
|
const encrypted = persistence.encodeBase64(persistence.encrypt(
|
|
@@ -6358,13 +6427,22 @@ function startDaemonControlServer({
|
|
|
6358
6427
|
permissionMode: z.z.string().optional(),
|
|
6359
6428
|
// B-069: spawn-origin tag ('assistant' = session_spawn). Recorded on
|
|
6360
6429
|
// the TrackedSession; old clients never send it.
|
|
6361
|
-
spawnedBy: z.z.string().optional()
|
|
6430
|
+
spawnedBy: z.z.string().optional(),
|
|
6431
|
+
// B-492: `very-happy spawn --fork` — same fields the web's fork flow
|
|
6432
|
+
// sends over the machine RPC. Old CLIs never send them.
|
|
6433
|
+
resumeClaudeSessionId: z.z.string().regex(/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i).optional(),
|
|
6434
|
+
resumeCodexThreadId: z.z.string().min(1).max(200).optional(),
|
|
6435
|
+
parentSessionId: z.z.string().min(1).max(200).optional()
|
|
6362
6436
|
}),
|
|
6363
6437
|
response: {
|
|
6364
6438
|
200: z.z.object({
|
|
6365
6439
|
success: z.z.boolean(),
|
|
6366
6440
|
sessionId: z.z.string().optional(),
|
|
6367
|
-
approvedNewDirectoryCreation: z.z.boolean().optional()
|
|
6441
|
+
approvedNewDirectoryCreation: z.z.boolean().optional(),
|
|
6442
|
+
// B-492: true when resumeClaudeSessionId / resumeCodexThreadId was
|
|
6443
|
+
// honoured. A caller that asked for a fork and does not get this
|
|
6444
|
+
// back is talking to an older daemon that spawned a fresh session.
|
|
6445
|
+
resumed: z.z.boolean().optional()
|
|
6368
6446
|
}),
|
|
6369
6447
|
409: z.z.object({
|
|
6370
6448
|
success: z.z.boolean(),
|
|
@@ -6379,13 +6457,14 @@ function startDaemonControlServer({
|
|
|
6379
6457
|
}
|
|
6380
6458
|
}
|
|
6381
6459
|
}, async (request, reply) => {
|
|
6382
|
-
const { directory, sessionId, agent, environmentVariables, variant, forceNew, permissionMode, spawnedBy } = request.body;
|
|
6460
|
+
const { directory, sessionId, agent, environmentVariables, variant, forceNew, permissionMode, spawnedBy, resumeClaudeSessionId, resumeCodexThreadId, parentSessionId } = request.body;
|
|
6383
6461
|
if (!directory && variant !== "assistant") {
|
|
6384
6462
|
reply.code(500);
|
|
6385
6463
|
return { success: false, error: "directory is required" };
|
|
6386
6464
|
}
|
|
6387
6465
|
persistence.logger.debug(`[CONTROL SERVER] Spawn session request: dir=${directory}, sessionId=${sessionId || "new"}, agent=${agent || "default"}, variant=${variant || "none"}, forceNew=${forceNew === true}, spawnedBy=${spawnedBy || "unset"}`);
|
|
6388
|
-
const result = await spawnSession({ directory, sessionId, agent, environmentVariables, variant, forceNew, permissionMode, spawnedBy });
|
|
6466
|
+
const result = await spawnSession({ directory, sessionId, agent, environmentVariables, variant, forceNew, permissionMode, spawnedBy, resumeClaudeSessionId, resumeCodexThreadId, parentSessionId });
|
|
6467
|
+
const resumed = Boolean(resumeClaudeSessionId || resumeCodexThreadId);
|
|
6389
6468
|
switch (result.type) {
|
|
6390
6469
|
case "success":
|
|
6391
6470
|
if (!result.sessionId) {
|
|
@@ -6398,7 +6477,8 @@ function startDaemonControlServer({
|
|
|
6398
6477
|
return {
|
|
6399
6478
|
success: true,
|
|
6400
6479
|
sessionId: result.sessionId,
|
|
6401
|
-
approvedNewDirectoryCreation: true
|
|
6480
|
+
approvedNewDirectoryCreation: true,
|
|
6481
|
+
...resumed ? { resumed: true } : {}
|
|
6402
6482
|
};
|
|
6403
6483
|
case "requestToApproveDirectoryCreation":
|
|
6404
6484
|
reply.code(409);
|
|
@@ -7639,8 +7719,8 @@ function serialTask(task) {
|
|
|
7639
7719
|
};
|
|
7640
7720
|
}
|
|
7641
7721
|
|
|
7642
|
-
function autoUpdateInstallArgs(version) {
|
|
7643
|
-
return ["i", "-g", "--allow-scripts=very-happy-cli,node-pty", `very-happy-cli@${version}`];
|
|
7722
|
+
function autoUpdateInstallArgs(version, prefix) {
|
|
7723
|
+
return ["i", "-g", ...prefix ? [`--prefix=${prefix}`] : [], "--allow-scripts=very-happy-cli,node-pty", `very-happy-cli@${version}`];
|
|
7644
7724
|
}
|
|
7645
7725
|
|
|
7646
7726
|
const processDefaults = {
|
|
@@ -7700,7 +7780,34 @@ const runNpmProcess = (args, deps = processDefaults) => new Promise((resolveResu
|
|
|
7700
7780
|
child.on("close", (code) => done({ code: timedOut ? null : code, stdout, stderr, terminationConfirmed: !timedOut || treeKilled }));
|
|
7701
7781
|
});
|
|
7702
7782
|
const runNpm = (args) => runNpmProcess(args);
|
|
7703
|
-
const defaults = {
|
|
7783
|
+
const defaults = {
|
|
7784
|
+
npm: runNpm,
|
|
7785
|
+
fs: { lstat: promises.lstat, readlink: promises.readlink, unlink: promises.unlink, rm: promises.rm, readFile: promises.readFile, symlink: promises.symlink, access: promises.access },
|
|
7786
|
+
platform: process.platform,
|
|
7787
|
+
runningPackageDir: projectPath.projectPath()
|
|
7788
|
+
};
|
|
7789
|
+
async function runningVersion(deps) {
|
|
7790
|
+
if (!deps.runningPackageDir) return null;
|
|
7791
|
+
try {
|
|
7792
|
+
const manifest = JSON.parse(await deps.fs.readFile(path.join(deps.runningPackageDir, "package.json"), "utf8"));
|
|
7793
|
+
return manifest?.name === "very-happy-cli" && typeof manifest.version === "string" ? manifest.version : null;
|
|
7794
|
+
} catch {
|
|
7795
|
+
return null;
|
|
7796
|
+
}
|
|
7797
|
+
}
|
|
7798
|
+
async function verifyRunningCopy(code, version, deps) {
|
|
7799
|
+
if (code !== 0 || !deps.runningPackageDir) return code;
|
|
7800
|
+
return await runningVersion(deps) === version ? 0 : { failed: "installed_elsewhere" };
|
|
7801
|
+
}
|
|
7802
|
+
async function writable(path, deps) {
|
|
7803
|
+
if (!deps.fs.access) return true;
|
|
7804
|
+
try {
|
|
7805
|
+
await deps.fs.access(path, promises.constants.W_OK);
|
|
7806
|
+
return true;
|
|
7807
|
+
} catch (error) {
|
|
7808
|
+
return error.code === "ENOENT";
|
|
7809
|
+
}
|
|
7810
|
+
}
|
|
7704
7811
|
function ownedCliLink(link, target, packageDir) {
|
|
7705
7812
|
const resolved = path.resolve(path.dirname(link), target);
|
|
7706
7813
|
return resolved.startsWith(path.join(packageDir, "bin") + path.sep);
|
|
@@ -7708,14 +7815,27 @@ function ownedCliLink(link, target, packageDir) {
|
|
|
7708
7815
|
async function installCliSafely(version, deps = defaults) {
|
|
7709
7816
|
const parsed = index.parseExactVersion(version);
|
|
7710
7817
|
if (!parsed) throw new Error("Invalid exact CLI version");
|
|
7711
|
-
const args = autoUpdateInstallArgs(parsed.exact);
|
|
7712
7818
|
if (deps.platform === "win32") {
|
|
7713
|
-
const result2 = await deps.npm(
|
|
7714
|
-
return result2.terminationConfirmed === false ? "blocked" : result2.code;
|
|
7819
|
+
const result2 = await deps.npm(autoUpdateInstallArgs(parsed.exact));
|
|
7820
|
+
return result2.terminationConfirmed === false ? "blocked" : verifyRunningCopy(result2.code, parsed.exact, deps);
|
|
7715
7821
|
}
|
|
7716
|
-
|
|
7822
|
+
let pinnedPrefix;
|
|
7823
|
+
if (deps.runningPackageDir) {
|
|
7824
|
+
const running = globalPrefixForPackage(deps.runningPackageDir);
|
|
7825
|
+
const runningStat = running ? await deps.fs.lstat(deps.runningPackageDir).catch(() => null) : null;
|
|
7826
|
+
if (!running || !runningStat?.isDirectory() || runningStat.isSymbolicLink() || !await runningVersion(deps)) {
|
|
7827
|
+
return { manual: "install_location_unverified" };
|
|
7828
|
+
}
|
|
7829
|
+
for (const path$1 of [path.dirname(deps.runningPackageDir), deps.runningPackageDir, path.join(running, "bin")]) {
|
|
7830
|
+
if (!await writable(path$1, deps)) return { manual: "install_location_not_writable" };
|
|
7831
|
+
}
|
|
7832
|
+
pinnedPrefix = running;
|
|
7833
|
+
}
|
|
7834
|
+
const prefixArgs = pinnedPrefix ? [`--prefix=${pinnedPrefix}`] : [];
|
|
7835
|
+
const args = autoUpdateInstallArgs(parsed.exact, pinnedPrefix);
|
|
7836
|
+
const rootResult = await deps.npm(["root", "-g", ...prefixArgs]);
|
|
7717
7837
|
if (rootResult.terminationConfirmed === false) return "blocked";
|
|
7718
|
-
const prefixResult = await deps.npm(["prefix", "-g"]);
|
|
7838
|
+
const prefixResult = await deps.npm(["prefix", "-g", ...prefixArgs]);
|
|
7719
7839
|
if (prefixResult.terminationConfirmed === false) return "blocked";
|
|
7720
7840
|
const root = rootResult.stdout.trim();
|
|
7721
7841
|
const prefix = prefixResult.stdout.trim();
|
|
@@ -7724,6 +7844,9 @@ async function installCliSafely(version, deps = defaults) {
|
|
|
7724
7844
|
}
|
|
7725
7845
|
if (path.resolve(root) !== path.resolve(prefix, "lib/node_modules")) throw new Error("Unexpected npm root/prefix relationship");
|
|
7726
7846
|
const packageDir = path.join(root, "very-happy-cli");
|
|
7847
|
+
if (deps.runningPackageDir && path.resolve(packageDir) !== path.resolve(deps.runningPackageDir)) {
|
|
7848
|
+
return { manual: "install_location_unverified" };
|
|
7849
|
+
}
|
|
7727
7850
|
const packageStat = await deps.fs.lstat(packageDir).catch((error) => {
|
|
7728
7851
|
if (error.code === "ENOENT") return null;
|
|
7729
7852
|
throw error;
|
|
@@ -7758,7 +7881,7 @@ async function installCliSafely(version, deps = defaults) {
|
|
|
7758
7881
|
return "blocked";
|
|
7759
7882
|
}
|
|
7760
7883
|
result = first.code;
|
|
7761
|
-
if (first.code === 0 || first.code === null) return first.code;
|
|
7884
|
+
if (first.code === 0 || first.code === null) return await verifyRunningCopy(first.code, parsed.exact, deps);
|
|
7762
7885
|
if (!/\b(?:EEXIST|ENOTEMPTY)\b/.test(first.stderr ?? "")) return first.code;
|
|
7763
7886
|
const failedStat = await deps.fs.lstat(packageDir).catch((error) => {
|
|
7764
7887
|
if (error.code === "ENOENT") return null;
|
|
@@ -7774,7 +7897,7 @@ async function installCliSafely(version, deps = defaults) {
|
|
|
7774
7897
|
safeToRestore = false;
|
|
7775
7898
|
return "blocked";
|
|
7776
7899
|
}
|
|
7777
|
-
return result;
|
|
7900
|
+
return await verifyRunningCopy(result, parsed.exact, deps);
|
|
7778
7901
|
} finally {
|
|
7779
7902
|
if (result !== 0 && safeToRestore) {
|
|
7780
7903
|
for (const { link, target } of ownLinks) {
|
|
@@ -7810,7 +7933,7 @@ function createUpdateController(deps) {
|
|
|
7810
7933
|
async function evaluate() {
|
|
7811
7934
|
if (!policy || running) return;
|
|
7812
7935
|
const target = manualVersion ?? policy.autoUpdateVersion ?? null;
|
|
7813
|
-
if (outcome?.version === target && ["failed", "installed"].includes(outcome.state)) {
|
|
7936
|
+
if (outcome?.version === target && ["failed", "installed", "manual_required"].includes(outcome.state)) {
|
|
7814
7937
|
const fingerprint = JSON.stringify([policy.checkedAt, outcome.state, outcome.version, outcome.detail, manualVersion]);
|
|
7815
7938
|
if (fingerprint !== lastPublished) {
|
|
7816
7939
|
lastPublished = fingerprint;
|
|
@@ -7848,6 +7971,11 @@ function createUpdateController(deps) {
|
|
|
7848
7971
|
publish("installing", target);
|
|
7849
7972
|
try {
|
|
7850
7973
|
const code = await deps.install(target);
|
|
7974
|
+
if (code && typeof code === "object") {
|
|
7975
|
+
if ("manual" in code) publish("manual_required", target, code.manual);
|
|
7976
|
+
else publish("failed", target, code.failed);
|
|
7977
|
+
return;
|
|
7978
|
+
}
|
|
7851
7979
|
blocked = code === "blocked";
|
|
7852
7980
|
publish(
|
|
7853
7981
|
blocked ? "manual_required" : code === 0 ? "installed" : "failed",
|
|
@@ -8016,7 +8144,7 @@ function parseJsonObject(text) {
|
|
|
8016
8144
|
return null;
|
|
8017
8145
|
}
|
|
8018
8146
|
}
|
|
8019
|
-
function resolveSdkClaudeBinary(platform = process.platform, arch = process.arch, resolver = (s) => node_module.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index-
|
|
8147
|
+
function resolveSdkClaudeBinary(platform = process.platform, arch = process.arch, resolver = (s) => node_module.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index-CqtfRzug.cjs', document.baseURI).href))).resolve(s)) {
|
|
8020
8148
|
const platformArch = `${platform}-${arch}`;
|
|
8021
8149
|
const candidates = [
|
|
8022
8150
|
`@anthropic-ai/claude-agent-sdk-${platformArch}/claude`,
|
|
@@ -9282,6 +9410,8 @@ ${goal}`;
|
|
|
9282
9410
|
|
|
9283
9411
|
const MAX_LINE_CHARS = 500;
|
|
9284
9412
|
const MAX_ARGS_CHARS = 160;
|
|
9413
|
+
const DEFAULT_LIMITS = { line: MAX_LINE_CHARS, args: MAX_ARGS_CHARS };
|
|
9414
|
+
const NO_LIMITS = { line: Number.POSITIVE_INFINITY, args: Number.POSITIVE_INFINITY };
|
|
9285
9415
|
function truncateText(text, max = MAX_LINE_CHARS) {
|
|
9286
9416
|
const chars = Array.from(text);
|
|
9287
9417
|
if (chars.length <= max) return text;
|
|
@@ -9297,12 +9427,12 @@ function safeJson(value, max) {
|
|
|
9297
9427
|
return "[unserializable]";
|
|
9298
9428
|
}
|
|
9299
9429
|
}
|
|
9300
|
-
function formatMessageBody(body) {
|
|
9430
|
+
function formatMessageBody(body, limits = DEFAULT_LIMITS) {
|
|
9301
9431
|
if (!body || typeof body !== "object") return null;
|
|
9302
9432
|
const b = body;
|
|
9303
9433
|
if (b.role === "user" && b.content?.type === "text" && typeof b.content.text === "string") {
|
|
9304
9434
|
const text = squash(b.content.text);
|
|
9305
|
-
return text.length > 0 ? `user: ${truncateText(text)}` : null;
|
|
9435
|
+
return text.length > 0 ? `user: ${truncateText(text, limits.line)}` : null;
|
|
9306
9436
|
}
|
|
9307
9437
|
if (b.role === "session" && b.content && typeof b.content === "object") {
|
|
9308
9438
|
const env = b.content;
|
|
@@ -9314,18 +9444,18 @@ function formatMessageBody(body) {
|
|
|
9314
9444
|
const text = squash(String(ev.text ?? ""));
|
|
9315
9445
|
if (text.length === 0) return null;
|
|
9316
9446
|
const role = env.role === "user" ? "user" : "assistant";
|
|
9317
|
-
return `${role}: ${truncateText(text)}`;
|
|
9447
|
+
return `${role}: ${truncateText(text, limits.line)}`;
|
|
9318
9448
|
}
|
|
9319
9449
|
case "tool-call-start": {
|
|
9320
9450
|
const name = String(ev.name ?? "tool");
|
|
9321
9451
|
const title = squash(String(ev.title ?? ""));
|
|
9322
|
-
const args = ev.args ? safeJson(ev.args,
|
|
9452
|
+
const args = ev.args ? safeJson(ev.args, limits.args) : "";
|
|
9323
9453
|
const detail = title || args;
|
|
9324
|
-
return `[tool] ${name}${detail ? `: ${truncateText(detail,
|
|
9454
|
+
return `[tool] ${name}${detail ? `: ${truncateText(detail, limits.args)}` : ""}`;
|
|
9325
9455
|
}
|
|
9326
9456
|
case "service": {
|
|
9327
9457
|
const text = squash(String(ev.text ?? ""));
|
|
9328
|
-
return text.length > 0 ? `[service] ${truncateText(text,
|
|
9458
|
+
return text.length > 0 ? `[service] ${truncateText(text, limits.args)}` : null;
|
|
9329
9459
|
}
|
|
9330
9460
|
case "turn-end": {
|
|
9331
9461
|
if (ev.status && ev.status !== "completed") return `[turn ${ev.status}]`;
|
|
@@ -9340,12 +9470,12 @@ function formatMessageBody(body) {
|
|
|
9340
9470
|
switch (d.type) {
|
|
9341
9471
|
case "message": {
|
|
9342
9472
|
const text = squash(String(d.message ?? ""));
|
|
9343
|
-
return text.length > 0 ? `assistant: ${truncateText(text)}` : null;
|
|
9473
|
+
return text.length > 0 ? `assistant: ${truncateText(text, limits.line)}` : null;
|
|
9344
9474
|
}
|
|
9345
9475
|
case "tool-call":
|
|
9346
|
-
return `[tool] ${String(d.name ?? "tool")}: ${safeJson(d.input,
|
|
9476
|
+
return `[tool] ${String(d.name ?? "tool")}: ${safeJson(d.input, limits.args)}`;
|
|
9347
9477
|
case "permission-request":
|
|
9348
|
-
return `[permission] ${String(d.toolName ?? "")}: ${truncateText(squash(String(d.description ?? "")),
|
|
9478
|
+
return `[permission] ${String(d.toolName ?? "")}: ${truncateText(squash(String(d.description ?? "")), limits.args)}`;
|
|
9349
9479
|
default:
|
|
9350
9480
|
return null;
|
|
9351
9481
|
}
|
|
@@ -9356,22 +9486,111 @@ function formatMessageBody(body) {
|
|
|
9356
9486
|
const texts = msg.content.filter((c) => c?.type === "text" && typeof c.text === "string").map((c) => squash(c.text)).filter((t) => t.length > 0);
|
|
9357
9487
|
if (texts.length > 0) {
|
|
9358
9488
|
const role = msg.role === "user" ? "user" : "assistant";
|
|
9359
|
-
return `${role}: ${truncateText(texts.join(" "))}`;
|
|
9489
|
+
return `${role}: ${truncateText(texts.join(" "), limits.line)}`;
|
|
9360
9490
|
}
|
|
9361
9491
|
}
|
|
9362
9492
|
return null;
|
|
9363
9493
|
}
|
|
9364
9494
|
return null;
|
|
9365
9495
|
}
|
|
9366
|
-
function formatTranscript(bodies) {
|
|
9496
|
+
function formatTranscript(bodies, options = {}) {
|
|
9497
|
+
const limits = options.full ? NO_LIMITS : DEFAULT_LIMITS;
|
|
9367
9498
|
const lines = [];
|
|
9368
9499
|
for (const body of bodies) {
|
|
9369
|
-
const line = formatMessageBody(body);
|
|
9500
|
+
const line = formatMessageBody(body, limits);
|
|
9370
9501
|
if (line !== null) lines.push(line);
|
|
9371
9502
|
}
|
|
9372
9503
|
return lines.join("\n");
|
|
9373
9504
|
}
|
|
9374
9505
|
|
|
9506
|
+
function asRecord(value) {
|
|
9507
|
+
return value && typeof value === "object" ? value : null;
|
|
9508
|
+
}
|
|
9509
|
+
function sessionEnvelope(body) {
|
|
9510
|
+
const b = asRecord(body);
|
|
9511
|
+
if (!b || b.role !== "session") return null;
|
|
9512
|
+
const env = asRecord(b.content);
|
|
9513
|
+
if (!env) return null;
|
|
9514
|
+
const ev = asRecord(env.ev);
|
|
9515
|
+
return ev && typeof ev.t === "string" ? { role: env.role, ev } : null;
|
|
9516
|
+
}
|
|
9517
|
+
function isUserPrompt(body) {
|
|
9518
|
+
const b = asRecord(body);
|
|
9519
|
+
return !!b && b.role === "user" && b.content?.type === "text" && typeof b.content.text === "string";
|
|
9520
|
+
}
|
|
9521
|
+
function agentPiece(body) {
|
|
9522
|
+
const env = sessionEnvelope(body);
|
|
9523
|
+
if (env && env.role !== "user") {
|
|
9524
|
+
if (env.ev.t === "text" && !env.ev.thinking) {
|
|
9525
|
+
const text = String(env.ev.text ?? "");
|
|
9526
|
+
return text.trim().length > 0 ? { kind: "text", text } : null;
|
|
9527
|
+
}
|
|
9528
|
+
if (env.ev.t === "tool-call-start") return { kind: "tool" };
|
|
9529
|
+
return null;
|
|
9530
|
+
}
|
|
9531
|
+
const b = asRecord(body);
|
|
9532
|
+
if (b?.role === "agent" && b.content?.type === "acp") {
|
|
9533
|
+
const d = asRecord(b.content.data);
|
|
9534
|
+
if (d?.type === "message") {
|
|
9535
|
+
const text = String(d.message ?? "");
|
|
9536
|
+
return text.trim().length > 0 ? { kind: "text", text } : null;
|
|
9537
|
+
}
|
|
9538
|
+
if (d?.type === "tool-call") return { kind: "tool" };
|
|
9539
|
+
}
|
|
9540
|
+
return null;
|
|
9541
|
+
}
|
|
9542
|
+
function analyzeLatestTurn(entries) {
|
|
9543
|
+
const lastSeq = entries.length > 0 ? entries[entries.length - 1].seq : 0;
|
|
9544
|
+
let userIndex = -1;
|
|
9545
|
+
for (let i = entries.length - 1; i >= 0; i--) {
|
|
9546
|
+
if (isUserPrompt(entries[i].body)) {
|
|
9547
|
+
userIndex = i;
|
|
9548
|
+
break;
|
|
9549
|
+
}
|
|
9550
|
+
}
|
|
9551
|
+
let ended = false;
|
|
9552
|
+
let status = null;
|
|
9553
|
+
let error = null;
|
|
9554
|
+
let texts = [];
|
|
9555
|
+
let lastMarker = null;
|
|
9556
|
+
let startedAfterPrompt = false;
|
|
9557
|
+
const emitsStarts = entries.some((entry) => sessionEnvelope(entry.body)?.ev?.t === "turn-start");
|
|
9558
|
+
for (let i = userIndex + 1; i < entries.length; i++) {
|
|
9559
|
+
const body = entries[i].body;
|
|
9560
|
+
const env = sessionEnvelope(body);
|
|
9561
|
+
if (env?.ev?.t === "turn-start") {
|
|
9562
|
+
lastMarker = "start";
|
|
9563
|
+
startedAfterPrompt = true;
|
|
9564
|
+
ended = false;
|
|
9565
|
+
status = null;
|
|
9566
|
+
error = null;
|
|
9567
|
+
texts = [];
|
|
9568
|
+
continue;
|
|
9569
|
+
}
|
|
9570
|
+
if (env?.ev?.t === "turn-end") {
|
|
9571
|
+
lastMarker = "end";
|
|
9572
|
+
if (userIndex >= 0 && emitsStarts && !startedAfterPrompt) continue;
|
|
9573
|
+
ended = true;
|
|
9574
|
+
status = typeof env.ev.status === "string" ? env.ev.status : null;
|
|
9575
|
+
error = typeof env.ev.error === "string" ? env.ev.error : null;
|
|
9576
|
+
continue;
|
|
9577
|
+
}
|
|
9578
|
+
const piece = agentPiece(body);
|
|
9579
|
+
if (!piece) continue;
|
|
9580
|
+
if (piece.kind === "tool") texts = [];
|
|
9581
|
+
else texts.push(piece.text);
|
|
9582
|
+
}
|
|
9583
|
+
if (userIndex < 0) ended = lastMarker === "end";
|
|
9584
|
+
return {
|
|
9585
|
+
userSeq: userIndex >= 0 ? entries[userIndex].seq : null,
|
|
9586
|
+
ended,
|
|
9587
|
+
status: ended ? status : null,
|
|
9588
|
+
error: ended ? error : null,
|
|
9589
|
+
answer: texts.join("\n\n").trim(),
|
|
9590
|
+
lastSeq
|
|
9591
|
+
};
|
|
9592
|
+
}
|
|
9593
|
+
|
|
9375
9594
|
const USER_SOCKET_CONNECT_TIMEOUT_MS = 15e3;
|
|
9376
9595
|
async function openUserScopedSocket(token, options = {}) {
|
|
9377
9596
|
const socket = socket_ioClient.io(persistence.configuration.serverUrl, {
|
|
@@ -9717,19 +9936,21 @@ async function bearerToken() {
|
|
|
9717
9936
|
if (!credentials) throw new Error("CLI is not authenticated (no ~/.happy/access.key)");
|
|
9718
9937
|
return credentials.token;
|
|
9719
9938
|
}
|
|
9720
|
-
|
|
9939
|
+
function requirePersisted(sessionId) {
|
|
9721
9940
|
const persisted = persistence.readPersistedSessions()[sessionId];
|
|
9722
9941
|
if (!persisted) {
|
|
9723
9942
|
throw new Error(
|
|
9724
9943
|
`No local key for session ${sessionId} \u2014 it was not spawned by this machine's daemon (or is older than 14 days).`
|
|
9725
9944
|
);
|
|
9726
9945
|
}
|
|
9727
|
-
|
|
9946
|
+
return persisted;
|
|
9947
|
+
}
|
|
9948
|
+
async function readSessionLog(sessionId, persisted, limit) {
|
|
9728
9949
|
const token = await bearerToken();
|
|
9729
9950
|
const response = await axios.get(
|
|
9730
9951
|
`${persistence.configuration.serverUrl}/v3/sessions/${encodeURIComponent(sessionId)}/messages`,
|
|
9731
9952
|
{
|
|
9732
|
-
params: { before_seq: 2147483647, limit
|
|
9953
|
+
params: { before_seq: 2147483647, limit },
|
|
9733
9954
|
headers: {
|
|
9734
9955
|
"Authorization": `Bearer ${token}`,
|
|
9735
9956
|
"X-Happy-Client": `${SESSION_OPS_CLIENT}/${persistence.configuration.currentCliVersion}`
|
|
@@ -9740,21 +9961,62 @@ async function readSessionTranscript(sessionId, limit) {
|
|
|
9740
9961
|
const messages = Array.isArray(response.data?.messages) ? response.data.messages : [];
|
|
9741
9962
|
messages.reverse();
|
|
9742
9963
|
const key = persistence.decodeBase64(persisted.encryptionKey);
|
|
9743
|
-
|
|
9744
|
-
|
|
9745
|
-
if (message.content?.t !== "encrypted") return null;
|
|
9964
|
+
return messages.map((message) => {
|
|
9965
|
+
if (message.content?.t !== "encrypted") return { seq: message.seq, body: null };
|
|
9746
9966
|
try {
|
|
9747
|
-
return persistence.decrypt(key, persisted.encryptionVariant, persistence.decodeBase64(message.content.c));
|
|
9967
|
+
return { seq: message.seq, body: persistence.decrypt(key, persisted.encryptionVariant, persistence.decodeBase64(message.content.c)) };
|
|
9748
9968
|
} catch {
|
|
9749
|
-
return null;
|
|
9969
|
+
return { seq: message.seq, body: null };
|
|
9750
9970
|
}
|
|
9751
9971
|
});
|
|
9972
|
+
}
|
|
9973
|
+
const TURN_WINDOW = 500;
|
|
9974
|
+
async function readSessionTranscript(sessionId, limit, options = {}) {
|
|
9975
|
+
const persisted = requirePersisted(sessionId);
|
|
9976
|
+
const bounded = Math.max(1, Math.min(MAX_READ_LIMIT, Math.floor(limit)));
|
|
9977
|
+
const entries = await readSessionLog(sessionId, persisted, Math.max(bounded, TURN_WINDOW));
|
|
9978
|
+
const shown = entries.slice(-bounded);
|
|
9979
|
+
const live = await index.listDaemonSessions();
|
|
9752
9980
|
return {
|
|
9753
9981
|
summary: toSummary(sessionId, persisted, sessionLiveness(live, sessionId)),
|
|
9754
|
-
messageCount:
|
|
9755
|
-
transcript: formatTranscript(
|
|
9982
|
+
messageCount: shown.length,
|
|
9983
|
+
transcript: formatTranscript(shown.map((entry) => entry.body), { full: options.full }),
|
|
9984
|
+
turn: analyzeLatestTurn(entries)
|
|
9756
9985
|
};
|
|
9757
9986
|
}
|
|
9987
|
+
async function readSessionMetadata(sessionId, persisted) {
|
|
9988
|
+
const token = await bearerToken();
|
|
9989
|
+
const response = await axios.get(`${persistence.configuration.serverUrl}/v1/sessions/${encodeURIComponent(sessionId)}`, {
|
|
9990
|
+
headers: {
|
|
9991
|
+
"Authorization": `Bearer ${token}`,
|
|
9992
|
+
"X-Happy-Client": `${SESSION_OPS_CLIENT}/${persistence.configuration.currentCliVersion}`
|
|
9993
|
+
},
|
|
9994
|
+
timeout: 15e3
|
|
9995
|
+
});
|
|
9996
|
+
const ciphertext = response.data?.session?.metadata;
|
|
9997
|
+
if (typeof ciphertext !== "string" || ciphertext.length === 0) return null;
|
|
9998
|
+
return persistence.decrypt(persistence.decodeBase64(persisted.encryptionKey), persisted.encryptionVariant, persistence.decodeBase64(ciphertext));
|
|
9999
|
+
}
|
|
10000
|
+
class TurnWaitTimeoutError extends Error {
|
|
10001
|
+
constructor(sessionId, timeoutMs, turn) {
|
|
10002
|
+
super(`Session ${sessionId}: the latest turn did not end within ${Math.round(timeoutMs / 1e3)}s`);
|
|
10003
|
+
this.sessionId = sessionId;
|
|
10004
|
+
this.timeoutMs = timeoutMs;
|
|
10005
|
+
this.turn = turn;
|
|
10006
|
+
}
|
|
10007
|
+
}
|
|
10008
|
+
async function waitForTurnEnd(sessionId, options) {
|
|
10009
|
+
const persisted = requirePersisted(sessionId);
|
|
10010
|
+
const pollMs = options.pollMs ?? 3e3;
|
|
10011
|
+
const sleep = options.sleep ?? ((ms) => new Promise((resolve) => setTimeout(resolve, ms)));
|
|
10012
|
+
const deadline = Date.now() + options.timeoutMs;
|
|
10013
|
+
while (true) {
|
|
10014
|
+
const turn = analyzeLatestTurn(await readSessionLog(sessionId, persisted, TURN_WINDOW));
|
|
10015
|
+
if (turn.ended) return turn;
|
|
10016
|
+
if (Date.now() + pollMs > deadline) throw new TurnWaitTimeoutError(sessionId, options.timeoutMs, turn);
|
|
10017
|
+
await sleep(pollMs);
|
|
10018
|
+
}
|
|
10019
|
+
}
|
|
9758
10020
|
async function stopSession(sessionId) {
|
|
9759
10021
|
return await index.stopDaemonSession(sessionId);
|
|
9760
10022
|
}
|
|
@@ -12492,7 +12754,7 @@ function registerSideQuestionHandler(rpc, deps) {
|
|
|
12492
12754
|
const retainMs = deps.retainMs ?? SIDE_QUESTION_RETAIN_MS;
|
|
12493
12755
|
const maxRunMs = deps.maxRunMs ?? SIDE_QUESTION_MAX_RUN_MS;
|
|
12494
12756
|
const fork = deps.run ?? (async (input) => {
|
|
12495
|
-
const { query } = await Promise.resolve().then(function () { return require('./index-
|
|
12757
|
+
const { query } = await Promise.resolve().then(function () { return require('./index-vyRqLjDv.cjs'); });
|
|
12496
12758
|
return runSideQuestion(query, input);
|
|
12497
12759
|
});
|
|
12498
12760
|
const run = async (input, live) => {
|
|
@@ -12611,7 +12873,7 @@ const MAX_TITLE_CHARS = 60;
|
|
|
12611
12873
|
const GENERATION_TIMEOUT_MS = 3e4;
|
|
12612
12874
|
function resolveClaudeBinary() {
|
|
12613
12875
|
try {
|
|
12614
|
-
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-
|
|
12876
|
+
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-CqtfRzug.cjs', document.baseURI).href)));
|
|
12615
12877
|
const utilsPath = path.resolve(path.join(projectPath.projectPath(), "scripts", "claude_version_utils.cjs"));
|
|
12616
12878
|
const { getClaudeCliPath } = require$1(utilsPath);
|
|
12617
12879
|
const path$1 = getClaudeCliPath();
|
|
@@ -14840,9 +15102,9 @@ function resolveLocalSignupBootstrap(configuredMode, configuredInviteCodes, gene
|
|
|
14840
15102
|
};
|
|
14841
15103
|
}
|
|
14842
15104
|
|
|
14843
|
-
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-
|
|
15105
|
+
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-CqtfRzug.cjs', document.baseURI).href)));
|
|
14844
15106
|
const __dirname$1 = path.dirname(__filename$1);
|
|
14845
|
-
const require_ = node_module.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index-
|
|
15107
|
+
const require_ = node_module.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index-CqtfRzug.cjs', document.baseURI).href)));
|
|
14846
15108
|
const PRISMA_QUERY_ENGINE_FILES = {
|
|
14847
15109
|
"arm64-darwin": "libquery_engine-darwin-arm64.dylib.node",
|
|
14848
15110
|
"x64-darwin": "libquery_engine-darwin.dylib.node",
|
|
@@ -17780,7 +18042,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
|
|
|
17780
18042
|
return;
|
|
17781
18043
|
} else if (subcommand === "install-terminal-hooks") {
|
|
17782
18044
|
try {
|
|
17783
|
-
const { installTerminalHooks, parseTerminalHooksArgs, TERMINAL_HOOKS_HELP } = await Promise.resolve().then(function () { return require('./installTerminalHooks-
|
|
18045
|
+
const { installTerminalHooks, parseTerminalHooksArgs, TERMINAL_HOOKS_HELP } = await Promise.resolve().then(function () { return require('./installTerminalHooks-Bf_adbl3.cjs'); });
|
|
17784
18046
|
const command = parseTerminalHooksArgs(args.slice(1));
|
|
17785
18047
|
if (command.action === "help") {
|
|
17786
18048
|
console.log(TERMINAL_HOOKS_HELP);
|
|
@@ -17797,7 +18059,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
|
|
|
17797
18059
|
}
|
|
17798
18060
|
} else if (subcommand === "agent-home") {
|
|
17799
18061
|
try {
|
|
17800
|
-
const { parseAgentHomeArgs, runAgentHomeCommand } = await Promise.resolve().then(function () { return require('./agentHome-
|
|
18062
|
+
const { parseAgentHomeArgs, runAgentHomeCommand } = await Promise.resolve().then(function () { return require('./agentHome-D6MSfwnp.cjs'); });
|
|
17801
18063
|
await runAgentHomeCommand(parseAgentHomeArgs(args.slice(1)));
|
|
17802
18064
|
process.exit(0);
|
|
17803
18065
|
} catch (error) {
|
|
@@ -17806,7 +18068,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
|
|
|
17806
18068
|
}
|
|
17807
18069
|
} else if (subcommand === "spawn") {
|
|
17808
18070
|
try {
|
|
17809
|
-
const { handleSpawnCommand } = await Promise.resolve().then(function () { return require('./spawn-
|
|
18071
|
+
const { handleSpawnCommand } = await Promise.resolve().then(function () { return require('./spawn-DH6_p4-f.cjs'); });
|
|
17810
18072
|
await handleSpawnCommand(args.slice(1));
|
|
17811
18073
|
} catch (error) {
|
|
17812
18074
|
console.error(chalk.red("Error:"), error instanceof Error ? error.message : "Unknown error");
|
|
@@ -17818,7 +18080,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
|
|
|
17818
18080
|
return;
|
|
17819
18081
|
} else if (subcommand === "sessions") {
|
|
17820
18082
|
try {
|
|
17821
|
-
const { handleSessionsCommand } = await Promise.resolve().then(function () { return require('./sessions-
|
|
18083
|
+
const { handleSessionsCommand } = await Promise.resolve().then(function () { return require('./sessions-B3vP18kz.cjs'); });
|
|
17822
18084
|
await handleSessionsCommand(args.slice(1));
|
|
17823
18085
|
} catch (error) {
|
|
17824
18086
|
console.error(chalk.red("Error:"), error instanceof Error ? error.message : "Unknown error");
|
|
@@ -17830,7 +18092,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
|
|
|
17830
18092
|
return;
|
|
17831
18093
|
} else if (subcommand === "send") {
|
|
17832
18094
|
try {
|
|
17833
|
-
const { handleSendCommand } = await Promise.resolve().then(function () { return require('./send-
|
|
18095
|
+
const { handleSendCommand } = await Promise.resolve().then(function () { return require('./send-aUkjhey7.cjs'); });
|
|
17834
18096
|
await handleSendCommand(args.slice(1));
|
|
17835
18097
|
} catch (error) {
|
|
17836
18098
|
console.error(chalk.red("Error:"), error instanceof Error ? error.message : "Unknown error");
|
|
@@ -17936,9 +18198,9 @@ Conversation history is preserved on the server, but in-flight tool calls are in
|
|
|
17936
18198
|
if (geminiSubcommand === "project" && args[2] === "set" && args[3]) {
|
|
17937
18199
|
const projectId = args[3];
|
|
17938
18200
|
try {
|
|
17939
|
-
const { saveGoogleCloudProjectToConfig } = await Promise.resolve().then(function () { return require('./config-
|
|
17940
|
-
const { readCredentialsForConfiguredRelay: readCredentialsForConfiguredRelay2 } = await Promise.resolve().then(function () { return require('./limits-
|
|
17941
|
-
const { ApiClient: ApiClient2 } = await Promise.resolve().then(function () { return require('./types-
|
|
18201
|
+
const { saveGoogleCloudProjectToConfig } = await Promise.resolve().then(function () { return require('./config-Cadw1sAk.cjs'); });
|
|
18202
|
+
const { readCredentialsForConfiguredRelay: readCredentialsForConfiguredRelay2 } = await Promise.resolve().then(function () { return require('./limits-DwcY3kyi.cjs'); }).then(function (n) { return n.persistence; });
|
|
18203
|
+
const { ApiClient: ApiClient2 } = await Promise.resolve().then(function () { return require('./types-CPubg05Z.cjs'); }).then(function (n) { return n.api; });
|
|
17942
18204
|
let userEmail = void 0;
|
|
17943
18205
|
try {
|
|
17944
18206
|
const credentials = await readCredentialsForConfiguredRelay2();
|
|
@@ -17969,7 +18231,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
|
|
|
17969
18231
|
}
|
|
17970
18232
|
if (geminiSubcommand === "project" && args[2] === "get") {
|
|
17971
18233
|
try {
|
|
17972
|
-
const { readGeminiLocalConfig } = await Promise.resolve().then(function () { return require('./config-
|
|
18234
|
+
const { readGeminiLocalConfig } = await Promise.resolve().then(function () { return require('./config-Cadw1sAk.cjs'); });
|
|
17973
18235
|
const config = readGeminiLocalConfig();
|
|
17974
18236
|
if (config.googleCloudProject) {
|
|
17975
18237
|
console.log(`Current Google Cloud Project: ${config.googleCloudProject}`);
|
|
@@ -18009,7 +18271,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
|
|
|
18009
18271
|
process.exit(0);
|
|
18010
18272
|
}
|
|
18011
18273
|
try {
|
|
18012
|
-
const { runGemini } = await Promise.resolve().then(function () { return require('./runGemini-
|
|
18274
|
+
const { runGemini } = await Promise.resolve().then(function () { return require('./runGemini-DuwdVV1O.cjs'); });
|
|
18013
18275
|
let startedBy = void 0;
|
|
18014
18276
|
for (let i = 1; i < args.length; i++) {
|
|
18015
18277
|
if (args[i] === "--started-by") {
|
|
@@ -18032,7 +18294,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
|
|
|
18032
18294
|
} else if (subcommand === "pi") {
|
|
18033
18295
|
if (args[1] === "--terminal") {
|
|
18034
18296
|
try {
|
|
18035
|
-
const { runPiTerminal } = await Promise.resolve().then(function () { return require('./piTerminal-
|
|
18297
|
+
const { runPiTerminal } = await Promise.resolve().then(function () { return require('./piTerminal-kDSd_r9X.cjs'); });
|
|
18036
18298
|
process.exitCode = await runPiTerminal(args.slice(2));
|
|
18037
18299
|
} catch (error) {
|
|
18038
18300
|
console.error(chalk.red("Error:"), error instanceof Error ? error.message : "Unknown error");
|
|
@@ -18049,7 +18311,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
|
|
|
18049
18311
|
}
|
|
18050
18312
|
};
|
|
18051
18313
|
try {
|
|
18052
|
-
const { runAcp, resolveAcpAgentConfig } = await Promise.resolve().then(function () { return require('./index-
|
|
18314
|
+
const { runAcp, resolveAcpAgentConfig } = await Promise.resolve().then(function () { return require('./index-BKGspSWk.cjs'); });
|
|
18053
18315
|
const parsed = parsePiRunnerArgs(args.slice(1));
|
|
18054
18316
|
const resolved = resolveAcpAgentConfig(["pi", ...parsed.passthrough]);
|
|
18055
18317
|
const { credentials } = await authAndSetupMachineIfNeeded();
|
|
@@ -18077,7 +18339,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
|
|
|
18077
18339
|
return;
|
|
18078
18340
|
} else if (subcommand === "acp") {
|
|
18079
18341
|
try {
|
|
18080
|
-
const { runAcp, resolveAcpAgentConfig } = await Promise.resolve().then(function () { return require('./index-
|
|
18342
|
+
const { runAcp, resolveAcpAgentConfig } = await Promise.resolve().then(function () { return require('./index-BKGspSWk.cjs'); });
|
|
18081
18343
|
let startedBy = void 0;
|
|
18082
18344
|
let verbose = false;
|
|
18083
18345
|
const acpArgs = [];
|
|
@@ -18117,7 +18379,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
|
|
|
18117
18379
|
return;
|
|
18118
18380
|
} else if (subcommand === "openclaw") {
|
|
18119
18381
|
try {
|
|
18120
|
-
const { runOpenClaw } = await Promise.resolve().then(function () { return require('./runOpenClaw-
|
|
18382
|
+
const { runOpenClaw } = await Promise.resolve().then(function () { return require('./runOpenClaw-BsvtCE_H.cjs'); });
|
|
18121
18383
|
let startedBy = void 0;
|
|
18122
18384
|
let verbose = false;
|
|
18123
18385
|
let gatewayUrl;
|
|
@@ -18168,7 +18430,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
|
|
|
18168
18430
|
return;
|
|
18169
18431
|
} else if (subcommand === "todo") {
|
|
18170
18432
|
try {
|
|
18171
|
-
const { handleTodoCommand } = await Promise.resolve().then(function () { return require('./todo-
|
|
18433
|
+
const { handleTodoCommand } = await Promise.resolve().then(function () { return require('./todo-Bcc2XxGh.cjs'); });
|
|
18172
18434
|
await handleTodoCommand(args.slice(1));
|
|
18173
18435
|
} catch (error) {
|
|
18174
18436
|
console.error(JSON.stringify({ error: error instanceof Error ? error.message : "Todo command failed" }));
|
|
@@ -18177,7 +18439,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
|
|
|
18177
18439
|
return;
|
|
18178
18440
|
} else if (subcommand === "teams") {
|
|
18179
18441
|
try {
|
|
18180
|
-
const { handleTeamsCommand } = await Promise.resolve().then(function () { return require('./teams-
|
|
18442
|
+
const { handleTeamsCommand } = await Promise.resolve().then(function () { return require('./teams-BW8D1n3o.cjs'); });
|
|
18181
18443
|
await handleTeamsCommand(args.slice(1));
|
|
18182
18444
|
} catch (error) {
|
|
18183
18445
|
console.error(error instanceof Error ? error.message : "Teams command failed");
|
|
@@ -18186,7 +18448,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
|
|
|
18186
18448
|
return;
|
|
18187
18449
|
} else if (subcommand === "mcp" && (args.length === 1 || args.length === 2 && args[1] === "--terminal-tools")) {
|
|
18188
18450
|
try {
|
|
18189
|
-
const { handleMcpCommand } = await Promise.resolve().then(function () { return require('./mcp-
|
|
18451
|
+
const { handleMcpCommand } = await Promise.resolve().then(function () { return require('./mcp-CMxEZ6-0.cjs'); });
|
|
18190
18452
|
await handleMcpCommand(args[1] === "--terminal-tools");
|
|
18191
18453
|
} catch (error) {
|
|
18192
18454
|
process.stderr.write(`[very-happy mcp] Fatal: ${error instanceof Error ? error.message : String(error)}
|
|
@@ -18572,6 +18834,7 @@ exports.SPAWN_AGENTS = SPAWN_AGENTS;
|
|
|
18572
18834
|
exports.StreamRelay = StreamRelay;
|
|
18573
18835
|
exports.TEAM_SKILL = TEAM_SKILL;
|
|
18574
18836
|
exports.TitleGenerator = TitleGenerator;
|
|
18837
|
+
exports.TurnWaitTimeoutError = TurnWaitTimeoutError;
|
|
18575
18838
|
exports.appendStagedAttachmentsToPrompt = appendStagedAttachmentsToPrompt;
|
|
18576
18839
|
exports.archiveSession = archiveSession;
|
|
18577
18840
|
exports.checkPreviewPath = checkPreviewPath;
|
|
@@ -18583,6 +18846,7 @@ exports.listAccountSessions = listAccountSessions;
|
|
|
18583
18846
|
exports.listSessions = listSessions;
|
|
18584
18847
|
exports.normalizeAcpPermissionMode = normalizeAcpPermissionMode;
|
|
18585
18848
|
exports.query = query;
|
|
18849
|
+
exports.readSessionMetadata = readSessionMetadata;
|
|
18586
18850
|
exports.readSessionTranscript = readSessionTranscript;
|
|
18587
18851
|
exports.registerAgentAttachmentDownloads = registerAgentAttachmentDownloads;
|
|
18588
18852
|
exports.registerAssistantSessionTools = registerAssistantSessionTools;
|
|
@@ -18598,4 +18862,5 @@ exports.startHappyServer = startHappyServer;
|
|
|
18598
18862
|
exports.stopSession = stopSession;
|
|
18599
18863
|
exports.tmuxSupportsSessionEnv = tmuxSupportsSessionEnv;
|
|
18600
18864
|
exports.waitForSessionKey = waitForSessionKey;
|
|
18865
|
+
exports.waitForTurnEnd = waitForTurnEnd;
|
|
18601
18866
|
exports.writeSessionModeFile = writeSessionModeFile;
|