very-happy-cli 0.2.108 → 0.2.109

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 (33) hide show
  1. package/dist/{AcpBackend-D4vV6SVl.cjs → AcpBackend-Cc4Ilypg.cjs} +1 -1
  2. package/dist/{AcpBackend-DwR8rrkS.mjs → AcpBackend-DOzPxcth.mjs} +1 -1
  3. package/dist/{AcpSessionManager-CPHDZ-nz.cjs → AcpSessionManager-CLfzatC_.cjs} +1 -1
  4. package/dist/{AcpSessionManager-C057dkLF.mjs → AcpSessionManager-DDN-Yir4.mjs} +1 -1
  5. package/dist/{config-BvVwprR0.cjs → config-DiVKfYr0.cjs} +2 -2
  6. package/dist/{config-DKMwLc1k.mjs → config-DnvzvFHR.mjs} +2 -2
  7. package/dist/{index-C7N-ONU_.cjs → index-B2U15moC.cjs} +2 -2
  8. package/dist/{index-DYY1DUOD.mjs → index-CGKxZKlo.mjs} +2 -2
  9. package/dist/{index-Db5m34eh.cjs → index-D2qU5HP4.cjs} +4 -4
  10. package/dist/{index-CzSv4d_S.mjs → index-DO-9Ep72.mjs} +175 -89
  11. package/dist/{index-BXnHT-Wu.mjs → index-DaQIcHvY.mjs} +5 -5
  12. package/dist/{index-DM0Ku1Rv.cjs → index-dd2R8uSE.cjs} +185 -92
  13. package/dist/index.cjs +2 -2
  14. package/dist/index.mjs +2 -2
  15. package/dist/{installTerminalHooks-Cs49gg_E.mjs → installTerminalHooks-BDagPTQW.mjs} +2 -2
  16. package/dist/{installTerminalHooks-BpvWmkZ9.cjs → installTerminalHooks-BoUmuYdq.cjs} +2 -2
  17. package/dist/lib.cjs +1 -1
  18. package/dist/lib.mjs +1 -1
  19. package/dist/{mcp-DY17lhMH.mjs → mcp-Ck_y0mCB.mjs} +2 -2
  20. package/dist/{mcp-rTSmj-tn.cjs → mcp-Du1QEnIf.cjs} +2 -2
  21. package/dist/{runGemini-Bqs52hw_.mjs → runGemini-D20S6Lc3.mjs} +4 -4
  22. package/dist/{runGemini-B3Mme1zr.cjs → runGemini-DV2M0A_k.cjs} +4 -4
  23. package/dist/{runOpenClaw-B2V9j9Le.cjs → runOpenClaw-C1Q2zl--.cjs} +3 -3
  24. package/dist/{runOpenClaw-CpbsQ7NZ.mjs → runOpenClaw-CuuXkfDE.mjs} +3 -3
  25. package/dist/{send-CLdMBQ8e.cjs → send-CtgnnJic.cjs} +2 -2
  26. package/dist/{send-uHgpvIqm.mjs → send-yUiBqHHL.mjs} +2 -2
  27. package/dist/sessions-BsaCq0Do.mjs +200 -0
  28. package/dist/sessions-CbbZhOTy.cjs +204 -0
  29. package/dist/{spawn-Dt4ujmHH.mjs → spawn-BKBY9P3J.mjs} +16 -3
  30. package/dist/{spawn-BXbVzbMs.cjs → spawn-CTO_hR8v.cjs} +16 -3
  31. package/dist/{types-D0-nhvuW.mjs → types-BKCvo4Cv.mjs} +8 -8
  32. package/dist/{types-D4bwyM-D.cjs → types-Cg8zzX_f.cjs} +8 -8
  33. package/package.json +7 -7
@@ -3,7 +3,7 @@
3
3
  var chalk = require('chalk');
4
4
  var os = require('node:os');
5
5
  var node_crypto = require('node:crypto');
6
- var persistence = require('./types-D4bwyM-D.cjs');
6
+ var persistence = require('./types-Cg8zzX_f.cjs');
7
7
  var spawn = require('cross-spawn');
8
8
  var path = require('node:path');
9
9
  var node_readline = require('node:readline');
@@ -4444,16 +4444,23 @@ function claudeModeHash(mode) {
4444
4444
  });
4445
4445
  }
4446
4446
 
4447
- function assistantSpawnTags(env = process.env) {
4448
- if (env.HAPPY_SPAWNED_BY !== "assistant") return void 0;
4447
+ const SPAWN_ORIGIN_TAG_MAX = 24;
4448
+ function spawnOriginTags(env = process.env) {
4449
4449
  if (env.HAPPY_SESSION_VARIANT === "assistant") return void 0;
4450
- return ["assistant"];
4450
+ const origin = (env.HAPPY_SPAWNED_BY ?? "").trim();
4451
+ if (!origin) return void 0;
4452
+ if (origin.length > SPAWN_ORIGIN_TAG_MAX) return void 0;
4453
+ if (!/^[a-z0-9][a-z0-9_-]*$/.test(origin)) return void 0;
4454
+ return [origin];
4455
+ }
4456
+ function isValidSpawnOrigin(value) {
4457
+ return spawnOriginTags({ HAPPY_SPAWNED_BY: value }) !== void 0;
4451
4458
  }
4452
4459
  function createSessionMetadata(opts) {
4453
4460
  const state = {
4454
4461
  controlledByUser: false
4455
4462
  };
4456
- const assistantTags = assistantSpawnTags();
4463
+ const originTags = spawnOriginTags();
4457
4464
  const metadata = {
4458
4465
  path: process.cwd(),
4459
4466
  host: os.hostname(),
@@ -4474,10 +4481,10 @@ function createSessionMetadata(opts) {
4474
4481
  dangerouslySkipPermissions: opts.dangerouslySkipPermissions ?? null,
4475
4482
  ...opts.parentSessionId ? { parentSessionId: opts.parentSessionId } : {},
4476
4483
  ...opts.forkedFromMessageId ? { forkedFromMessageId: opts.forkedFromMessageId } : {},
4477
- // B-091: assistant-dispatched sessions carry the 'assistant' tag from
4478
- // birth (see assistantSpawnTags) — applies to every flavor the daemon
4484
+ // B-091/B-303: dispatched sessions carry their spawn origin as a tag
4485
+ // from birth (see spawnOriginTags) — applies to every flavor the daemon
4479
4486
  // can spawn, since HAPPY_SPAWNED_BY is exported flavor-independently.
4480
- ...assistantTags ? { tags: assistantTags } : {}
4487
+ ...originTags ? { tags: originTags } : {}
4481
4488
  };
4482
4489
  return { state, metadata };
4483
4490
  }
@@ -6936,7 +6943,7 @@ function parseJsonObject(text) {
6936
6943
  return null;
6937
6944
  }
6938
6945
  }
6939
- 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-DM0Ku1Rv.cjs', document.baseURI).href))).resolve(s)) {
6946
+ 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-dd2R8uSE.cjs', document.baseURI).href))).resolve(s)) {
6940
6947
  const platformArch = `${platform}-${arch}`;
6941
6948
  const candidates = [
6942
6949
  `@anthropic-ai/claude-agent-sdk-${platformArch}/claude`,
@@ -9319,6 +9326,109 @@ function formatTranscript(bodies) {
9319
9326
  return lines.join("\n");
9320
9327
  }
9321
9328
 
9329
+ const SESSION_OPS_CLIENT = "session-ops";
9330
+ const DEFAULT_RECENT_LIMIT = 15;
9331
+ const MAX_READ_LIMIT = 100;
9332
+ function mergeSessionSummaries(live, persisted, options = {}) {
9333
+ const recentLimit = Math.max(0, options.recentLimit ?? DEFAULT_RECENT_LIMIT);
9334
+ const seen = /* @__PURE__ */ new Set();
9335
+ const summaries = [];
9336
+ for (const child of live) {
9337
+ const id = typeof child.happySessionId === "string" ? child.happySessionId : void 0;
9338
+ if (!id || seen.has(id)) continue;
9339
+ seen.add(id);
9340
+ summaries.push(toSummary(id, persisted[id], {
9341
+ live: true,
9342
+ pid: typeof child.pid === "number" ? child.pid : void 0
9343
+ }));
9344
+ }
9345
+ const rest = Object.entries(persisted).filter(([id]) => !seen.has(id)).filter(([, entry]) => entry.metadata?.flavor !== "terminal-mirror").sort((a, b) => b[1].savedAt - a[1].savedAt).slice(0, recentLimit);
9346
+ for (const [id, entry] of rest) {
9347
+ summaries.push(toSummary(id, entry, { live: false }));
9348
+ }
9349
+ if (!options.tag) return summaries;
9350
+ const wanted = options.tag;
9351
+ return summaries.filter((summary) => summary.tags?.includes(wanted) === true);
9352
+ }
9353
+ function toSummary(id, persisted, extra) {
9354
+ const meta = persisted?.metadata;
9355
+ return {
9356
+ id,
9357
+ live: extra.live,
9358
+ ...extra.pid !== void 0 ? { pid: extra.pid } : {},
9359
+ ...meta?.summary?.text ? { title: meta.summary.text } : {},
9360
+ ...meta?.path ? { cwd: meta.path } : {},
9361
+ ...meta?.flavor ? { flavor: meta.flavor } : {},
9362
+ ...meta?.tags?.length ? { tags: [...meta.tags] } : {},
9363
+ ...meta?.variant ? { variant: meta.variant } : {},
9364
+ url: sessionWebUrl(id),
9365
+ ...persisted?.savedAt !== void 0 ? { savedAt: persisted.savedAt } : {}
9366
+ };
9367
+ }
9368
+ async function listSessions(options = {}) {
9369
+ const live = await listDaemonSessions();
9370
+ return mergeSessionSummaries(live, persistence.readPersistedSessions(), options);
9371
+ }
9372
+ async function bearerToken() {
9373
+ const credentials = await persistence.readCredentialsForConfiguredRelay();
9374
+ if (!credentials) throw new Error("CLI is not authenticated (no ~/.happy/access.key)");
9375
+ return credentials.token;
9376
+ }
9377
+ async function readSessionTranscript(sessionId, limit) {
9378
+ const persisted = persistence.readPersistedSessions()[sessionId];
9379
+ if (!persisted) {
9380
+ throw new Error(
9381
+ `No local key for session ${sessionId} \u2014 it was not spawned by this machine's daemon (or is older than 14 days).`
9382
+ );
9383
+ }
9384
+ const bounded = Math.max(1, Math.min(MAX_READ_LIMIT, Math.floor(limit)));
9385
+ const token = await bearerToken();
9386
+ const response = await axios.get(
9387
+ `${persistence.configuration.serverUrl}/v3/sessions/${encodeURIComponent(sessionId)}/messages`,
9388
+ {
9389
+ params: { before_seq: 2147483647, limit: bounded },
9390
+ headers: {
9391
+ "Authorization": `Bearer ${token}`,
9392
+ "X-Happy-Client": `${SESSION_OPS_CLIENT}/${persistence.configuration.currentCliVersion}`
9393
+ },
9394
+ timeout: 15e3
9395
+ }
9396
+ );
9397
+ const messages = Array.isArray(response.data?.messages) ? response.data.messages : [];
9398
+ messages.reverse();
9399
+ const key = persistence.decodeBase64(persisted.encryptionKey);
9400
+ const bodies = messages.map((message) => {
9401
+ if (message.content?.t !== "encrypted") return null;
9402
+ try {
9403
+ return persistence.decrypt(key, persisted.encryptionVariant, persistence.decodeBase64(message.content.c));
9404
+ } catch {
9405
+ return null;
9406
+ }
9407
+ });
9408
+ return {
9409
+ summary: toSummary(sessionId, persisted, { live: false }),
9410
+ messageCount: messages.length,
9411
+ transcript: formatTranscript(bodies)
9412
+ };
9413
+ }
9414
+ async function stopSession(sessionId) {
9415
+ return await stopDaemonSession(sessionId);
9416
+ }
9417
+ async function archiveSession(sessionId) {
9418
+ const token = await bearerToken();
9419
+ await axios.post(
9420
+ `${persistence.configuration.serverUrl}/v1/sessions/${encodeURIComponent(sessionId)}/archive`,
9421
+ {},
9422
+ {
9423
+ headers: {
9424
+ "Authorization": `Bearer ${token}`,
9425
+ "X-Happy-Client": `${SESSION_OPS_CLIENT}/${persistence.configuration.currentCliVersion}`
9426
+ },
9427
+ timeout: 1e4
9428
+ }
9429
+ );
9430
+ }
9431
+
9322
9432
  const PERSONAL_MEMORY_SOFT_LIMIT_CHARS = 2e3;
9323
9433
  function headingTitle(line) {
9324
9434
  const m = /^##(?!#)\s*(.*?)\s*$/.exec(line);
@@ -9415,19 +9525,24 @@ function fail(text) {
9415
9525
  function describeSession(id, persisted, extra) {
9416
9526
  const meta = persisted?.metadata;
9417
9527
  const parts = [id];
9418
- if (extra?.live !== void 0) parts.push(extra.live ? "[running]" : "[not running]");
9419
9528
  if (meta?.summary?.text) parts.push(`title="${meta.summary.text}"`);
9420
9529
  if (meta?.path) parts.push(`cwd=${meta.path}`);
9421
9530
  if (meta?.flavor) parts.push(`agent=${meta.flavor}`);
9531
+ if (meta?.tags?.length) parts.push(`tags=${meta.tags.join(",")}`);
9422
9532
  if (meta?.variant === "assistant") parts.push("(assistant)");
9423
- if (extra?.pid) parts.push(`pid=${extra.pid}`);
9424
9533
  parts.push(sessionWebUrl(id));
9425
9534
  return parts.join(" ");
9426
9535
  }
9427
- async function bearerToken() {
9428
- const credentials = await persistence.readCredentialsForConfiguredRelay();
9429
- if (!credentials) throw new Error("CLI is not authenticated (no ~/.happy/access.key)");
9430
- return credentials.token;
9536
+ function describeSummary(summary) {
9537
+ const parts = [summary.id, summary.live ? "[running]" : "[not running]"];
9538
+ if (summary.title) parts.push(`title="${summary.title}"`);
9539
+ if (summary.cwd) parts.push(`cwd=${summary.cwd}`);
9540
+ if (summary.flavor) parts.push(`agent=${summary.flavor}`);
9541
+ if (summary.tags?.length) parts.push(`tags=${summary.tags.join(",")}`);
9542
+ if (summary.variant === "assistant") parts.push("(assistant)");
9543
+ if (summary.pid !== void 0) parts.push(`pid=${summary.pid}`);
9544
+ parts.push(summary.url);
9545
+ return parts.join(" ");
9431
9546
  }
9432
9547
  function registerAssistantTools(mcp) {
9433
9548
  mcp.registerTool("sessions_list", {
@@ -9436,22 +9551,10 @@ function registerAssistantTools(mcp) {
9436
9551
  inputSchema: {}
9437
9552
  }, async () => {
9438
9553
  try {
9439
- const live = await listDaemonSessions();
9440
- const persisted = persistence.readPersistedSessions();
9441
- const lines = [];
9442
- const seen = /* @__PURE__ */ new Set();
9443
- for (const child of live) {
9444
- const id = child.happySessionId;
9445
- seen.add(id);
9446
- lines.push(describeSession(id, persisted[id], { pid: child.pid, live: true }));
9447
- }
9448
- const rest = Object.entries(persisted).filter(([id]) => !seen.has(id)).filter(([, entry]) => entry.metadata?.flavor !== "terminal-mirror").sort((a, b) => b[1].savedAt - a[1].savedAt).slice(0, 15);
9449
- for (const [id, entry] of rest) {
9450
- lines.push(describeSession(id, entry, { live: false }));
9451
- }
9452
- if (lines.length === 0) return ok("No sessions found on this machine.");
9453
- return ok(`${lines.length} session(s):
9454
- ${lines.join("\n")}`);
9554
+ const sessions = await listSessions();
9555
+ if (sessions.length === 0) return ok("No sessions found on this machine.");
9556
+ return ok(`${sessions.length} session(s):
9557
+ ${sessions.map(describeSummary).join("\n")}`);
9455
9558
  } catch (error) {
9456
9559
  return fail(`Failed to list sessions: ${error instanceof Error ? error.message : String(error)}`);
9457
9560
  }
@@ -9465,37 +9568,12 @@ ${lines.join("\n")}`);
9465
9568
  }
9466
9569
  }, async (args) => {
9467
9570
  if (!persistence.isValidSessionId(args.sessionId)) return fail("Invalid sessionId");
9468
- const limit = Math.max(1, Math.min(100, Math.floor(args.limit ?? 20)));
9469
9571
  try {
9470
- const persisted = persistence.readPersistedSessions()[args.sessionId];
9471
- if (!persisted) {
9472
- return fail(`No local key for session ${args.sessionId} \u2014 it was not spawned by this machine's daemon (or is older than 14 days).`);
9473
- }
9474
- const token = await bearerToken();
9475
- const response = await axios.get(
9476
- `${persistence.configuration.serverUrl}/v3/sessions/${encodeURIComponent(args.sessionId)}/messages`,
9477
- {
9478
- params: { before_seq: 2147483647, limit },
9479
- headers: { "Authorization": `Bearer ${token}`, "X-Happy-Client": `${MCP_CLIENT_TAG}/${persistence.configuration.currentCliVersion}` },
9480
- timeout: 15e3
9481
- }
9482
- );
9483
- const messages = Array.isArray(response.data?.messages) ? response.data.messages : [];
9484
- messages.reverse();
9485
- const key = persistence.decodeBase64(persisted.encryptionKey);
9486
- const bodies = messages.map((m) => {
9487
- if (m.content?.t !== "encrypted") return null;
9488
- try {
9489
- return persistence.decrypt(key, persisted.encryptionVariant, persistence.decodeBase64(m.content.c));
9490
- } catch {
9491
- return null;
9492
- }
9493
- });
9494
- const transcript = formatTranscript(bodies);
9495
- const header = describeSession(args.sessionId, persisted);
9496
- return ok(`${header}
9497
- --- last ${messages.length} message(s) ---
9498
- ${transcript.length > 0 ? transcript : "(no readable conversation content in this range)"}`);
9572
+ const result = await readSessionTranscript(args.sessionId, args.limit ?? 20);
9573
+ const body = result.transcript.length > 0 ? result.transcript : "(no readable conversation content in this range)";
9574
+ return ok(`${describeSummary(result.summary)}
9575
+ --- last ${result.messageCount} message(s) ---
9576
+ ${body}`);
9499
9577
  } catch (error) {
9500
9578
  return fail(`Failed to read session: ${error instanceof Error ? error.message : String(error)}`);
9501
9579
  }
@@ -9560,7 +9638,7 @@ ${transcript.length > 0 ? transcript : "(no readable conversation content in thi
9560
9638
  if (!persistence.isValidSessionId(args.sessionId)) return fail("Invalid sessionId");
9561
9639
  try {
9562
9640
  const persisted = persistence.readPersistedSessions()[args.sessionId];
9563
- const success = await stopDaemonSession(args.sessionId);
9641
+ const success = await stopSession(args.sessionId);
9564
9642
  if (!success) return fail(`Session ${args.sessionId} was not found among the daemon's running sessions.`);
9565
9643
  return ok(`Stopped ${describeSession(args.sessionId, persisted)}`);
9566
9644
  } catch (error) {
@@ -9576,15 +9654,7 @@ ${transcript.length > 0 ? transcript : "(no readable conversation content in thi
9576
9654
  }, async (args) => {
9577
9655
  if (!persistence.isValidSessionId(args.sessionId)) return fail("Invalid sessionId");
9578
9656
  try {
9579
- const token = await bearerToken();
9580
- await axios.post(
9581
- `${persistence.configuration.serverUrl}/v1/sessions/${encodeURIComponent(args.sessionId)}/archive`,
9582
- {},
9583
- {
9584
- headers: { "Authorization": `Bearer ${token}`, "X-Happy-Client": `${MCP_CLIENT_TAG}/${persistence.configuration.currentCliVersion}` },
9585
- timeout: 1e4
9586
- }
9587
- );
9657
+ await archiveSession(args.sessionId);
9588
9658
  const persisted = persistence.readPersistedSessions()[args.sessionId];
9589
9659
  return ok(`Archived ${describeSession(args.sessionId, persisted)}`);
9590
9660
  } catch (error) {
@@ -10260,7 +10330,7 @@ function registerSideQuestionHandler(rpc, deps) {
10260
10330
  const retainMs = deps.retainMs ?? SIDE_QUESTION_RETAIN_MS;
10261
10331
  const maxRunMs = deps.maxRunMs ?? SIDE_QUESTION_MAX_RUN_MS;
10262
10332
  const run = deps.run ?? (async (input) => {
10263
- const { query } = await Promise.resolve().then(function () { return require('./index-C7N-ONU_.cjs'); });
10333
+ const { query } = await Promise.resolve().then(function () { return require('./index-B2U15moC.cjs'); });
10264
10334
  return runSideQuestion(query, input);
10265
10335
  });
10266
10336
  const slots = /* @__PURE__ */ new Map();
@@ -10362,7 +10432,7 @@ const MAX_TITLE_CHARS = 60;
10362
10432
  const GENERATION_TIMEOUT_MS = 3e4;
10363
10433
  function resolveClaudeBinary() {
10364
10434
  try {
10365
- 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-DM0Ku1Rv.cjs', document.baseURI).href)));
10435
+ 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-dd2R8uSE.cjs', document.baseURI).href)));
10366
10436
  const utilsPath = path.resolve(path.join(persistence.projectPath(), "scripts", "claude_version_utils.cjs"));
10367
10437
  const { getClaudeCliPath } = require$1(utilsPath);
10368
10438
  const path$1 = getClaudeCliPath();
@@ -10800,6 +10870,7 @@ async function runClaude(credentials, options = {}) {
10800
10870
  const forkedFromMessageId = process.env.HAPPY_FORKED_FROM_MESSAGE_ID;
10801
10871
  const importedFromClaudeSessionId = process.env.HAPPY_IMPORTED_FROM_CLAUDE_SESSION_ID;
10802
10872
  const importTitle = process.env.HAPPY_IMPORT_TITLE;
10873
+ const originTags = spawnOriginTags();
10803
10874
  let metadata = {
10804
10875
  path: workingDirectory,
10805
10876
  host: os.hostname(),
@@ -10832,12 +10903,13 @@ async function runClaude(credentials, options = {}) {
10832
10903
  ...importedFromClaudeSessionId ? { importedFromClaudeSessionId } : {},
10833
10904
  ...importTitle ? { summary: { text: importTitle, updatedAt: Date.now() } } : {},
10834
10905
  ...isAssistantVariant ? { variant: "assistant" } : {},
10835
- // B-091: sessions the assistant dispatched (daemon spawn RPC exports
10836
- // HAPPY_SPAWNED_BY, B-069) are born with the 'assistant' tag so every
10837
- // list shows their origin. NOT on the meta-agent itself — that one is
10838
- // the variant above and never joins the lists at all. (Shared helper:
10839
- // the other flavors get the same tag via createSessionMetadata.)
10840
- ...assistantSpawnTags() ? { tags: assistantSpawnTags() } : {}
10906
+ // B-091/B-303: dispatched sessions (daemon spawn RPC exports
10907
+ // HAPPY_SPAWNED_BY, B-069) are born tagged with their spawn origin so
10908
+ // every list shows where the work came from. NOT on the meta-agent
10909
+ // itself — that one is the variant above and never joins the lists at
10910
+ // all. (Shared helper: the other flavors get the same tag via
10911
+ // createSessionMetadata.)
10912
+ ...originTags ? { tags: originTags } : {}
10841
10913
  };
10842
10914
  const reconnectSessionId = process.env.HAPPY_RECONNECT_SESSION_ID;
10843
10915
  const reconnectKeyBase64 = process.env.HAPPY_RECONNECT_ENCRYPTION_KEY;
@@ -12562,9 +12634,9 @@ function resolveLocalSignupBootstrap(configuredMode, configuredInviteCodes, gene
12562
12634
  };
12563
12635
  }
12564
12636
 
12565
- 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-DM0Ku1Rv.cjs', document.baseURI).href)));
12637
+ 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-dd2R8uSE.cjs', document.baseURI).href)));
12566
12638
  const __dirname$1 = path.dirname(__filename$1);
12567
- const require_ = node_module.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index-DM0Ku1Rv.cjs', document.baseURI).href)));
12639
+ const require_ = node_module.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index-dd2R8uSE.cjs', document.baseURI).href)));
12568
12640
  const PRISMA_QUERY_ENGINE_FILES = {
12569
12641
  "arm64-darwin": "libquery_engine-darwin-arm64.dylib.node",
12570
12642
  "x64-darwin": "libquery_engine-darwin.dylib.node",
@@ -15188,7 +15260,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
15188
15260
  process.exit(0);
15189
15261
  } else if (subcommand === "install-terminal-hooks") {
15190
15262
  try {
15191
- const { installTerminalHooks, parseTerminalHooksArgs, TERMINAL_HOOKS_HELP } = await Promise.resolve().then(function () { return require('./installTerminalHooks-BpvWmkZ9.cjs'); });
15263
+ const { installTerminalHooks, parseTerminalHooksArgs, TERMINAL_HOOKS_HELP } = await Promise.resolve().then(function () { return require('./installTerminalHooks-BoUmuYdq.cjs'); });
15192
15264
  const command = parseTerminalHooksArgs(args.slice(1));
15193
15265
  if (command.action === "help") {
15194
15266
  console.log(TERMINAL_HOOKS_HELP);
@@ -15205,7 +15277,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
15205
15277
  }
15206
15278
  } else if (subcommand === "spawn") {
15207
15279
  try {
15208
- const { handleSpawnCommand } = await Promise.resolve().then(function () { return require('./spawn-BXbVzbMs.cjs'); });
15280
+ const { handleSpawnCommand } = await Promise.resolve().then(function () { return require('./spawn-CTO_hR8v.cjs'); });
15209
15281
  await handleSpawnCommand(args.slice(1));
15210
15282
  } catch (error) {
15211
15283
  console.error(chalk.red("Error:"), error instanceof Error ? error.message : "Unknown error");
@@ -15215,9 +15287,21 @@ Conversation history is preserved on the server, but in-flight tool calls are in
15215
15287
  process.exit(1);
15216
15288
  }
15217
15289
  return;
15290
+ } else if (subcommand === "sessions") {
15291
+ try {
15292
+ const { handleSessionsCommand } = await Promise.resolve().then(function () { return require('./sessions-CbbZhOTy.cjs'); });
15293
+ await handleSessionsCommand(args.slice(1));
15294
+ } catch (error) {
15295
+ console.error(chalk.red("Error:"), error instanceof Error ? error.message : "Unknown error");
15296
+ if (process.env.DEBUG) {
15297
+ console.error(error);
15298
+ }
15299
+ process.exit(1);
15300
+ }
15301
+ return;
15218
15302
  } else if (subcommand === "send") {
15219
15303
  try {
15220
- const { handleSendCommand } = await Promise.resolve().then(function () { return require('./send-CLdMBQ8e.cjs'); });
15304
+ const { handleSendCommand } = await Promise.resolve().then(function () { return require('./send-CtgnnJic.cjs'); });
15221
15305
  await handleSendCommand(args.slice(1));
15222
15306
  } catch (error) {
15223
15307
  console.error(chalk.red("Error:"), error instanceof Error ? error.message : "Unknown error");
@@ -15323,9 +15407,9 @@ Conversation history is preserved on the server, but in-flight tool calls are in
15323
15407
  if (geminiSubcommand === "project" && args[2] === "set" && args[3]) {
15324
15408
  const projectId = args[3];
15325
15409
  try {
15326
- const { saveGoogleCloudProjectToConfig } = await Promise.resolve().then(function () { return require('./config-BvVwprR0.cjs'); });
15327
- const { readCredentialsForConfiguredRelay: readCredentialsForConfiguredRelay2 } = await Promise.resolve().then(function () { return require('./types-D4bwyM-D.cjs'); }).then(function (n) { return n.persistence; });
15328
- const { ApiClient: ApiClient2 } = await Promise.resolve().then(function () { return require('./types-D4bwyM-D.cjs'); }).then(function (n) { return n.api; });
15410
+ const { saveGoogleCloudProjectToConfig } = await Promise.resolve().then(function () { return require('./config-DiVKfYr0.cjs'); });
15411
+ const { readCredentialsForConfiguredRelay: readCredentialsForConfiguredRelay2 } = await Promise.resolve().then(function () { return require('./types-Cg8zzX_f.cjs'); }).then(function (n) { return n.persistence; });
15412
+ const { ApiClient: ApiClient2 } = await Promise.resolve().then(function () { return require('./types-Cg8zzX_f.cjs'); }).then(function (n) { return n.api; });
15329
15413
  let userEmail = void 0;
15330
15414
  try {
15331
15415
  const credentials = await readCredentialsForConfiguredRelay2();
@@ -15356,7 +15440,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
15356
15440
  }
15357
15441
  if (geminiSubcommand === "project" && args[2] === "get") {
15358
15442
  try {
15359
- const { readGeminiLocalConfig } = await Promise.resolve().then(function () { return require('./config-BvVwprR0.cjs'); });
15443
+ const { readGeminiLocalConfig } = await Promise.resolve().then(function () { return require('./config-DiVKfYr0.cjs'); });
15360
15444
  const config = readGeminiLocalConfig();
15361
15445
  if (config.googleCloudProject) {
15362
15446
  console.log(`Current Google Cloud Project: ${config.googleCloudProject}`);
@@ -15396,7 +15480,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
15396
15480
  process.exit(0);
15397
15481
  }
15398
15482
  try {
15399
- const { runGemini } = await Promise.resolve().then(function () { return require('./runGemini-B3Mme1zr.cjs'); });
15483
+ const { runGemini } = await Promise.resolve().then(function () { return require('./runGemini-DV2M0A_k.cjs'); });
15400
15484
  let startedBy = void 0;
15401
15485
  for (let i = 1; i < args.length; i++) {
15402
15486
  if (args[i] === "--started-by") {
@@ -15418,7 +15502,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
15418
15502
  return;
15419
15503
  } else if (subcommand === "acp") {
15420
15504
  try {
15421
- const { runAcp, resolveAcpAgentConfig } = await Promise.resolve().then(function () { return require('./index-Db5m34eh.cjs'); });
15505
+ const { runAcp, resolveAcpAgentConfig } = await Promise.resolve().then(function () { return require('./index-D2qU5HP4.cjs'); });
15422
15506
  let startedBy = void 0;
15423
15507
  let verbose = false;
15424
15508
  const acpArgs = [];
@@ -15458,7 +15542,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
15458
15542
  return;
15459
15543
  } else if (subcommand === "openclaw") {
15460
15544
  try {
15461
- const { runOpenClaw } = await Promise.resolve().then(function () { return require('./runOpenClaw-B2V9j9Le.cjs'); });
15545
+ const { runOpenClaw } = await Promise.resolve().then(function () { return require('./runOpenClaw-C1Q2zl--.cjs'); });
15462
15546
  let startedBy = void 0;
15463
15547
  let verbose = false;
15464
15548
  let gatewayUrl;
@@ -15509,7 +15593,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
15509
15593
  return;
15510
15594
  } else if (subcommand === "mcp" && args.length === 1) {
15511
15595
  try {
15512
- const { handleMcpCommand } = await Promise.resolve().then(function () { return require('./mcp-rTSmj-tn.cjs'); });
15596
+ const { handleMcpCommand } = await Promise.resolve().then(function () { return require('./mcp-Du1QEnIf.cjs'); });
15513
15597
  await handleMcpCommand();
15514
15598
  } catch (error) {
15515
15599
  process.stderr.write(`[very-happy mcp] Fatal: ${error instanceof Error ? error.message : String(error)}
@@ -15724,6 +15808,8 @@ ${chalk.bold("Usage:")}
15724
15808
  print its web URL (for automation; see spawn --help)
15725
15809
  very-happy send Send a message into an existing session
15726
15810
  (for automation; see send --help)
15811
+ very-happy sessions List, read, stop or archive sessions on this
15812
+ machine (for automation; see sessions --help)
15727
15813
  very-happy codex Start Codex mode
15728
15814
  very-happy gemini Start Gemini mode (ACP)
15729
15815
  very-happy acp Start a generic ACP-compatible agent
@@ -15869,23 +15955,30 @@ exports.BasePermissionHandler = BasePermissionHandler;
15869
15955
  exports.BaseReasoningProcessor = BaseReasoningProcessor;
15870
15956
  exports.CHANGE_TITLE_INSTRUCTION = CHANGE_TITLE_INSTRUCTION;
15871
15957
  exports.DEFAULT_GEMINI_MODEL = DEFAULT_GEMINI_MODEL;
15958
+ exports.DEFAULT_RECENT_LIMIT = DEFAULT_RECENT_LIMIT;
15872
15959
  exports.GEMINI_API_KEY_ENV = GEMINI_API_KEY_ENV;
15873
15960
  exports.GEMINI_MODEL_ENV = GEMINI_MODEL_ENV;
15874
15961
  exports.GOOGLE_API_KEY_ENV = GOOGLE_API_KEY_ENV;
15962
+ exports.MAX_READ_LIMIT = MAX_READ_LIMIT;
15875
15963
  exports.MessageBuffer = MessageBuffer;
15876
15964
  exports.MessageQueue2 = MessageQueue2;
15965
+ exports.archiveSession = archiveSession;
15877
15966
  exports.checkIfDaemonRunningAndCleanupStaleState = checkIfDaemonRunningAndCleanupStaleState;
15878
15967
  exports.createSessionMetadata = createSessionMetadata;
15879
15968
  exports.hashObject = hashObject;
15880
15969
  exports.initialMachineMetadata = initialMachineMetadata;
15970
+ exports.isValidSpawnOrigin = isValidSpawnOrigin;
15971
+ exports.listSessions = listSessions;
15881
15972
  exports.notifyDaemonSessionStarted = notifyDaemonSessionStarted;
15882
15973
  exports.pushClipboardViaDaemon = pushClipboardViaDaemon;
15883
15974
  exports.query = query;
15975
+ exports.readSessionTranscript = readSessionTranscript;
15884
15976
  exports.registerKillSessionHandler = registerKillSessionHandler;
15885
15977
  exports.sendUserMessage = sendUserMessage;
15886
15978
  exports.sessionWebUrl = sessionWebUrl;
15887
15979
  exports.setupOfflineReconnection = setupOfflineReconnection;
15888
15980
  exports.spawnDaemonSession = spawnDaemonSession;
15889
15981
  exports.startHappyServer = startHappyServer;
15982
+ exports.stopSession = stopSession;
15890
15983
  exports.tmuxSupportsSessionEnv = tmuxSupportsSessionEnv;
15891
15984
  exports.waitForSessionKey = waitForSessionKey;
package/dist/index.cjs CHANGED
@@ -1,8 +1,8 @@
1
1
  'use strict';
2
2
 
3
3
  require('chalk');
4
- require('./index-DM0Ku1Rv.cjs');
5
- require('./types-D4bwyM-D.cjs');
4
+ require('./index-dd2R8uSE.cjs');
5
+ require('./types-Cg8zzX_f.cjs');
6
6
  require('zod');
7
7
  require('node:child_process');
8
8
  require('node:os');
package/dist/index.mjs CHANGED
@@ -1,6 +1,6 @@
1
1
  import 'chalk';
2
- import './index-CzSv4d_S.mjs';
3
- import './types-D0-nhvuW.mjs';
2
+ import './index-DO-9Ep72.mjs';
3
+ import './types-BKCvo4Cv.mjs';
4
4
  import 'zod';
5
5
  import 'node:child_process';
6
6
  import 'node:os';
@@ -3,8 +3,8 @@ import { join, resolve } from 'node:path';
3
3
  import { homedir } from 'node:os';
4
4
  import { spawnSync } from 'node:child_process';
5
5
  import chalk from 'chalk';
6
- import { p as projectPath } from './types-D0-nhvuW.mjs';
7
- import { t as tmuxSupportsSessionEnv } from './index-CzSv4d_S.mjs';
6
+ import { p as projectPath } from './types-BKCvo4Cv.mjs';
7
+ import { t as tmuxSupportsSessionEnv } from './index-DO-9Ep72.mjs';
8
8
  import 'axios';
9
9
  import 'node:util';
10
10
  import 'node:fs/promises';
@@ -5,8 +5,8 @@ var path = require('node:path');
5
5
  var os = require('node:os');
6
6
  var node_child_process = require('node:child_process');
7
7
  var chalk = require('chalk');
8
- var persistence = require('./types-D4bwyM-D.cjs');
9
- var index = require('./index-DM0Ku1Rv.cjs');
8
+ var persistence = require('./types-Cg8zzX_f.cjs');
9
+ var index = require('./index-dd2R8uSE.cjs');
10
10
  require('axios');
11
11
  require('node:util');
12
12
  require('node:fs/promises');
package/dist/lib.cjs CHANGED
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- var persistence = require('./types-D4bwyM-D.cjs');
3
+ var persistence = require('./types-Cg8zzX_f.cjs');
4
4
  require('axios');
5
5
  require('chalk');
6
6
  require('node:util');
package/dist/lib.mjs CHANGED
@@ -1,4 +1,4 @@
1
- export { A as ApiClient, a as ApiSessionClient, R as RawJSONLinesSchema, c as configuration, l as logger } from './types-D0-nhvuW.mjs';
1
+ export { A as ApiClient, a as ApiSessionClient, R as RawJSONLinesSchema, c as configuration, l as logger } from './types-BKCvo4Cv.mjs';
2
2
  import 'axios';
3
3
  import 'chalk';
4
4
  import 'node:util';
@@ -1,9 +1,9 @@
1
1
  import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
2
  import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
3
3
  import { z } from 'zod';
4
- import { p as pushClipboardViaDaemon } from './index-CzSv4d_S.mjs';
4
+ import { p as pushClipboardViaDaemon } from './index-DO-9Ep72.mjs';
5
5
  import { C as CLIPBOARD_TOOL_NAME, a as CLIPBOARD_TOOL_TITLE, b as CLIPBOARD_TOOL_DESCRIPTION, c as CLIPBOARD_MAX_BYTES } from './limits-CwFb5S2b.mjs';
6
- import { l as logger } from './types-D0-nhvuW.mjs';
6
+ import { l as logger } from './types-BKCvo4Cv.mjs';
7
7
  import 'chalk';
8
8
  import 'node:os';
9
9
  import 'node:crypto';
@@ -3,9 +3,9 @@
3
3
  var mcp_js = require('@modelcontextprotocol/sdk/server/mcp.js');
4
4
  var stdio_js = require('@modelcontextprotocol/sdk/server/stdio.js');
5
5
  var z = require('zod');
6
- var index = require('./index-DM0Ku1Rv.cjs');
6
+ var index = require('./index-dd2R8uSE.cjs');
7
7
  var limits = require('./limits-KdWKmwtH.cjs');
8
- var persistence = require('./types-D4bwyM-D.cjs');
8
+ var persistence = require('./types-Cg8zzX_f.cjs');
9
9
  require('chalk');
10
10
  require('node:os');
11
11
  require('node:crypto');
@@ -2,10 +2,10 @@ import { useStdout, useInput, Box, Text, render } from 'ink';
2
2
  import React, { useState, useRef, useEffect, useCallback } from 'react';
3
3
  import { randomUUID } from 'node:crypto';
4
4
  import { join } from 'node:path';
5
- import { l as logger, h as connectionState, A as ApiClient, i as readSettings, e as errorLogMetadata, j as encodeBase64, p as projectPath, d as contentLogMetadata } from './types-D0-nhvuW.mjs';
6
- import { g as GEMINI_API_KEY_ENV, j as GOOGLE_API_KEY_ENV, G as GEMINI_MODEL_ENV, B as BasePermissionHandler, k as BaseReasoningProcessor, i as initialMachineMetadata, d as createSessionMetadata, e as setupOfflineReconnection, n as notifyDaemonSessionStarted, M as MessageQueue2, h as hashObject, l as MessageBuffer, C as CHANGE_TITLE_INSTRUCTION, r as registerKillSessionHandler, f as startHappyServer } from './index-CzSv4d_S.mjs';
7
- import { A as AcpBackend } from './AcpBackend-DwR8rrkS.mjs';
8
- import { readGeminiLocalConfig, determineGeminiModel, getGeminiModelSource, getInitialGeminiModel, saveGeminiModelToConfig } from './config-DKMwLc1k.mjs';
5
+ import { l as logger, h as connectionState, A as ApiClient, j as readSettings, e as errorLogMetadata, k as encodeBase64, p as projectPath, d as contentLogMetadata } from './types-BKCvo4Cv.mjs';
6
+ import { v as GEMINI_API_KEY_ENV, x as GOOGLE_API_KEY_ENV, G as GEMINI_MODEL_ENV, B as BasePermissionHandler, y as BaseReasoningProcessor, g as initialMachineMetadata, h as createSessionMetadata, j as setupOfflineReconnection, n as notifyDaemonSessionStarted, k as MessageQueue2, m as hashObject, z as MessageBuffer, C as CHANGE_TITLE_INSTRUCTION, u as registerKillSessionHandler, o as startHappyServer } from './index-DO-9Ep72.mjs';
7
+ import { A as AcpBackend } from './AcpBackend-DOzPxcth.mjs';
8
+ import { readGeminiLocalConfig, determineGeminiModel, getGeminiModelSource, getInitialGeminiModel, saveGeminiModelToConfig } from './config-DnvzvFHR.mjs';
9
9
  import 'axios';
10
10
  import 'chalk';
11
11
  import 'node:util';
@@ -4,10 +4,10 @@ var ink = require('ink');
4
4
  var React = require('react');
5
5
  var node_crypto = require('node:crypto');
6
6
  var path = require('node:path');
7
- var persistence = require('./types-D4bwyM-D.cjs');
8
- var index = require('./index-DM0Ku1Rv.cjs');
9
- var AcpBackend = require('./AcpBackend-D4vV6SVl.cjs');
10
- var config = require('./config-BvVwprR0.cjs');
7
+ var persistence = require('./types-Cg8zzX_f.cjs');
8
+ var index = require('./index-dd2R8uSE.cjs');
9
+ var AcpBackend = require('./AcpBackend-Cc4Ilypg.cjs');
10
+ var config = require('./config-DiVKfYr0.cjs');
11
11
  require('axios');
12
12
  require('chalk');
13
13
  require('node:util');
@@ -5,9 +5,9 @@ var node_child_process = require('node:child_process');
5
5
  var os = require('node:os');
6
6
  var node_fs = require('node:fs');
7
7
  var path = require('node:path');
8
- var persistence = require('./types-D4bwyM-D.cjs');
9
- var AcpSessionManager = require('./AcpSessionManager-CPHDZ-nz.cjs');
10
- var index = require('./index-DM0Ku1Rv.cjs');
8
+ var persistence = require('./types-Cg8zzX_f.cjs');
9
+ var AcpSessionManager = require('./AcpSessionManager-CLfzatC_.cjs');
10
+ var index = require('./index-dd2R8uSE.cjs');
11
11
  var WebSocket = require('ws');
12
12
  var ed = require('@noble/ed25519');
13
13
  var sha2_js = require('@noble/hashes/sha2.js');
@@ -3,9 +3,9 @@ import { execFileSync } from 'node:child_process';
3
3
  import os from 'node:os';
4
4
  import { existsSync, readFileSync } from 'node:fs';
5
5
  import { join } from 'node:path';
6
- import { k as ensurePrivateDirectorySync, m as hardenPrivateFileSync, w as writePrivateFileSync, e as errorLogMetadata, d as contentLogMetadata, h as connectionState, A as ApiClient, i as readSettings, j as encodeBase64, l as logger, c as configuration } from './types-D0-nhvuW.mjs';
7
- import { A as AcpSessionManager } from './AcpSessionManager-C057dkLF.mjs';
8
- import { i as initialMachineMetadata, d as createSessionMetadata, e as setupOfflineReconnection, n as notifyDaemonSessionStarted, M as MessageQueue2, r as registerKillSessionHandler } from './index-CzSv4d_S.mjs';
6
+ import { m as ensurePrivateDirectorySync, n as hardenPrivateFileSync, w as writePrivateFileSync, e as errorLogMetadata, d as contentLogMetadata, h as connectionState, A as ApiClient, j as readSettings, k as encodeBase64, l as logger, c as configuration } from './types-BKCvo4Cv.mjs';
7
+ import { A as AcpSessionManager } from './AcpSessionManager-DDN-Yir4.mjs';
8
+ import { g as initialMachineMetadata, h as createSessionMetadata, j as setupOfflineReconnection, n as notifyDaemonSessionStarted, k as MessageQueue2, u as registerKillSessionHandler } from './index-DO-9Ep72.mjs';
9
9
  import WebSocket from 'ws';
10
10
  import * as ed from '@noble/ed25519';
11
11
  import { sha512 } from '@noble/hashes/sha2.js';