very-happy-cli 0.2.107 → 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-B3WfHjyi.cjs → AcpBackend-Cc4Ilypg.cjs} +1 -1
  2. package/dist/{AcpBackend-leZGKCNL.mjs → AcpBackend-DOzPxcth.mjs} +1 -1
  3. package/dist/{AcpSessionManager-Cza1nTaQ.cjs → AcpSessionManager-CLfzatC_.cjs} +1 -1
  4. package/dist/{AcpSessionManager-CI_-4TvB.mjs → AcpSessionManager-DDN-Yir4.mjs} +1 -1
  5. package/dist/{config-CpVncJmR.cjs → config-DiVKfYr0.cjs} +2 -2
  6. package/dist/{config-TEae6YCF.mjs → config-DnvzvFHR.mjs} +2 -2
  7. package/dist/{index-RyvQwH4I.cjs → index-B2U15moC.cjs} +2 -2
  8. package/dist/{index-Dg78JF0h.mjs → index-CGKxZKlo.mjs} +2 -2
  9. package/dist/{index-b_E_olpx.cjs → index-D2qU5HP4.cjs} +4 -4
  10. package/dist/{index-CIfhQ_X6.mjs → index-DO-9Ep72.mjs} +181 -89
  11. package/dist/{index-D9H-dsUT.mjs → index-DaQIcHvY.mjs} +5 -5
  12. package/dist/{index-CF9-9B70.cjs → index-dd2R8uSE.cjs} +191 -92
  13. package/dist/index.cjs +2 -2
  14. package/dist/index.mjs +2 -2
  15. package/dist/{installTerminalHooks-tPNg8EgD.mjs → installTerminalHooks-BDagPTQW.mjs} +2 -2
  16. package/dist/{installTerminalHooks-DMSUDPG3.cjs → installTerminalHooks-BoUmuYdq.cjs} +2 -2
  17. package/dist/lib.cjs +1 -1
  18. package/dist/lib.mjs +1 -1
  19. package/dist/{mcp-DUXABUpc.mjs → mcp-Ck_y0mCB.mjs} +2 -2
  20. package/dist/{mcp-B13ZiAxa.cjs → mcp-Du1QEnIf.cjs} +2 -2
  21. package/dist/{runGemini-aCMjZ4lm.mjs → runGemini-D20S6Lc3.mjs} +4 -4
  22. package/dist/{runGemini-Dvf_ajZd.cjs → runGemini-DV2M0A_k.cjs} +4 -4
  23. package/dist/{runOpenClaw-D9v6E9th.cjs → runOpenClaw-C1Q2zl--.cjs} +3 -3
  24. package/dist/{runOpenClaw-BLdlHdZa.mjs → runOpenClaw-CuuXkfDE.mjs} +3 -3
  25. package/dist/{send-DUoz9am9.cjs → send-CtgnnJic.cjs} +2 -2
  26. package/dist/{send-DAnYf1wR.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-Gr4_bY2m.mjs → spawn-BKBY9P3J.mjs} +16 -3
  30. package/dist/{spawn-4FlGcOQK.cjs → spawn-CTO_hR8v.cjs} +16 -3
  31. package/dist/{types-DOJq8cyH.mjs → types-BKCvo4Cv.mjs} +8 -8
  32. package/dist/{types-4iIbK7lA.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-4iIbK7lA.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-CF9-9B70.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`,
@@ -9099,6 +9106,12 @@ async function startDaemon() {
9099
9106
  });
9100
9107
  claudeAuthService.start();
9101
9108
  apiMachine.connect();
9109
+ if (identityConflict?.confidence === "weak") {
9110
+ void apiMachine.updateMachineMetadata((current) => ({
9111
+ ...current ?? initialMachineMetadata,
9112
+ host: initialMachineMetadata.host
9113
+ })).then(() => persistence.logger.debug(`[DAEMON RUN] claimed the machine record for host ${initialMachineMetadata.host}`)).catch((error) => persistence.logger.debug("[DAEMON RUN] could not refresh the recorded host:", error));
9114
+ }
9102
9115
  let cliUpdateCheckRunning = false;
9103
9116
  const refreshCliUpdate = async () => {
9104
9117
  if (cliUpdateCheckRunning) return;
@@ -9313,6 +9326,109 @@ function formatTranscript(bodies) {
9313
9326
  return lines.join("\n");
9314
9327
  }
9315
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
+
9316
9432
  const PERSONAL_MEMORY_SOFT_LIMIT_CHARS = 2e3;
9317
9433
  function headingTitle(line) {
9318
9434
  const m = /^##(?!#)\s*(.*?)\s*$/.exec(line);
@@ -9409,19 +9525,24 @@ function fail(text) {
9409
9525
  function describeSession(id, persisted, extra) {
9410
9526
  const meta = persisted?.metadata;
9411
9527
  const parts = [id];
9412
- if (extra?.live !== void 0) parts.push(extra.live ? "[running]" : "[not running]");
9413
9528
  if (meta?.summary?.text) parts.push(`title="${meta.summary.text}"`);
9414
9529
  if (meta?.path) parts.push(`cwd=${meta.path}`);
9415
9530
  if (meta?.flavor) parts.push(`agent=${meta.flavor}`);
9531
+ if (meta?.tags?.length) parts.push(`tags=${meta.tags.join(",")}`);
9416
9532
  if (meta?.variant === "assistant") parts.push("(assistant)");
9417
- if (extra?.pid) parts.push(`pid=${extra.pid}`);
9418
9533
  parts.push(sessionWebUrl(id));
9419
9534
  return parts.join(" ");
9420
9535
  }
9421
- async function bearerToken() {
9422
- const credentials = await persistence.readCredentialsForConfiguredRelay();
9423
- if (!credentials) throw new Error("CLI is not authenticated (no ~/.happy/access.key)");
9424
- 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(" ");
9425
9546
  }
9426
9547
  function registerAssistantTools(mcp) {
9427
9548
  mcp.registerTool("sessions_list", {
@@ -9430,22 +9551,10 @@ function registerAssistantTools(mcp) {
9430
9551
  inputSchema: {}
9431
9552
  }, async () => {
9432
9553
  try {
9433
- const live = await listDaemonSessions();
9434
- const persisted = persistence.readPersistedSessions();
9435
- const lines = [];
9436
- const seen = /* @__PURE__ */ new Set();
9437
- for (const child of live) {
9438
- const id = child.happySessionId;
9439
- seen.add(id);
9440
- lines.push(describeSession(id, persisted[id], { pid: child.pid, live: true }));
9441
- }
9442
- 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);
9443
- for (const [id, entry] of rest) {
9444
- lines.push(describeSession(id, entry, { live: false }));
9445
- }
9446
- if (lines.length === 0) return ok("No sessions found on this machine.");
9447
- return ok(`${lines.length} session(s):
9448
- ${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")}`);
9449
9558
  } catch (error) {
9450
9559
  return fail(`Failed to list sessions: ${error instanceof Error ? error.message : String(error)}`);
9451
9560
  }
@@ -9459,37 +9568,12 @@ ${lines.join("\n")}`);
9459
9568
  }
9460
9569
  }, async (args) => {
9461
9570
  if (!persistence.isValidSessionId(args.sessionId)) return fail("Invalid sessionId");
9462
- const limit = Math.max(1, Math.min(100, Math.floor(args.limit ?? 20)));
9463
9571
  try {
9464
- const persisted = persistence.readPersistedSessions()[args.sessionId];
9465
- if (!persisted) {
9466
- 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).`);
9467
- }
9468
- const token = await bearerToken();
9469
- const response = await axios.get(
9470
- `${persistence.configuration.serverUrl}/v3/sessions/${encodeURIComponent(args.sessionId)}/messages`,
9471
- {
9472
- params: { before_seq: 2147483647, limit },
9473
- headers: { "Authorization": `Bearer ${token}`, "X-Happy-Client": `${MCP_CLIENT_TAG}/${persistence.configuration.currentCliVersion}` },
9474
- timeout: 15e3
9475
- }
9476
- );
9477
- const messages = Array.isArray(response.data?.messages) ? response.data.messages : [];
9478
- messages.reverse();
9479
- const key = persistence.decodeBase64(persisted.encryptionKey);
9480
- const bodies = messages.map((m) => {
9481
- if (m.content?.t !== "encrypted") return null;
9482
- try {
9483
- return persistence.decrypt(key, persisted.encryptionVariant, persistence.decodeBase64(m.content.c));
9484
- } catch {
9485
- return null;
9486
- }
9487
- });
9488
- const transcript = formatTranscript(bodies);
9489
- const header = describeSession(args.sessionId, persisted);
9490
- return ok(`${header}
9491
- --- last ${messages.length} message(s) ---
9492
- ${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}`);
9493
9577
  } catch (error) {
9494
9578
  return fail(`Failed to read session: ${error instanceof Error ? error.message : String(error)}`);
9495
9579
  }
@@ -9554,7 +9638,7 @@ ${transcript.length > 0 ? transcript : "(no readable conversation content in thi
9554
9638
  if (!persistence.isValidSessionId(args.sessionId)) return fail("Invalid sessionId");
9555
9639
  try {
9556
9640
  const persisted = persistence.readPersistedSessions()[args.sessionId];
9557
- const success = await stopDaemonSession(args.sessionId);
9641
+ const success = await stopSession(args.sessionId);
9558
9642
  if (!success) return fail(`Session ${args.sessionId} was not found among the daemon's running sessions.`);
9559
9643
  return ok(`Stopped ${describeSession(args.sessionId, persisted)}`);
9560
9644
  } catch (error) {
@@ -9570,15 +9654,7 @@ ${transcript.length > 0 ? transcript : "(no readable conversation content in thi
9570
9654
  }, async (args) => {
9571
9655
  if (!persistence.isValidSessionId(args.sessionId)) return fail("Invalid sessionId");
9572
9656
  try {
9573
- const token = await bearerToken();
9574
- await axios.post(
9575
- `${persistence.configuration.serverUrl}/v1/sessions/${encodeURIComponent(args.sessionId)}/archive`,
9576
- {},
9577
- {
9578
- headers: { "Authorization": `Bearer ${token}`, "X-Happy-Client": `${MCP_CLIENT_TAG}/${persistence.configuration.currentCliVersion}` },
9579
- timeout: 1e4
9580
- }
9581
- );
9657
+ await archiveSession(args.sessionId);
9582
9658
  const persisted = persistence.readPersistedSessions()[args.sessionId];
9583
9659
  return ok(`Archived ${describeSession(args.sessionId, persisted)}`);
9584
9660
  } catch (error) {
@@ -10254,7 +10330,7 @@ function registerSideQuestionHandler(rpc, deps) {
10254
10330
  const retainMs = deps.retainMs ?? SIDE_QUESTION_RETAIN_MS;
10255
10331
  const maxRunMs = deps.maxRunMs ?? SIDE_QUESTION_MAX_RUN_MS;
10256
10332
  const run = deps.run ?? (async (input) => {
10257
- const { query } = await Promise.resolve().then(function () { return require('./index-RyvQwH4I.cjs'); });
10333
+ const { query } = await Promise.resolve().then(function () { return require('./index-B2U15moC.cjs'); });
10258
10334
  return runSideQuestion(query, input);
10259
10335
  });
10260
10336
  const slots = /* @__PURE__ */ new Map();
@@ -10356,7 +10432,7 @@ const MAX_TITLE_CHARS = 60;
10356
10432
  const GENERATION_TIMEOUT_MS = 3e4;
10357
10433
  function resolveClaudeBinary() {
10358
10434
  try {
10359
- 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-CF9-9B70.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)));
10360
10436
  const utilsPath = path.resolve(path.join(persistence.projectPath(), "scripts", "claude_version_utils.cjs"));
10361
10437
  const { getClaudeCliPath } = require$1(utilsPath);
10362
10438
  const path$1 = getClaudeCliPath();
@@ -10794,6 +10870,7 @@ async function runClaude(credentials, options = {}) {
10794
10870
  const forkedFromMessageId = process.env.HAPPY_FORKED_FROM_MESSAGE_ID;
10795
10871
  const importedFromClaudeSessionId = process.env.HAPPY_IMPORTED_FROM_CLAUDE_SESSION_ID;
10796
10872
  const importTitle = process.env.HAPPY_IMPORT_TITLE;
10873
+ const originTags = spawnOriginTags();
10797
10874
  let metadata = {
10798
10875
  path: workingDirectory,
10799
10876
  host: os.hostname(),
@@ -10826,12 +10903,13 @@ async function runClaude(credentials, options = {}) {
10826
10903
  ...importedFromClaudeSessionId ? { importedFromClaudeSessionId } : {},
10827
10904
  ...importTitle ? { summary: { text: importTitle, updatedAt: Date.now() } } : {},
10828
10905
  ...isAssistantVariant ? { variant: "assistant" } : {},
10829
- // B-091: sessions the assistant dispatched (daemon spawn RPC exports
10830
- // HAPPY_SPAWNED_BY, B-069) are born with the 'assistant' tag so every
10831
- // list shows their origin. NOT on the meta-agent itself — that one is
10832
- // the variant above and never joins the lists at all. (Shared helper:
10833
- // the other flavors get the same tag via createSessionMetadata.)
10834
- ...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 } : {}
10835
10913
  };
10836
10914
  const reconnectSessionId = process.env.HAPPY_RECONNECT_SESSION_ID;
10837
10915
  const reconnectKeyBase64 = process.env.HAPPY_RECONNECT_ENCRYPTION_KEY;
@@ -12556,9 +12634,9 @@ function resolveLocalSignupBootstrap(configuredMode, configuredInviteCodes, gene
12556
12634
  };
12557
12635
  }
12558
12636
 
12559
- 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-CF9-9B70.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)));
12560
12638
  const __dirname$1 = path.dirname(__filename$1);
12561
- const require_ = node_module.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index-CF9-9B70.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)));
12562
12640
  const PRISMA_QUERY_ENGINE_FILES = {
12563
12641
  "arm64-darwin": "libquery_engine-darwin-arm64.dylib.node",
12564
12642
  "x64-darwin": "libquery_engine-darwin.dylib.node",
@@ -15182,7 +15260,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
15182
15260
  process.exit(0);
15183
15261
  } else if (subcommand === "install-terminal-hooks") {
15184
15262
  try {
15185
- const { installTerminalHooks, parseTerminalHooksArgs, TERMINAL_HOOKS_HELP } = await Promise.resolve().then(function () { return require('./installTerminalHooks-DMSUDPG3.cjs'); });
15263
+ const { installTerminalHooks, parseTerminalHooksArgs, TERMINAL_HOOKS_HELP } = await Promise.resolve().then(function () { return require('./installTerminalHooks-BoUmuYdq.cjs'); });
15186
15264
  const command = parseTerminalHooksArgs(args.slice(1));
15187
15265
  if (command.action === "help") {
15188
15266
  console.log(TERMINAL_HOOKS_HELP);
@@ -15199,7 +15277,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
15199
15277
  }
15200
15278
  } else if (subcommand === "spawn") {
15201
15279
  try {
15202
- const { handleSpawnCommand } = await Promise.resolve().then(function () { return require('./spawn-4FlGcOQK.cjs'); });
15280
+ const { handleSpawnCommand } = await Promise.resolve().then(function () { return require('./spawn-CTO_hR8v.cjs'); });
15203
15281
  await handleSpawnCommand(args.slice(1));
15204
15282
  } catch (error) {
15205
15283
  console.error(chalk.red("Error:"), error instanceof Error ? error.message : "Unknown error");
@@ -15209,9 +15287,21 @@ Conversation history is preserved on the server, but in-flight tool calls are in
15209
15287
  process.exit(1);
15210
15288
  }
15211
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;
15212
15302
  } else if (subcommand === "send") {
15213
15303
  try {
15214
- const { handleSendCommand } = await Promise.resolve().then(function () { return require('./send-DUoz9am9.cjs'); });
15304
+ const { handleSendCommand } = await Promise.resolve().then(function () { return require('./send-CtgnnJic.cjs'); });
15215
15305
  await handleSendCommand(args.slice(1));
15216
15306
  } catch (error) {
15217
15307
  console.error(chalk.red("Error:"), error instanceof Error ? error.message : "Unknown error");
@@ -15317,9 +15407,9 @@ Conversation history is preserved on the server, but in-flight tool calls are in
15317
15407
  if (geminiSubcommand === "project" && args[2] === "set" && args[3]) {
15318
15408
  const projectId = args[3];
15319
15409
  try {
15320
- const { saveGoogleCloudProjectToConfig } = await Promise.resolve().then(function () { return require('./config-CpVncJmR.cjs'); });
15321
- const { readCredentialsForConfiguredRelay: readCredentialsForConfiguredRelay2 } = await Promise.resolve().then(function () { return require('./types-4iIbK7lA.cjs'); }).then(function (n) { return n.persistence; });
15322
- const { ApiClient: ApiClient2 } = await Promise.resolve().then(function () { return require('./types-4iIbK7lA.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; });
15323
15413
  let userEmail = void 0;
15324
15414
  try {
15325
15415
  const credentials = await readCredentialsForConfiguredRelay2();
@@ -15350,7 +15440,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
15350
15440
  }
15351
15441
  if (geminiSubcommand === "project" && args[2] === "get") {
15352
15442
  try {
15353
- const { readGeminiLocalConfig } = await Promise.resolve().then(function () { return require('./config-CpVncJmR.cjs'); });
15443
+ const { readGeminiLocalConfig } = await Promise.resolve().then(function () { return require('./config-DiVKfYr0.cjs'); });
15354
15444
  const config = readGeminiLocalConfig();
15355
15445
  if (config.googleCloudProject) {
15356
15446
  console.log(`Current Google Cloud Project: ${config.googleCloudProject}`);
@@ -15390,7 +15480,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
15390
15480
  process.exit(0);
15391
15481
  }
15392
15482
  try {
15393
- const { runGemini } = await Promise.resolve().then(function () { return require('./runGemini-Dvf_ajZd.cjs'); });
15483
+ const { runGemini } = await Promise.resolve().then(function () { return require('./runGemini-DV2M0A_k.cjs'); });
15394
15484
  let startedBy = void 0;
15395
15485
  for (let i = 1; i < args.length; i++) {
15396
15486
  if (args[i] === "--started-by") {
@@ -15412,7 +15502,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
15412
15502
  return;
15413
15503
  } else if (subcommand === "acp") {
15414
15504
  try {
15415
- const { runAcp, resolveAcpAgentConfig } = await Promise.resolve().then(function () { return require('./index-b_E_olpx.cjs'); });
15505
+ const { runAcp, resolveAcpAgentConfig } = await Promise.resolve().then(function () { return require('./index-D2qU5HP4.cjs'); });
15416
15506
  let startedBy = void 0;
15417
15507
  let verbose = false;
15418
15508
  const acpArgs = [];
@@ -15452,7 +15542,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
15452
15542
  return;
15453
15543
  } else if (subcommand === "openclaw") {
15454
15544
  try {
15455
- const { runOpenClaw } = await Promise.resolve().then(function () { return require('./runOpenClaw-D9v6E9th.cjs'); });
15545
+ const { runOpenClaw } = await Promise.resolve().then(function () { return require('./runOpenClaw-C1Q2zl--.cjs'); });
15456
15546
  let startedBy = void 0;
15457
15547
  let verbose = false;
15458
15548
  let gatewayUrl;
@@ -15503,7 +15593,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
15503
15593
  return;
15504
15594
  } else if (subcommand === "mcp" && args.length === 1) {
15505
15595
  try {
15506
- const { handleMcpCommand } = await Promise.resolve().then(function () { return require('./mcp-B13ZiAxa.cjs'); });
15596
+ const { handleMcpCommand } = await Promise.resolve().then(function () { return require('./mcp-Du1QEnIf.cjs'); });
15507
15597
  await handleMcpCommand();
15508
15598
  } catch (error) {
15509
15599
  process.stderr.write(`[very-happy mcp] Fatal: ${error instanceof Error ? error.message : String(error)}
@@ -15718,6 +15808,8 @@ ${chalk.bold("Usage:")}
15718
15808
  print its web URL (for automation; see spawn --help)
15719
15809
  very-happy send Send a message into an existing session
15720
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)
15721
15813
  very-happy codex Start Codex mode
15722
15814
  very-happy gemini Start Gemini mode (ACP)
15723
15815
  very-happy acp Start a generic ACP-compatible agent
@@ -15863,23 +15955,30 @@ exports.BasePermissionHandler = BasePermissionHandler;
15863
15955
  exports.BaseReasoningProcessor = BaseReasoningProcessor;
15864
15956
  exports.CHANGE_TITLE_INSTRUCTION = CHANGE_TITLE_INSTRUCTION;
15865
15957
  exports.DEFAULT_GEMINI_MODEL = DEFAULT_GEMINI_MODEL;
15958
+ exports.DEFAULT_RECENT_LIMIT = DEFAULT_RECENT_LIMIT;
15866
15959
  exports.GEMINI_API_KEY_ENV = GEMINI_API_KEY_ENV;
15867
15960
  exports.GEMINI_MODEL_ENV = GEMINI_MODEL_ENV;
15868
15961
  exports.GOOGLE_API_KEY_ENV = GOOGLE_API_KEY_ENV;
15962
+ exports.MAX_READ_LIMIT = MAX_READ_LIMIT;
15869
15963
  exports.MessageBuffer = MessageBuffer;
15870
15964
  exports.MessageQueue2 = MessageQueue2;
15965
+ exports.archiveSession = archiveSession;
15871
15966
  exports.checkIfDaemonRunningAndCleanupStaleState = checkIfDaemonRunningAndCleanupStaleState;
15872
15967
  exports.createSessionMetadata = createSessionMetadata;
15873
15968
  exports.hashObject = hashObject;
15874
15969
  exports.initialMachineMetadata = initialMachineMetadata;
15970
+ exports.isValidSpawnOrigin = isValidSpawnOrigin;
15971
+ exports.listSessions = listSessions;
15875
15972
  exports.notifyDaemonSessionStarted = notifyDaemonSessionStarted;
15876
15973
  exports.pushClipboardViaDaemon = pushClipboardViaDaemon;
15877
15974
  exports.query = query;
15975
+ exports.readSessionTranscript = readSessionTranscript;
15878
15976
  exports.registerKillSessionHandler = registerKillSessionHandler;
15879
15977
  exports.sendUserMessage = sendUserMessage;
15880
15978
  exports.sessionWebUrl = sessionWebUrl;
15881
15979
  exports.setupOfflineReconnection = setupOfflineReconnection;
15882
15980
  exports.spawnDaemonSession = spawnDaemonSession;
15883
15981
  exports.startHappyServer = startHappyServer;
15982
+ exports.stopSession = stopSession;
15884
15983
  exports.tmuxSupportsSessionEnv = tmuxSupportsSessionEnv;
15885
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-CF9-9B70.cjs');
5
- require('./types-4iIbK7lA.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-CIfhQ_X6.mjs';
3
- import './types-DOJq8cyH.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-DOJq8cyH.mjs';
7
- import { t as tmuxSupportsSessionEnv } from './index-CIfhQ_X6.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-4iIbK7lA.cjs');
9
- var index = require('./index-CF9-9B70.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-4iIbK7lA.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-DOJq8cyH.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-CIfhQ_X6.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-DOJq8cyH.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-CF9-9B70.cjs');
6
+ var index = require('./index-dd2R8uSE.cjs');
7
7
  var limits = require('./limits-KdWKmwtH.cjs');
8
- var persistence = require('./types-4iIbK7lA.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-DOJq8cyH.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-CIfhQ_X6.mjs';
7
- import { A as AcpBackend } from './AcpBackend-leZGKCNL.mjs';
8
- import { readGeminiLocalConfig, determineGeminiModel, getGeminiModelSource, getInitialGeminiModel, saveGeminiModelToConfig } from './config-TEae6YCF.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-4iIbK7lA.cjs');
8
- var index = require('./index-CF9-9B70.cjs');
9
- var AcpBackend = require('./AcpBackend-B3WfHjyi.cjs');
10
- var config = require('./config-CpVncJmR.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-4iIbK7lA.cjs');
9
- var AcpSessionManager = require('./AcpSessionManager-Cza1nTaQ.cjs');
10
- var index = require('./index-CF9-9B70.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');