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.
Files changed (50) hide show
  1. package/dist/{AcpBackend-Baqb8dNm.mjs → AcpBackend-BjTA5gUB.mjs} +2 -2
  2. package/dist/{AcpBackend-CnZpEfGd.cjs → AcpBackend-blE9IEod.cjs} +2 -2
  3. package/dist/{AcpSessionManager-CC6mdFXs.mjs → AcpSessionManager-D-9mrp40.mjs} +1 -1
  4. package/dist/{AcpSessionManager-e2vxmIbj.cjs → AcpSessionManager-bF8PYu_B.cjs} +1 -1
  5. package/dist/{agentGuidance--QIi_rZ2.cjs → agentGuidance-BXa9ikrZ.cjs} +1 -1
  6. package/dist/{agentGuidance-oMVJvUl7.mjs → agentGuidance-Dvo3cZMW.mjs} +1 -1
  7. package/dist/{agentHome-CKSPsS8d.mjs → agentHome-CeFDNzvq.mjs} +2 -2
  8. package/dist/{agentHome-3kRCtzOL.cjs → agentHome-D6MSfwnp.cjs} +2 -2
  9. package/dist/codex/happyMcpStdioBridge.cjs +2 -2
  10. package/dist/codex/happyMcpStdioBridge.mjs +2 -2
  11. package/dist/{config-C8jpk6IA.mjs → config-C-A1XF62.mjs} +4 -4
  12. package/dist/{config-CzJZcvTO.cjs → config-Cadw1sAk.cjs} +4 -4
  13. package/dist/{index-DgK4KX-Z.cjs → index-BKGspSWk.cjs} +7 -7
  14. package/dist/{index-Dfkyar7S.mjs → index-CIyjJy8D.mjs} +338 -76
  15. package/dist/{index-CyfXsCXl.cjs → index-CqtfRzug.cjs} +338 -73
  16. package/dist/{index-DrVq0CqK.mjs → index-DEp6CmmS.mjs} +8 -8
  17. package/dist/{index-BPCXUrEe.mjs → index-DYQgcgL2.mjs} +4 -4
  18. package/dist/{index-DBN2Zpqc.cjs → index-vyRqLjDv.cjs} +4 -4
  19. package/dist/index.cjs +4 -4
  20. package/dist/index.mjs +4 -4
  21. package/dist/{installTerminalHooks-kdAoTfNT.cjs → installTerminalHooks-Bf_adbl3.cjs} +4 -4
  22. package/dist/{installTerminalHooks-COqkLz6f.mjs → installTerminalHooks-Ch_yTtEA.mjs} +4 -4
  23. package/dist/lib.cjs +2 -2
  24. package/dist/lib.mjs +2 -2
  25. package/dist/{limits-BXI1Gzvd.mjs → limits-DS-bnYYp.mjs} +7 -7
  26. package/dist/{limits-FZWhlsBu.cjs → limits-DwcY3kyi.cjs} +7 -7
  27. package/dist/{mcp-DoLZbbZp.cjs → mcp-CMxEZ6-0.cjs} +4 -4
  28. package/dist/{mcp-Dfnoirpi.mjs → mcp-zu8n8TkR.mjs} +4 -4
  29. package/dist/{piRuntime-BK6YZm2X.mjs → piRuntime-Cu6cXZ6N.mjs} +2 -2
  30. package/dist/{piRuntime-DmE4ysfG.cjs → piRuntime-D3ny0mVg.cjs} +2 -2
  31. package/dist/{piTerminal-Bczubq2n.mjs → piTerminal-M677UP7y.mjs} +6 -6
  32. package/dist/{piTerminal-qQAzQwIU.cjs → piTerminal-kDSd_r9X.cjs} +6 -6
  33. package/dist/{runGemini-ComTu0EB.cjs → runGemini-DuwdVV1O.cjs} +6 -6
  34. package/dist/{runGemini-Cce_pjTs.mjs → runGemini-DvJwQVGp.mjs} +6 -6
  35. package/dist/{runOpenClaw-DXP5_chb.mjs → runOpenClaw-BG82bF18.mjs} +5 -5
  36. package/dist/{runOpenClaw-M3YlDt8z.cjs → runOpenClaw-BsvtCE_H.cjs} +5 -5
  37. package/dist/{send-0LrSwGgr.cjs → send-aUkjhey7.cjs} +20 -6
  38. package/dist/{send-DDD57Cr_.mjs → send-o6WM-1G8.mjs} +20 -6
  39. package/dist/{sessions-2Bkau9T4.cjs → sessions-B3vP18kz.cjs} +56 -10
  40. package/dist/{sessions-ClBPEtz2.mjs → sessions-DlU3foY_.mjs} +56 -10
  41. package/dist/{spawn-Cm3Da8Ge.cjs → spawn-DH6_p4-f.cjs} +166 -27
  42. package/dist/spawn-DxHIIqhi.mjs +397 -0
  43. package/dist/{teams-DKKeIG-u.cjs → teams-BW8D1n3o.cjs} +4 -4
  44. package/dist/{teams-DyBjdXI3.mjs → teams-DoAA_CcN.mjs} +4 -4
  45. package/dist/{todo-8RgCTDxH.cjs → todo-Bcc2XxGh.cjs} +3 -3
  46. package/dist/{todo-jXHGGH89.mjs → todo-BhJbG5eq.mjs} +3 -3
  47. package/dist/{types-ipzMqciq.mjs → types-BN3eiipi.mjs} +46 -3
  48. package/dist/{types-t1gxALVE.cjs → types-CPubg05Z.cjs} +52 -2
  49. package/package.json +7 -7
  50. 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-t1gxALVE.cjs');
7
- var persistence = require('./limits-FZWhlsBu.cjs');
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--QIi_rZ2.cjs');
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 || settings.includeCoAuthoredBy === void 0) {
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
- ALWAYS when you start a new chat - you must call a tool "mcp__happy__change_title" to set a chat title. When you think chat title is not relevant anymore - call the tool again to change it. When chat name is too generic and you have a change to make it more specific - call the tool again to change it. This title is needed to easily find the chat in the future. Help human.
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 making commit messages, instead of just giving co-credit to Claude, also give credit to Happy like so:
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-3kRCtzOL.cjs'); });
5339
- const { describeAgentHome } = await Promise.resolve().then(function () { return require('./types-t1gxALVE.cjs'); }).then(function (n) { return n.index; });
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 = { npm: runNpm, fs: { lstat: promises.lstat, readlink: promises.readlink, unlink: promises.unlink, rm: promises.rm, readFile: promises.readFile, symlink: promises.symlink }, platform: process.platform };
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(args);
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
- const rootResult = await deps.npm(["root", "-g"]);
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-CyfXsCXl.cjs', document.baseURI).href))).resolve(s)) {
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, MAX_ARGS_CHARS) : "";
9452
+ const args = ev.args ? safeJson(ev.args, limits.args) : "";
9323
9453
  const detail = title || args;
9324
- return `[tool] ${name}${detail ? `: ${truncateText(detail, MAX_ARGS_CHARS)}` : ""}`;
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, MAX_ARGS_CHARS)}` : null;
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, MAX_ARGS_CHARS)}`;
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 ?? "")), MAX_ARGS_CHARS)}`;
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
- async function readSessionTranscript(sessionId, limit) {
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
- const bounded = Math.max(1, Math.min(MAX_READ_LIMIT, Math.floor(limit)));
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: bounded },
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
- const live = await index.listDaemonSessions();
9744
- const bodies = messages.map((message) => {
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: messages.length,
9755
- transcript: formatTranscript(bodies)
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-DBN2Zpqc.cjs'); });
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-CyfXsCXl.cjs', document.baseURI).href)));
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-CyfXsCXl.cjs', document.baseURI).href)));
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-CyfXsCXl.cjs', document.baseURI).href)));
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-kdAoTfNT.cjs'); });
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-3kRCtzOL.cjs'); });
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-Cm3Da8Ge.cjs'); });
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-2Bkau9T4.cjs'); });
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-0LrSwGgr.cjs'); });
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-CzJZcvTO.cjs'); });
17940
- const { readCredentialsForConfiguredRelay: readCredentialsForConfiguredRelay2 } = await Promise.resolve().then(function () { return require('./limits-FZWhlsBu.cjs'); }).then(function (n) { return n.persistence; });
17941
- const { ApiClient: ApiClient2 } = await Promise.resolve().then(function () { return require('./types-t1gxALVE.cjs'); }).then(function (n) { return n.api; });
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-CzJZcvTO.cjs'); });
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-ComTu0EB.cjs'); });
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-qQAzQwIU.cjs'); });
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-DgK4KX-Z.cjs'); });
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-DgK4KX-Z.cjs'); });
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-M3YlDt8z.cjs'); });
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-8RgCTDxH.cjs'); });
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-DKKeIG-u.cjs'); });
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-DoLZbbZp.cjs'); });
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;