very-happy-cli 0.2.152 → 0.2.154

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 (61) hide show
  1. package/dist/{AcpBackend-CogiKCng.cjs → AcpBackend-B14xNj5L.cjs} +2 -2
  2. package/dist/{AcpBackend-Bs3wwYbt.mjs → AcpBackend-Ckyadhf4.mjs} +2 -2
  3. package/dist/{AcpSessionManager-BazkBuFo.cjs → AcpSessionManager-CCHmPdrR.cjs} +1 -1
  4. package/dist/{AcpSessionManager-BT8PJMEm.mjs → AcpSessionManager-H8t4P-IW.mjs} +1 -1
  5. package/dist/{agentGuidance-CqBn77AI.cjs → agentGuidance-DUBXppv-.cjs} +2 -1
  6. package/dist/{agentGuidance-Daxn5Nvj.mjs → agentGuidance-TLYQxsm2.mjs} +2 -1
  7. package/dist/{agentHome-CCYfs8Ec.mjs → agentHome-B20RWdgE.mjs} +3 -3
  8. package/dist/{agentHome-CpJjrQZc.cjs → agentHome-BUsLTZnz.cjs} +3 -3
  9. package/dist/{auto-DV5emt1-.mjs → auto-BQnncDcs.mjs} +7 -7
  10. package/dist/{auto-DncmTDvw.cjs → auto-IeldARBS.cjs} +7 -7
  11. package/dist/codex/happyMcpStdioBridge.cjs +2 -2
  12. package/dist/codex/happyMcpStdioBridge.mjs +2 -2
  13. package/dist/{config-DbKpQpdL.mjs → config-B-ocQh5V.mjs} +5 -5
  14. package/dist/{config-DeJgSMh-.cjs → config-DM_xI9M6.cjs} +5 -5
  15. package/dist/{index-BauTv2jB.mjs → index-BELV05ko.mjs} +284 -45
  16. package/dist/{index-imt4mC41.cjs → index-BUxBxSxJ.cjs} +9 -9
  17. package/dist/{index-CN7OF2cU.mjs → index-CIx3248o.mjs} +5 -5
  18. package/dist/{index-DahaLbu4.mjs → index-ZKuBjvHi.mjs} +9 -9
  19. package/dist/{index-ZIW1jrYm.cjs → index-eCjkm8Y2.cjs} +307 -66
  20. package/dist/{index-CRaJ9k2p.cjs → index-okLyUzeD.cjs} +5 -5
  21. package/dist/index.cjs +5 -5
  22. package/dist/index.mjs +5 -5
  23. package/dist/{install-CDR3qBhs.cjs → install-BZOdxfPd.cjs} +1 -1
  24. package/dist/{install-C1K3nrxF.mjs → install-CoLN3whR.mjs} +1 -1
  25. package/dist/{installPiTools-C-Lxv4Bt.mjs → installPiTools-Cj7yU9Fc.mjs} +2 -1
  26. package/dist/{installPiTools-BKnXjrVu.cjs → installPiTools-DuZ6jZvX.cjs} +3 -2
  27. package/dist/{installTerminalHooks-BoDxpaBO.cjs → installTerminalHooks-CA4OcAS7.cjs} +7 -7
  28. package/dist/{installTerminalHooks-VvmlO6Ue.mjs → installTerminalHooks-Dde_8t36.mjs} +6 -6
  29. package/dist/lib.cjs +3 -3
  30. package/dist/lib.mjs +3 -3
  31. package/dist/{limits-BNTWyUaZ.cjs → limits-CmzISka2.cjs} +7 -7
  32. package/dist/{limits-CKR_HJnO.mjs → limits-Dt7_unH4.mjs} +7 -7
  33. package/dist/{mcp-CCKCKL6l.cjs → mcp-7iDHlyCI.cjs} +14 -6
  34. package/dist/{mcp-D4dAo5BQ.mjs → mcp-9Ui4nQZL.mjs} +14 -7
  35. package/dist/piExtension.d.mts +4 -1
  36. package/dist/piExtension.mjs +24 -1
  37. package/dist/{piRuntime-Bn5ypbjH.cjs → piRuntime-BesGGPME.cjs} +2 -2
  38. package/dist/{piRuntime-CW-XA4rz.mjs → piRuntime-C4E4pgye.mjs} +2 -2
  39. package/dist/{piTerminal-BLSXK1u2.mjs → piTerminal-CCEGCQOY.mjs} +8 -7
  40. package/dist/{piTerminal-B7K75aXB.cjs → piTerminal-fUogwxYr.cjs} +8 -7
  41. package/dist/{runGemini-D5N11LxO.mjs → runGemini-BW-pEklU.mjs} +7 -7
  42. package/dist/{runGemini-Bgg1BzDK.cjs → runGemini-CNPGSsSK.cjs} +8 -8
  43. package/dist/{runOpenClaw-B9qWHybc.cjs → runOpenClaw-Bsodkg_s.cjs} +6 -6
  44. package/dist/{runOpenClaw-CCpyKbrn.mjs → runOpenClaw-NRB6-_jU.mjs} +6 -6
  45. package/dist/{send-wl9ei8yG.cjs → send-Bd00QcHC.cjs} +56 -18
  46. package/dist/{send-C44kcXz5.mjs → send-DYeSFg8s.mjs} +56 -19
  47. package/dist/{sessions-DXJEcUg6.mjs → sessions-DlPOYKLU.mjs} +5 -5
  48. package/dist/{sessions-Tad8elmy.cjs → sessions-RIFUoy_g.cjs} +5 -5
  49. package/dist/{spawn-BOlb5y1_.mjs → spawn-D1bhyHbH.mjs} +5 -5
  50. package/dist/{spawn-DA8WAFmm.cjs → spawn-DxrfHTF4.cjs} +5 -5
  51. package/dist/{teams-qVLrFcdd.cjs → teams-Cfy0VMCo.cjs} +6 -6
  52. package/dist/{teams-Bs8lI887.mjs → teams-pfKHpkgL.mjs} +6 -6
  53. package/dist/terminalTitleSuggest-DKgX3osW.mjs +38 -0
  54. package/dist/terminalTitleSuggest-Dji8I0Jy.cjs +45 -0
  55. package/dist/{todo-nzsqGZqp.mjs → todo-B2CjDg_V.mjs} +2 -2
  56. package/dist/{todo-mCMoGjJk.cjs → todo-B4cBFzHB.cjs} +2 -2
  57. package/dist/{types-CN28qJl7.cjs → types-Bd_TGr0F.cjs} +34 -10
  58. package/dist/{types-xKrxbCRv.mjs → types-D5RWyBE5.mjs} +32 -9
  59. package/package.json +7 -7
  60. package/dist/projectPath-CSpqWdxp.mjs +0 -10
  61. package/dist/projectPath-ChLhdOyt.cjs +0 -13
@@ -1,14 +1,14 @@
1
1
  import{createRequire as _pkgrollCR}from"node:module";const require=_pkgrollCR(import.meta.url);import chalk from 'chalk';
2
2
  import os, { homedir, userInfo, tmpdir } from 'node:os';
3
3
  import { randomUUID, randomInt, randomBytes, createHash as createHash$1, timingSafeEqual } from 'node:crypto';
4
- import { v as notifyDaemonSessionEvent, g as getProjectPath, w as initializeSandbox, x as wrapCommand, u as contentLogMetadata, I as InvalidateSync, R as RawJSONLinesSchema, c as delay, y as AsyncLock, M as MAX_CHAT_ATTACHMENT_SOURCE_BYTES, z as notifyDaemonClaudeAuthFailed, B as commandOnPath, j as checkIfDaemonRunningAndCleanupStaleState, D as deriveLocalCliUpdateSummary, E as isClaudeSessionId, G as getLocalHappyAgentCredentialPath, H as readLocalHappyAgentCredentials, J as parseExactVersion, K as compareExactVersions, L as extractCompleteLines, N as decideBackfill, O as parseTerminalHookPayload, P as tmuxArgs, Q as scrubTmuxClientEnv, S as decideMirrorBinding, T as MIRROR_BACKFILL_LINES_DEFAULT, U as mirrorLineKey, V as mirrorLocalId, W as listDaemonSessions, k as stopDaemonSession, X as detectCLIAvailability, Y as detectResumeSupport, Z as refreshAgentHomes, d as describeAgentHome, _ as isDaemonRunningCurrentlyInstalledHappyVersion, $ as stopDaemon, a0 as TurnActivityTracker, a1 as summarizeSpawnSessionForLog, a2 as locateClaudeConversation, a3 as agentHomeSpawnEnv, a4 as shellescape, A as ApiClient, a5 as fetchCliUpdateState, a6 as resolveCliUpdateCheckInterval, a7 as DEFAULT_CLI_UPDATE_CHECK_INTERVAL_MS, a8 as cleanupDaemonState, i as isValidSessionId, s as spawnDaemonSession, a9 as listVhTerminals, aa as isValidTerminalId, ab as readVhTerminal, ac as sendToVhTerminal, ad as TITLE_PROMPT_PREFIX, ae as BOARD_ANALYZER_PROMPT_PREFIX, o as connectionState, af as startOfflineReconnection, q as notifyDaemonSessionStarted, C as CodexAppServerClient } from './types-xKrxbCRv.mjs';
5
- import { l as logger, k as BUILTIN_TODO_DISCOVERY, U as STREAM_DELTA_MAX_CHARS, V as ensurePrivateDirectory, W as hardenPrivateFile, c as configuration, p as packageJson, r as readSettings, X as readCredentials, L as credentialRelayProblem, F as readDaemonState, Y as AGENT_VERSION_SOURCES, j as encodeBase64, Z as readSettingsOutcome, u as updateSettings, _ as encodeBase64Url, E as decodeBase64, $ as writeCredentialsLegacy, a0 as writeCredentialsDataKey, f as readCredentialsForConfiguredRelay, z as encrypt, d as readPersistedSessions, w as writePrivateFileSync, a1 as decryptWithDataKey, a2 as decryptLegacy, a3 as persistSession, D as decrypt, m as ensurePrivateDirectorySync, a4 as getAgentCodeDefaults, a5 as normalizeAgentKey, a6 as isClaudeOpus55Model, a7 as supportsClaudeOpus55, a8 as AUTOMATION_SUMMARY_MAX_CHARS, a9 as AUTOMATION_CLAIM_MAX_RUNS, aa as AUTOMATION_DEFAULT_LEASE_MS, i as isAutomationRunTerminal, ab as acquireDaemonLock, ac as deletePersistedSessions, ad as writeDaemonState, ae as writeSettings, af as releaseDaemonLock, ag as ContextUsageSchema, C as CLIPBOARD_TOOL_NAME, a as CLIPBOARD_TOOL_TITLE, b as CLIPBOARD_TOOL_DESCRIPTION, h as CLIPBOARD_MAX_BYTES, ah as clearCredentials, ai as clearMachineId, aj as SandboxConfigSchema, e as createEnvelope, ak as getLatestDaemonLog } from './limits-CKR_HJnO.mjs';
4
+ import { v as notifyDaemonSessionEvent, g as getProjectPath, w as initializeSandbox, x as wrapCommand, u as contentLogMetadata, I as InvalidateSync, R as RawJSONLinesSchema, c as delay, y as AsyncLock, M as MAX_CHAT_ATTACHMENT_SOURCE_BYTES, z as notifyDaemonClaudeAuthFailed, B as commandOnPath, j as checkIfDaemonRunningAndCleanupStaleState, D as deriveLocalCliUpdateSummary, E as isClaudeSessionId, G as getLocalHappyAgentCredentialPath, H as readLocalHappyAgentCredentials, J as parseExactVersion, K as compareExactVersions, L as extractCompleteLines, N as decideBackfill, O as parseTerminalHookPayload, P as tmuxArgs, Q as scrubTmuxClientEnv, S as decideMirrorBinding, T as MIRROR_BACKFILL_LINES_DEFAULT, U as mirrorLineKey, V as mirrorLocalId, W as listDaemonSessions, k as stopDaemonSession, X as detectCLIAvailability, Y as detectResumeSupport, Z as refreshAgentHomes, d as describeAgentHome, _ as isDaemonRunningCurrentlyInstalledHappyVersion, $ as stopDaemon, a0 as TurnActivityTracker, a1 as summarizeSpawnSessionForLog, a2 as locateClaudeConversation, a3 as agentHomeSpawnEnv, a4 as shellescape, A as ApiClient, a5 as fetchCliUpdateState, a6 as resolveCliUpdateCheckInterval, a7 as DEFAULT_CLI_UPDATE_CHECK_INTERVAL_MS, a8 as cleanupDaemonState, a9 as resumeDaemonSession, i as isValidSessionId, s as spawnDaemonSession, aa as listVhTerminals, ab as isValidTerminalId, ac as readVhTerminal, ad as sendToVhTerminal, ae as TITLE_PROMPT_PREFIX, af as BOARD_ANALYZER_PROMPT_PREFIX, o as connectionState, ag as startOfflineReconnection, q as notifyDaemonSessionStarted, C as CodexAppServerClient } from './types-D5RWyBE5.mjs';
5
+ import { l as logger, k as BUILTIN_TODO_DISCOVERY, U as STREAM_DELTA_MAX_CHARS, V as ensurePrivateDirectory, W as hardenPrivateFile, c as configuration, p as packageJson, r as readSettings, X as readCredentials, L as credentialRelayProblem, F as readDaemonState, Y as AGENT_VERSION_SOURCES, j as encodeBase64, Z as readSettingsOutcome, u as updateSettings, _ as encodeBase64Url, E as decodeBase64, $ as writeCredentialsLegacy, a0 as writeCredentialsDataKey, f as readCredentialsForConfiguredRelay, z as encrypt, d as readPersistedSessions, w as writePrivateFileSync, a1 as decryptWithDataKey, a2 as decryptLegacy, a3 as persistSession, D as decrypt, m as ensurePrivateDirectorySync, a4 as getAgentCodeDefaults, a5 as normalizeAgentKey, a6 as isClaudeOpus55Model, a7 as supportsClaudeOpus55, a8 as AUTOMATION_SUMMARY_MAX_CHARS, a9 as AUTOMATION_CLAIM_MAX_RUNS, aa as AUTOMATION_DEFAULT_LEASE_MS, i as isAutomationRunTerminal, ab as acquireDaemonLock, ac as deletePersistedSessions, ad as writeDaemonState, ae as writeSettings, af as releaseDaemonLock, ag as ContextUsageSchema, C as CLIPBOARD_TOOL_NAME, a as CLIPBOARD_TOOL_TITLE, b as CLIPBOARD_TOOL_DESCRIPTION, h as CLIPBOARD_MAX_BYTES, ah as clearCredentials, ai as clearMachineId, aj as SandboxConfigSchema, e as createEnvelope, ak as getLatestDaemonLog } from './limits-Dt7_unH4.mjs';
6
6
  import spawn$1, { spawn } from 'cross-spawn';
7
7
  import path, { join, resolve, basename, delimiter, isAbsolute, dirname, sep, normalize } from 'node:path';
8
8
  import { createInterface } from 'node:readline';
9
9
  import { existsSync, readFileSync, readdirSync, statSync, mkdirSync, realpathSync, unlinkSync, renameSync, writeFileSync, accessSync, constants as constants$1, openSync, fsyncSync, closeSync, rmSync as rmSync$1, chmodSync as chmodSync$1 } from 'node:fs';
10
- import { p as projectPath } from './projectPath-CSpqWdxp.mjs';
11
- import { j as trimIdent, k as AGENT_GUIDANCE, l as createAutomationsClient, i as isAutomationsUnavailable, m as AutomationsRequestError, t as teamScopePath, T as TeamConnectionPreflightError, h as createTeamsClient, P as PREVIEW_TOOL_NAME, R as REPORT_PROGRESS_TOOL_NAME, n as TEAM_TOOL_NAMES, o as AUTOMATION_TOOL_NAMES, r as registerTeamsTools, c as registerAutomationTools, a as PREVIEW_TOOL_TITLE, b as PREVIEW_TOOL_DESCRIPTION, p as REPORT_PROGRESS_TOOL_TITLE, q as REPORT_PROGRESS_TOOL_DESCRIPTION } from './agentGuidance-Daxn5Nvj.mjs';
10
+ import { p as projectPath } from './terminalTitleSuggest-DKgX3osW.mjs';
11
+ import { j as trimIdent, k as AGENT_GUIDANCE, l as createAutomationsClient, i as isAutomationsUnavailable, m as AutomationsRequestError, t as teamScopePath, T as TeamConnectionPreflightError, h as createTeamsClient, P as PREVIEW_TOOL_NAME, R as REPORT_PROGRESS_TOOL_NAME, n as TEAM_TOOL_NAMES, o as AUTOMATION_TOOL_NAMES, r as registerTeamsTools, c as registerAutomationTools, a as PREVIEW_TOOL_TITLE, b as PREVIEW_TOOL_DESCRIPTION, p as REPORT_PROGRESS_TOOL_TITLE, q as REPORT_PROGRESS_TOOL_DESCRIPTION } from './agentGuidance-TLYQxsm2.mjs';
12
12
  import { readFile, writeFile, rename, unlink, mkdir, access as access$1, symlink, rm, readlink, lstat, constants, stat, open as open$1, appendFile } from 'node:fs/promises';
13
13
  import fs, { watch, access } from 'fs/promises';
14
14
  import { useStdout, useInput, Box, Text, render } from 'ink';
@@ -5380,8 +5380,8 @@ ${typeLabels[type] || type}:`));
5380
5380
  }
5381
5381
  console.log(chalk.gray(" An external claude command is only needed for native terminal/mirror use."));
5382
5382
  try {
5383
- const { resolveAgentHomesForCli } = await import('./agentHome-CCYfs8Ec.mjs');
5384
- const { describeAgentHome } = await import('./types-xKrxbCRv.mjs').then(function (n) { return n.ag; });
5383
+ const { resolveAgentHomesForCli } = await import('./agentHome-B20RWdgE.mjs');
5384
+ const { describeAgentHome } = await import('./types-D5RWyBE5.mjs').then(function (n) { return n.ah; });
5385
5385
  const homes = await resolveAgentHomesForCli();
5386
5386
  console.log(chalk.green(`\u2713 Claude config dir: ${describeAgentHome(homes.claudeConfigDir)}`));
5387
5387
  console.log(chalk.green(`\u2713 Codex home: ${describeAgentHome(homes.codexHome)}`));
@@ -6262,6 +6262,7 @@ function startDaemonControlServer({
6262
6262
  getChildren,
6263
6263
  stopSession,
6264
6264
  spawnSession,
6265
+ resumeSession,
6265
6266
  requestShutdown,
6266
6267
  onHappySessionWebhook,
6267
6268
  onSessionStateEvent,
@@ -6474,6 +6475,48 @@ function startDaemonControlServer({
6474
6475
  };
6475
6476
  }
6476
6477
  });
6478
+ typed.post("/resume-session", {
6479
+ schema: {
6480
+ body: z.object({
6481
+ sessionId: z.string().min(1).max(200),
6482
+ model: z.string().optional(),
6483
+ permissionMode: z.string().optional()
6484
+ }),
6485
+ response: {
6486
+ 200: z.object({
6487
+ success: z.boolean(),
6488
+ sessionId: z.string().optional(),
6489
+ error: z.string().optional()
6490
+ }),
6491
+ 500: z.object({
6492
+ success: z.boolean(),
6493
+ error: z.string().optional()
6494
+ }),
6495
+ 503: z.object({
6496
+ success: z.boolean(),
6497
+ error: z.string().optional()
6498
+ })
6499
+ }
6500
+ }
6501
+ }, async (request, reply) => {
6502
+ const { sessionId, model, permissionMode } = request.body;
6503
+ if (!resumeSession) {
6504
+ reply.code(503);
6505
+ return { success: false, error: "daemon is still starting up" };
6506
+ }
6507
+ logger.debug(`[CONTROL SERVER] Resume session request: ${sessionId} (model=${model ?? "unset"}, permissionMode=${permissionMode ?? "unset"})`);
6508
+ const result = await resumeSession(sessionId, { model, permissionMode });
6509
+ switch (result.type) {
6510
+ case "success":
6511
+ return { success: true, sessionId: result.sessionId };
6512
+ case "requestToApproveDirectoryCreation":
6513
+ reply.code(500);
6514
+ return { success: false, error: `Cannot resume: working directory ${result.directory} needs to be created first` };
6515
+ case "error":
6516
+ reply.code(500);
6517
+ return { success: false, error: result.errorMessage };
6518
+ }
6519
+ });
6477
6520
  typed.post("/terminal-hook", {
6478
6521
  schema: {
6479
6522
  body: z.any(),
@@ -9358,6 +9401,20 @@ export default async function(pi) {
9358
9401
  return data.result;
9359
9402
  }
9360
9403
  await rpc('initialize', {protocolVersion:'2024-11-05',capabilities:{},clientInfo:{name:'very-happy-pi-teams',version:'1'}});
9404
+ if (!managed && pi.setSessionName) {
9405
+ // B-500: name the pi session from its first prompt (managed sessions are titled by TitleGenerator).
9406
+ let titleArmed = false, generation = 0;
9407
+ pi.on('session_start', async () => { generation += 1; titleArmed = !pi.getSessionName?.(); });
9408
+ pi.on('before_agent_start', async (event) => {
9409
+ const prompt = event && typeof event.prompt === 'string' ? event.prompt : '';
9410
+ if (!titleArmed || !prompt.trim()) return;
9411
+ titleArmed = false;
9412
+ const expected = generation;
9413
+ rpc('very-happy/terminal-title-suggest', {prompt}).then(result => {
9414
+ if (result && result.title && expected === generation && !pi.getSessionName?.()) pi.setSessionName(result.title);
9415
+ }).catch(() => {});
9416
+ });
9417
+ }
9361
9418
  const available = await rpc('tools/list', {});
9362
9419
  for (const tool of available.tools || []) {
9363
9420
  pi.registerTool({name:tool.name,label:tool.name,description:tool.description || tool.name,parameters:tool.inputSchema,
@@ -9982,6 +10039,35 @@ async function readSessionMetadata(sessionId, persisted) {
9982
10039
  if (typeof ciphertext !== "string" || ciphertext.length === 0) return null;
9983
10040
  return decrypt(decodeBase64(persisted.encryptionKey), persisted.encryptionVariant, decodeBase64(ciphertext));
9984
10041
  }
10042
+ async function readSessionState(sessionId, persisted) {
10043
+ const token = await bearerToken();
10044
+ const response = await axios.get(`${configuration.serverUrl}/v1/sessions/${encodeURIComponent(sessionId)}`, {
10045
+ headers: {
10046
+ "Authorization": `Bearer ${token}`,
10047
+ "X-Happy-Client": `${SESSION_OPS_CLIENT}/${configuration.currentCliVersion}`
10048
+ },
10049
+ timeout: 15e3,
10050
+ validateStatus: (status) => status >= 200 && status < 300 || status === 404
10051
+ });
10052
+ if (response.status === 404) return { found: false, active: false };
10053
+ const row = response.data?.session;
10054
+ if (!row || typeof row.id !== "string") throw new Error(`Server returned no session row for ${sessionId}`);
10055
+ const state = {
10056
+ found: true,
10057
+ active: row.active === true,
10058
+ ...typeof row.activeAt === "number" ? { activeAt: row.activeAt } : {},
10059
+ archivedAt: typeof row.archivedAt === "number" ? row.archivedAt : null,
10060
+ ...typeof row.updatedAt === "number" ? { updatedAt: row.updatedAt } : {}
10061
+ };
10062
+ if (persisted && typeof row.metadata === "string" && row.metadata.length > 0) {
10063
+ try {
10064
+ const metadata = decrypt(decodeBase64(persisted.encryptionKey), persisted.encryptionVariant, decodeBase64(row.metadata));
10065
+ if (metadata?.machineId) state.machineId = metadata.machineId;
10066
+ } catch {
10067
+ }
10068
+ }
10069
+ return state;
10070
+ }
9985
10071
  class TurnWaitTimeoutError extends Error {
9986
10072
  constructor(sessionId, timeoutMs, turn) {
9987
10073
  super(`Session ${sessionId}: the latest turn did not end within ${Math.round(timeoutMs / 1e3)}s`);
@@ -10019,6 +10105,20 @@ async function archiveSession(sessionId) {
10019
10105
  }
10020
10106
  );
10021
10107
  }
10108
+ async function unarchiveSession(sessionId) {
10109
+ const token = await bearerToken();
10110
+ await axios.post(
10111
+ `${configuration.serverUrl}/v1/sessions/${encodeURIComponent(sessionId)}/unarchive`,
10112
+ {},
10113
+ {
10114
+ headers: {
10115
+ "Authorization": `Bearer ${token}`,
10116
+ "X-Happy-Client": `${SESSION_OPS_CLIENT}/${configuration.currentCliVersion}`
10117
+ },
10118
+ timeout: 1e4
10119
+ }
10120
+ );
10121
+ }
10022
10122
 
10023
10123
  function receiptPath(home, operationId) {
10024
10124
  if (!/^[a-zA-Z0-9_-]{1,128}$/.test(operationId)) throw new Error("Invalid team operation id");
@@ -12045,6 +12145,8 @@ async function startDaemon() {
12045
12145
  getChildren: getCurrentChildren,
12046
12146
  stopSession,
12047
12147
  spawnSession,
12148
+ resumeSession,
12149
+ // B-501: `very-happy send --resume`
12048
12150
  requestShutdown: () => requestShutdown("happy-cli"),
12049
12151
  onHappySessionWebhook,
12050
12152
  onSessionStateEvent,
@@ -12449,6 +12551,127 @@ This session is now connected as the team lead. Call team_inspect to read the au
12449
12551
  };
12450
12552
  }
12451
12553
 
12554
+ const ACTIVE_FRESH_WINDOW_MS = 15 * 60 * 1e3;
12555
+ const DEFAULT_RESUME_WAIT_MS = 3e4;
12556
+ const DEFAULT_RESUME_POLL_MS = 1e3;
12557
+ function classifySessionState(input) {
12558
+ const { liveHere, server, now } = input;
12559
+ if (!server.found) return "not_found";
12560
+ if (typeof server.archivedAt === "number") return "archived";
12561
+ if (liveHere) return "live";
12562
+ if (server.active && typeof server.activeAt === "number" && now - server.activeAt <= ACTIVE_FRESH_WINDOW_MS) return "live";
12563
+ return "offline";
12564
+ }
12565
+ function explainNotLive(sessionId, status, resumeHint) {
12566
+ switch (status) {
12567
+ case "archived":
12568
+ return `Session ${sessionId} is archived \u2014 no live wrapper will receive this message. ${resumeHint}`;
12569
+ case "offline":
12570
+ return `Session ${sessionId} is offline (its wrapper exited or timed out) \u2014 no live wrapper will receive this message. ${resumeHint}`;
12571
+ case "not_found":
12572
+ return `Session ${sessionId} was not found on this account \u2014 it cannot be messaged or resumed. Spawn a new session instead.`;
12573
+ }
12574
+ }
12575
+ const CLI_RESUME_HINT = "Use --resume to bring it back on this machine, or spawn a new session.";
12576
+ const defaultDeps = {
12577
+ listLive: () => listDaemonSessions(),
12578
+ readState: (sessionId, persisted) => readSessionState(sessionId, persisted),
12579
+ send: (sessionId, persisted, text, client, options) => sendUserMessage(sessionId, persisted, text, client, options),
12580
+ unarchive: unarchiveSession,
12581
+ archive: archiveSession,
12582
+ resume: resumeDaemonSession,
12583
+ sleep: (ms) => delay(ms).then(() => void 0),
12584
+ now: () => Date.now()
12585
+ };
12586
+ async function deliverToSession(sessionId, persisted, text, client, options = {}, deps = {}) {
12587
+ const d = { ...defaultDeps, ...deps };
12588
+ const resumeHint = options.resumeHint ?? CLI_RESUME_HINT;
12589
+ const classify = async () => {
12590
+ const [live, server] = await Promise.all([d.listLive(), d.readState(sessionId, persisted)]);
12591
+ return classifySessionState({ liveHere: sessionLiveness(live, sessionId).live, server, now: d.now() });
12592
+ };
12593
+ let status = await classify();
12594
+ let resumed = false;
12595
+ let resumeOutcome;
12596
+ if (status !== "live") {
12597
+ if (!options.resume || status === "not_found") {
12598
+ return { sessionId, status, delivered: false, resumed: false, stored: false, error: explainNotLive(sessionId, status, resumeHint) };
12599
+ }
12600
+ const wasArchived = status === "archived";
12601
+ if (wasArchived) {
12602
+ try {
12603
+ await d.unarchive(sessionId);
12604
+ } catch (error) {
12605
+ const message = `unarchive failed: ${error instanceof Error ? error.message : String(error)}`;
12606
+ return { sessionId, status, delivered: false, resumed: false, stored: false, error: message, resume: { ok: false, error: message } };
12607
+ }
12608
+ }
12609
+ const outcome = await d.resume(sessionId, {
12610
+ ...typeof options.model === "string" ? { model: options.model } : {},
12611
+ ...options.permissionMode !== void 0 ? { permissionMode: options.permissionMode } : {}
12612
+ });
12613
+ if (!outcome.success) {
12614
+ let message = outcome.error ?? "resume failed";
12615
+ if (wasArchived) {
12616
+ try {
12617
+ await d.archive(sessionId);
12618
+ } catch (error) {
12619
+ message += `; failed to restore archive state: ${error instanceof Error ? error.message : String(error)}`;
12620
+ }
12621
+ }
12622
+ return { sessionId, status, delivered: false, resumed: false, stored: false, error: message, resume: { ok: false, error: message } };
12623
+ }
12624
+ resumed = true;
12625
+ resumeOutcome = { ok: true };
12626
+ status = await waitUntilLive(classify, d, options);
12627
+ if (status !== "live") {
12628
+ const waited = Math.round((options.waitMs ?? DEFAULT_RESUME_WAIT_MS) / 1e3);
12629
+ return {
12630
+ sessionId,
12631
+ status,
12632
+ delivered: false,
12633
+ resumed,
12634
+ stored: false,
12635
+ resume: resumeOutcome,
12636
+ error: `Session ${sessionId} was resumed but no live wrapper showed up within ${waited}s (state: ${status}); message not sent`
12637
+ };
12638
+ }
12639
+ }
12640
+ await d.send(sessionId, persisted, text, client, {
12641
+ ...options.model !== void 0 ? { model: options.model } : {},
12642
+ ...options.sentFrom !== void 0 ? { sentFrom: options.sentFrom } : {}
12643
+ });
12644
+ let after = "live";
12645
+ try {
12646
+ after = await classify();
12647
+ } catch {
12648
+ after = "live";
12649
+ }
12650
+ if (after !== "live") {
12651
+ return {
12652
+ sessionId,
12653
+ status: after,
12654
+ delivered: false,
12655
+ resumed,
12656
+ stored: true,
12657
+ ...resumeOutcome ? { resume: resumeOutcome } : {},
12658
+ error: `Session ${sessionId} went ${after} while sending: the message is stored server-side but no wrapper is attached to read it. ${after === "not_found" ? "Spawn a new session." : resumeHint}`
12659
+ };
12660
+ }
12661
+ return { sessionId, status: "live", delivered: true, resumed, stored: true, ...resumeOutcome ? { resume: resumeOutcome } : {} };
12662
+ }
12663
+ async function waitUntilLive(classify, d, options) {
12664
+ const waitMs = options.waitMs ?? DEFAULT_RESUME_WAIT_MS;
12665
+ const pollMs = options.pollMs ?? DEFAULT_RESUME_POLL_MS;
12666
+ const deadline = d.now() + waitMs;
12667
+ let status = await classify();
12668
+ while (status !== "live" && d.now() < deadline) {
12669
+ await d.sleep(pollMs);
12670
+ status = await classify();
12671
+ }
12672
+ return status;
12673
+ }
12674
+
12452
12675
  const PERSONAL_MEMORY_SOFT_LIMIT_CHARS = 2e3;
12453
12676
  function headingTitle(line) {
12454
12677
  const m = /^##(?!#)\s*(.*?)\s*$/.exec(line);
@@ -12548,11 +12771,13 @@ function fail(text) {
12548
12771
  function describeSession(id, persisted, extra) {
12549
12772
  const meta = persisted?.metadata;
12550
12773
  const parts = [id];
12774
+ if (extra?.live !== void 0) parts.push(extra.live ? "[running]" : "[not running]");
12551
12775
  if (meta?.summary?.text) parts.push(`title="${meta.summary.text}"`);
12552
12776
  if (meta?.path) parts.push(`cwd=${meta.path}`);
12553
12777
  if (meta?.flavor) parts.push(`agent=${meta.flavor}`);
12554
12778
  if (meta?.tags?.length) parts.push(`tags=${meta.tags.join(",")}`);
12555
12779
  if (meta?.variant === "assistant") parts.push("(assistant)");
12780
+ if (extra?.pid) parts.push(`pid=${extra.pid}`);
12556
12781
  parts.push(sessionWebUrl(id));
12557
12782
  return parts.join(" ");
12558
12783
  }
@@ -12606,19 +12831,27 @@ ${body}`);
12606
12831
  }
12607
12832
  });
12608
12833
  mcp.registerTool("session_send", {
12609
- description: "Send a user message into an existing session on this machine. Returns immediately after delivery \u2014 it does NOT wait for the session to respond; use session_read later to check progress.",
12834
+ description: "Send a user message into an existing session on this machine. Only delivers when a live wrapper will read it: an archived / offline session is refused (the server would store the message unread) unless resume:true brings it back on this machine first. Returns immediately after delivery \u2014 it does NOT wait for the session to respond; use session_read later to check progress.",
12610
12835
  title: "Send Message to Session",
12611
12836
  inputSchema: {
12612
12837
  sessionId: z.string().describe("The Happy session id to message"),
12613
- text: z.string().describe("The message text to send")
12838
+ text: z.string().describe("The message text to send"),
12839
+ resume: z.boolean().optional().describe("If the session is archived or offline, resume it on this machine (like the web Restore button) and wait until it is live before sending")
12614
12840
  }
12615
12841
  }, async (args) => {
12616
12842
  if (!isValidSessionId(args.sessionId)) return fail("Invalid sessionId");
12617
12843
  if (typeof args.text !== "string" || args.text.trim().length === 0) return fail("text must be non-empty");
12618
12844
  try {
12619
12845
  const persisted = await waitForSessionKey(args.sessionId, 0);
12620
- await sendUserMessage(args.sessionId, persisted, args.text, MCP_CLIENT_TAG);
12621
- return ok(`Message delivered to ${describeSession(args.sessionId, persisted)}`);
12846
+ const result = await deliverToSession(args.sessionId, persisted, args.text, MCP_CLIENT_TAG, {
12847
+ resume: args.resume === true,
12848
+ resumeHint: "Pass resume:true to bring it back on this machine, or spawn a new session."
12849
+ });
12850
+ if (!result.delivered) {
12851
+ const detail = result.error ?? `session is ${result.status}`;
12852
+ return fail(result.stored ? `Not delivered: ${detail}` : `Session ${args.sessionId} is ${result.status}: ${detail}`);
12853
+ }
12854
+ return ok(`Message delivered${result.resumed ? " (session resumed on this machine)" : ""} to ${describeSession(args.sessionId, persisted, { live: true })}`);
12622
12855
  } catch (error) {
12623
12856
  return fail(`Failed to send: ${error instanceof Error ? error.message : String(error)}`);
12624
12857
  }
@@ -13391,7 +13624,7 @@ function registerSideQuestionHandler(rpc, deps) {
13391
13624
  const retainMs = deps.retainMs ?? SIDE_QUESTION_RETAIN_MS;
13392
13625
  const maxRunMs = deps.maxRunMs ?? SIDE_QUESTION_MAX_RUN_MS;
13393
13626
  const fork = deps.run ?? (async (input) => {
13394
- const { query } = await import('./index-CN7OF2cU.mjs');
13627
+ const { query } = await import('./index-CIx3248o.mjs');
13395
13628
  return runSideQuestion(query, input);
13396
13629
  });
13397
13630
  const run = async (input, live) => {
@@ -13568,7 +13801,12 @@ function runClaudeOneShot(binary, prompt) {
13568
13801
  try {
13569
13802
  child = spawn$3(binary, ["-p", "--model", "haiku", prompt], {
13570
13803
  stdio: ["ignore", "pipe", "ignore"],
13571
- env: process.env
13804
+ // HAPPY_MANAGED=1: this claude is run BY happy. The user-wide
13805
+ // terminal-mirror SessionStart hook exits on it, so a one-shot
13806
+ // spawned from inside a vh web terminal (VH_TERMINAL_ID
13807
+ // inherited — B-500's pi terminal bridge, or `very-happy` typed
13808
+ // in a terminal) never binds a mirror session to itself.
13809
+ env: { ...process.env, HAPPY_MANAGED: "1" }
13572
13810
  });
13573
13811
  } catch (error) {
13574
13812
  logger.debug("[titleGenerator] spawn failed", { error: String(error) });
@@ -13603,6 +13841,18 @@ function runClaudeOneShot(binary, prompt) {
13603
13841
  });
13604
13842
  });
13605
13843
  }
13844
+ async function suggestTitleForPrompt(prompt) {
13845
+ const binary = resolveClaudeBinary();
13846
+ if (!binary) {
13847
+ logger.debug("[titleGenerator] no claude binary; skipping auto-title");
13848
+ return null;
13849
+ }
13850
+ const stdout = await runClaudeOneShot(binary, buildPrompt(prompt));
13851
+ if (stdout == null) return null;
13852
+ const title = sanitizeTitle(stdout);
13853
+ if (!title) logger.debug("[titleGenerator] empty/unusable title output; skipping");
13854
+ return title;
13855
+ }
13606
13856
  class TitleGenerator {
13607
13857
  constructor(session) {
13608
13858
  this.session = session;
@@ -13626,23 +13876,12 @@ class TitleGenerator {
13626
13876
  });
13627
13877
  }
13628
13878
  async generate(firstUserMessage) {
13629
- const binary = resolveClaudeBinary();
13630
- if (!binary) {
13631
- logger.debug("[titleGenerator] no claude binary; skipping auto-title");
13632
- return;
13633
- }
13634
13879
  if (this.session.getMetadata()?.summary?.text) {
13635
13880
  logger.debug("[titleGenerator] summary appeared before generation; skipping");
13636
13881
  return;
13637
13882
  }
13638
- const prompt = buildPrompt(firstUserMessage);
13639
- const stdout = await runClaudeOneShot(binary, prompt);
13640
- if (stdout == null) return;
13641
- const title = sanitizeTitle(stdout);
13642
- if (!title) {
13643
- logger.debug("[titleGenerator] empty/unusable title output; skipping");
13644
- return;
13645
- }
13883
+ const title = await suggestTitleForPrompt(firstUserMessage);
13884
+ if (!title) return;
13646
13885
  if (this.session.getMetadata()?.summary?.text) {
13647
13886
  logger.debug("[titleGenerator] summary set during generation; not overwriting");
13648
13887
  return;
@@ -18670,7 +18909,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
18670
18909
  process.exit(0);
18671
18910
  } else if (subcommand === "install-pi-tools") {
18672
18911
  try {
18673
- const { handleInstallPiTools } = await import('./installPiTools-C-Lxv4Bt.mjs');
18912
+ const { handleInstallPiTools } = await import('./installPiTools-Cj7yU9Fc.mjs');
18674
18913
  await handleInstallPiTools(args.slice(1));
18675
18914
  } catch (error) {
18676
18915
  console.error(error instanceof Error ? error.message : "Pi tools installation failed");
@@ -18679,7 +18918,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
18679
18918
  return;
18680
18919
  } else if (subcommand === "install-terminal-hooks") {
18681
18920
  try {
18682
- const { installTerminalHooks, parseTerminalHooksArgs, TERMINAL_HOOKS_HELP } = await import('./installTerminalHooks-VvmlO6Ue.mjs');
18921
+ const { installTerminalHooks, parseTerminalHooksArgs, TERMINAL_HOOKS_HELP } = await import('./installTerminalHooks-Dde_8t36.mjs');
18683
18922
  const command = parseTerminalHooksArgs(args.slice(1));
18684
18923
  if (command.action === "help") {
18685
18924
  console.log(TERMINAL_HOOKS_HELP);
@@ -18696,7 +18935,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
18696
18935
  }
18697
18936
  } else if (subcommand === "agent-home") {
18698
18937
  try {
18699
- const { parseAgentHomeArgs, runAgentHomeCommand } = await import('./agentHome-CCYfs8Ec.mjs');
18938
+ const { parseAgentHomeArgs, runAgentHomeCommand } = await import('./agentHome-B20RWdgE.mjs');
18700
18939
  await runAgentHomeCommand(parseAgentHomeArgs(args.slice(1)));
18701
18940
  process.exit(0);
18702
18941
  } catch (error) {
@@ -18705,7 +18944,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
18705
18944
  }
18706
18945
  } else if (subcommand === "spawn") {
18707
18946
  try {
18708
- const { handleSpawnCommand } = await import('./spawn-BOlb5y1_.mjs');
18947
+ const { handleSpawnCommand } = await import('./spawn-D1bhyHbH.mjs');
18709
18948
  await handleSpawnCommand(args.slice(1));
18710
18949
  } catch (error) {
18711
18950
  console.error(chalk.red("Error:"), error instanceof Error ? error.message : "Unknown error");
@@ -18717,7 +18956,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
18717
18956
  return;
18718
18957
  } else if (subcommand === "sessions") {
18719
18958
  try {
18720
- const { handleSessionsCommand } = await import('./sessions-DXJEcUg6.mjs');
18959
+ const { handleSessionsCommand } = await import('./sessions-DlPOYKLU.mjs');
18721
18960
  await handleSessionsCommand(args.slice(1));
18722
18961
  } catch (error) {
18723
18962
  console.error(chalk.red("Error:"), error instanceof Error ? error.message : "Unknown error");
@@ -18729,7 +18968,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
18729
18968
  return;
18730
18969
  } else if (subcommand === "send") {
18731
18970
  try {
18732
- const { handleSendCommand } = await import('./send-C44kcXz5.mjs');
18971
+ const { handleSendCommand } = await import('./send-DYeSFg8s.mjs');
18733
18972
  await handleSendCommand(args.slice(1));
18734
18973
  } catch (error) {
18735
18974
  console.error(chalk.red("Error:"), error instanceof Error ? error.message : "Unknown error");
@@ -18835,9 +19074,9 @@ Conversation history is preserved on the server, but in-flight tool calls are in
18835
19074
  if (geminiSubcommand === "project" && args[2] === "set" && args[3]) {
18836
19075
  const projectId = args[3];
18837
19076
  try {
18838
- const { saveGoogleCloudProjectToConfig } = await import('./config-DbKpQpdL.mjs');
18839
- const { readCredentialsForConfiguredRelay: readCredentialsForConfiguredRelay2 } = await import('./limits-CKR_HJnO.mjs').then(function (n) { return n.al; });
18840
- const { ApiClient: ApiClient2 } = await import('./types-xKrxbCRv.mjs').then(function (n) { return n.ah; });
19077
+ const { saveGoogleCloudProjectToConfig } = await import('./config-B-ocQh5V.mjs');
19078
+ const { readCredentialsForConfiguredRelay: readCredentialsForConfiguredRelay2 } = await import('./limits-Dt7_unH4.mjs').then(function (n) { return n.al; });
19079
+ const { ApiClient: ApiClient2 } = await import('./types-D5RWyBE5.mjs').then(function (n) { return n.ai; });
18841
19080
  let userEmail = void 0;
18842
19081
  try {
18843
19082
  const credentials = await readCredentialsForConfiguredRelay2();
@@ -18868,7 +19107,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
18868
19107
  }
18869
19108
  if (geminiSubcommand === "project" && args[2] === "get") {
18870
19109
  try {
18871
- const { readGeminiLocalConfig } = await import('./config-DbKpQpdL.mjs');
19110
+ const { readGeminiLocalConfig } = await import('./config-B-ocQh5V.mjs');
18872
19111
  const config = readGeminiLocalConfig();
18873
19112
  if (config.googleCloudProject) {
18874
19113
  console.log(`Current Google Cloud Project: ${config.googleCloudProject}`);
@@ -18908,7 +19147,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
18908
19147
  process.exit(0);
18909
19148
  }
18910
19149
  try {
18911
- const { runGemini } = await import('./runGemini-D5N11LxO.mjs');
19150
+ const { runGemini } = await import('./runGemini-BW-pEklU.mjs');
18912
19151
  let startedBy = void 0;
18913
19152
  for (let i = 1; i < args.length; i++) {
18914
19153
  if (args[i] === "--started-by") {
@@ -18931,7 +19170,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
18931
19170
  } else if (subcommand === "pi") {
18932
19171
  if (args[1] === "--terminal") {
18933
19172
  try {
18934
- const { runPiTerminal } = await import('./piTerminal-BLSXK1u2.mjs');
19173
+ const { runPiTerminal } = await import('./piTerminal-CCEGCQOY.mjs');
18935
19174
  process.exitCode = await runPiTerminal(args.slice(2));
18936
19175
  } catch (error) {
18937
19176
  console.error(chalk.red("Error:"), error instanceof Error ? error.message : "Unknown error");
@@ -18948,7 +19187,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
18948
19187
  }
18949
19188
  };
18950
19189
  try {
18951
- const { runAcp, resolveAcpAgentConfig } = await import('./index-DahaLbu4.mjs');
19190
+ const { runAcp, resolveAcpAgentConfig } = await import('./index-ZKuBjvHi.mjs');
18952
19191
  const parsed = parsePiRunnerArgs(args.slice(1));
18953
19192
  const resolved = resolveAcpAgentConfig(["pi", ...parsed.passthrough]);
18954
19193
  const { credentials } = await authAndSetupMachineIfNeeded();
@@ -18976,7 +19215,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
18976
19215
  return;
18977
19216
  } else if (subcommand === "acp") {
18978
19217
  try {
18979
- const { runAcp, resolveAcpAgentConfig } = await import('./index-DahaLbu4.mjs');
19218
+ const { runAcp, resolveAcpAgentConfig } = await import('./index-ZKuBjvHi.mjs');
18980
19219
  let startedBy = void 0;
18981
19220
  let verbose = false;
18982
19221
  const acpArgs = [];
@@ -19016,7 +19255,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
19016
19255
  return;
19017
19256
  } else if (subcommand === "openclaw") {
19018
19257
  try {
19019
- const { runOpenClaw } = await import('./runOpenClaw-CCpyKbrn.mjs');
19258
+ const { runOpenClaw } = await import('./runOpenClaw-NRB6-_jU.mjs');
19020
19259
  let startedBy = void 0;
19021
19260
  let verbose = false;
19022
19261
  let gatewayUrl;
@@ -19067,7 +19306,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
19067
19306
  return;
19068
19307
  } else if (subcommand === "todo") {
19069
19308
  try {
19070
- const { handleTodoCommand } = await import('./todo-nzsqGZqp.mjs');
19309
+ const { handleTodoCommand } = await import('./todo-B2CjDg_V.mjs');
19071
19310
  await handleTodoCommand(args.slice(1));
19072
19311
  } catch (error) {
19073
19312
  console.error(JSON.stringify({ error: error instanceof Error ? error.message : "Todo command failed" }));
@@ -19076,7 +19315,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
19076
19315
  return;
19077
19316
  } else if (subcommand === "teams") {
19078
19317
  try {
19079
- const { handleTeamsCommand } = await import('./teams-Bs8lI887.mjs');
19318
+ const { handleTeamsCommand } = await import('./teams-pfKHpkgL.mjs');
19080
19319
  await handleTeamsCommand(args.slice(1));
19081
19320
  } catch (error) {
19082
19321
  console.error(error instanceof Error ? error.message : "Teams command failed");
@@ -19085,7 +19324,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
19085
19324
  return;
19086
19325
  } else if (subcommand === "auto") {
19087
19326
  try {
19088
- const { handleAutoCommand } = await import('./auto-DV5emt1-.mjs');
19327
+ const { handleAutoCommand } = await import('./auto-BQnncDcs.mjs');
19089
19328
  await handleAutoCommand(args.slice(1));
19090
19329
  } catch (error) {
19091
19330
  console.error(chalk.red("Error:"), error instanceof Error ? error.message : "Automation command failed");
@@ -19097,7 +19336,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
19097
19336
  return;
19098
19337
  } else if (subcommand === "mcp" && (args.length === 1 || args.length === 2 && args[1] === "--terminal-tools")) {
19099
19338
  try {
19100
- const { handleMcpCommand } = await import('./mcp-D4dAo5BQ.mjs');
19339
+ const { handleMcpCommand } = await import('./mcp-9Ui4nQZL.mjs');
19101
19340
  await handleMcpCommand(args[1] === "--terminal-tools");
19102
19341
  } catch (error) {
19103
19342
  process.stderr.write(`[very-happy mcp] Fatal: ${error instanceof Error ? error.message : String(error)}
@@ -19467,4 +19706,4 @@ ${chalk.bold("Examples:")}
19467
19706
  }
19468
19707
  }
19469
19708
 
19470
- export { CHANGE_TITLE_INSTRUCTION as $, ALLOWED_SPAWN_PERMISSION_MODES as A, createSessionMetadata as B, setupOfflineReconnection as C, DEFAULT_RECENT_LIMIT as D, StreamRelay as E, MessageQueue2 as F, GEMINI_MODEL_ENV as G, hashObject as H, startHappyServer as I, registerAgentAttachmentDownloads as J, TitleGenerator as K, registerKillSessionHandler as L, MAX_READ_LIMIT as M, CLAUDE_ATTACHMENT_KINDS as N, stageClaudeAttachments as O, PI_TEAMS_EXTENSION as P, appendStagedAttachmentsToPrompt as Q, BasePermissionHandler as R, SPAWN_AGENTS as S, TurnWaitTimeoutError as T, writeSessionModeFile as U, normalizeAcpPermissionMode as V, removeSessionModeFile as W, GEMINI_API_KEY_ENV as X, GOOGLE_API_KEY_ENV as Y, BaseReasoningProcessor as Z, MessageBuffer as _, listSessions as a, resolvePermissionRequest as b, archiveSession as c, sendUserMessage as d, sessionWebUrl as e, DEFAULT_GEMINI_MODEL as f, describeTrigger as g, describeAction as h, sanitizeSpawnPermissionMode as i, tmuxSupportsSessionEnv as j, readSessionMetadata as k, listAccountSessions as l, resolveSpawnPermissionMode as m, resolveFirstMessageMeta as n, isValidSpawnOrigin as o, parseDuration as p, query as q, readSessionTranscript as r, stopSession as s, triggerFromFlags as t, waitForSessionKey as u, checkPreviewPath as v, waitForTurnEnd as w, registerAssistantSessionTools as x, TEAM_SKILL as y, initialMachineMetadata as z };
19709
+ export { BaseReasoningProcessor as $, ALLOWED_SPAWN_PERMISSION_MODES as A, TEAM_SKILL as B, initialMachineMetadata as C, DEFAULT_RECENT_LIMIT as D, createSessionMetadata as E, setupOfflineReconnection as F, GEMINI_MODEL_ENV as G, StreamRelay as H, MessageQueue2 as I, hashObject as J, startHappyServer as K, registerAgentAttachmentDownloads as L, MAX_READ_LIMIT as M, TitleGenerator as N, registerKillSessionHandler as O, PI_TEAMS_EXTENSION as P, CLAUDE_ATTACHMENT_KINDS as Q, stageClaudeAttachments as R, SPAWN_AGENTS as S, TurnWaitTimeoutError as T, appendStagedAttachmentsToPrompt as U, BasePermissionHandler as V, writeSessionModeFile as W, normalizeAcpPermissionMode as X, removeSessionModeFile as Y, GEMINI_API_KEY_ENV as Z, GOOGLE_API_KEY_ENV as _, listSessions as a, MessageBuffer as a0, CHANGE_TITLE_INSTRUCTION as a1, resolvePermissionRequest as b, archiveSession as c, deliverToSession as d, sessionWebUrl as e, DEFAULT_GEMINI_MODEL as f, describeTrigger as g, describeAction as h, sanitizeSpawnPermissionMode as i, tmuxSupportsSessionEnv as j, readSessionMetadata as k, listAccountSessions as l, resolveSpawnPermissionMode as m, resolveFirstMessageMeta as n, isValidSpawnOrigin as o, parseDuration as p, query as q, readSessionTranscript as r, stopSession as s, triggerFromFlags as t, waitForSessionKey as u, sendUserMessage as v, waitForTurnEnd as w, checkPreviewPath as x, registerAssistantSessionTools as y, suggestTitleForPrompt as z };
@@ -1,14 +1,14 @@
1
1
  'use strict';
2
2
 
3
- var AcpBackend = require('./AcpBackend-CogiKCng.cjs');
4
- var persistence = require('./limits-BNTWyUaZ.cjs');
5
- var AcpSessionManager = require('./AcpSessionManager-BazkBuFo.cjs');
6
- var index$1 = require('./index-ZIW1jrYm.cjs');
7
- var piRuntime = require('./piRuntime-Bn5ypbjH.cjs');
3
+ var AcpBackend = require('./AcpBackend-B14xNj5L.cjs');
4
+ var persistence = require('./limits-CmzISka2.cjs');
5
+ var AcpSessionManager = require('./AcpSessionManager-CCHmPdrR.cjs');
6
+ var index$1 = require('./index-eCjkm8Y2.cjs');
7
+ var piRuntime = require('./piRuntime-BesGGPME.cjs');
8
8
  var node_crypto = require('node:crypto');
9
9
  var path = require('node:path');
10
- var index = require('./types-CN28qJl7.cjs');
11
- var projectPath = require('./projectPath-ChLhdOyt.cjs');
10
+ var index = require('./types-Bd_TGr0F.cjs');
11
+ var terminalTitleSuggest = require('./terminalTitleSuggest-Dji8I0Jy.cjs');
12
12
  require('node:child_process');
13
13
  require('@agentclientprotocol/sdk');
14
14
  require('node:fs/promises');
@@ -21,7 +21,7 @@ require('node:util');
21
21
  require('@paralleldrive/cuid2');
22
22
  require('cross-spawn');
23
23
  require('node:readline');
24
- require('./agentGuidance-CqBn77AI.cjs');
24
+ require('./agentGuidance-DUBXppv-.cjs');
25
25
  require('fs/promises');
26
26
  require('ink');
27
27
  require('react');
@@ -688,7 +688,7 @@ async function runAcp(opts) {
688
688
  if (opts.agentName === "pi") session.updateAgentState((state2) => ({ ...state2, contextUsage: null }));
689
689
  const mcpServers = {
690
690
  happy: {
691
- command: path.join(projectPath.projectPath(), "bin", "very-happy-mcp.mjs"),
691
+ command: path.join(terminalTitleSuggest.projectPath(), "bin", "very-happy-mcp.mjs"),
692
692
  args: ["--url", happyServer.url]
693
693
  }
694
694
  };
@@ -1,11 +1,11 @@
1
- import { q as query } from './index-BauTv2jB.mjs';
1
+ import { q as query } from './index-BELV05ko.mjs';
2
2
  export { AbortError } from '@anthropic-ai/claude-agent-sdk';
3
3
  import 'chalk';
4
4
  import 'node:os';
5
5
  import 'node:crypto';
6
- import './types-xKrxbCRv.mjs';
6
+ import './types-D5RWyBE5.mjs';
7
7
  import 'axios';
8
- import './limits-CKR_HJnO.mjs';
8
+ import './limits-Dt7_unH4.mjs';
9
9
  import 'node:fs/promises';
10
10
  import 'node:fs';
11
11
  import 'node:path';
@@ -21,7 +21,7 @@ import 'fs/promises';
21
21
  import 'crypto';
22
22
  import 'path';
23
23
  import 'cross-spawn';
24
- import './projectPath-CSpqWdxp.mjs';
24
+ import './terminalTitleSuggest-DKgX3osW.mjs';
25
25
  import 'url';
26
26
  import 'os';
27
27
  import 'node:child_process';
@@ -30,7 +30,7 @@ import 'fs';
30
30
  import 'node:readline';
31
31
  import '@anthropic-ai/sandbox-runtime';
32
32
  import 'expo-server-sdk';
33
- import './agentGuidance-Daxn5Nvj.mjs';
33
+ import './agentGuidance-TLYQxsm2.mjs';
34
34
  import 'ink';
35
35
  import 'react';
36
36
  import 'ps-list';