very-happy-cli 0.2.104 → 0.2.106

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-DDGfk3HJ.cjs → AcpBackend-DMmvLNNM.cjs} +1 -1
  2. package/dist/{AcpBackend-De4iQ_JG.mjs → AcpBackend-Ux5FD_6F.mjs} +1 -1
  3. package/dist/{AcpSessionManager-DRzAgHtT.mjs → AcpSessionManager-C1hoU_rK.mjs} +1 -1
  4. package/dist/{AcpSessionManager-Cdv6Xgwy.cjs → AcpSessionManager-RYkxYWDn.cjs} +1 -1
  5. package/dist/{config-E3KdWyaQ.mjs → config-DAb5saOC.mjs} +2 -2
  6. package/dist/{config-CqM5UxVd.cjs → config-Dkn5KcXp.cjs} +2 -2
  7. package/dist/{index-CX_3uUem.cjs → index-BLW-smJu.cjs} +209 -71
  8. package/dist/{index--TiLl7-A.mjs → index-CgWdwkhB.mjs} +205 -67
  9. package/dist/{index-C_dmtMJ6.mjs → index-D2ZzPm58.mjs} +5 -5
  10. package/dist/{index-De6H3U0N.cjs → index-D48mWUTN.cjs} +2 -2
  11. package/dist/{index-Bzj1XdPx.mjs → index-DCpgRGWy.mjs} +2 -2
  12. package/dist/{index-fuavV8uc.cjs → index-Do3JnAi7.cjs} +4 -4
  13. package/dist/index.cjs +2 -2
  14. package/dist/index.mjs +2 -2
  15. package/dist/{installTerminalHooks-BXMBwrvq.cjs → installTerminalHooks-9rn15uP8.cjs} +2 -2
  16. package/dist/{installTerminalHooks-DV0e8-V3.mjs → installTerminalHooks-l1B-nbWa.mjs} +2 -2
  17. package/dist/lib.cjs +1 -1
  18. package/dist/lib.d.cts +6 -0
  19. package/dist/lib.d.mts +6 -0
  20. package/dist/lib.mjs +1 -1
  21. package/dist/{mcp-Cq3On_Qo.cjs → mcp-C3zpbx-m.cjs} +2 -2
  22. package/dist/{mcp-DFS9Zohz.mjs → mcp-ZvHzv_lJ.mjs} +2 -2
  23. package/dist/{runGemini-BFjtlkZI.mjs → runGemini-0QqaFN1l.mjs} +4 -4
  24. package/dist/{runGemini-DFvjh8cO.cjs → runGemini-q20IdxQV.cjs} +4 -4
  25. package/dist/{runOpenClaw-BFYj1F4u.mjs → runOpenClaw-C6Z6MLHq.mjs} +3 -3
  26. package/dist/{runOpenClaw-B5Og1FED.cjs → runOpenClaw-CtWkyvDJ.cjs} +3 -3
  27. package/dist/{send-Bog0YPxo.cjs → send-B8YQyV3D.cjs} +2 -2
  28. package/dist/{send-B666yos0.mjs → send-DEhUWg8v.mjs} +2 -2
  29. package/dist/{spawn-DrqvVoNF.mjs → spawn-BzbPyTHU.mjs} +2 -2
  30. package/dist/{spawn-BSdMkMPX.cjs → spawn-ChmlP1Z_.cjs} +2 -2
  31. package/dist/{types-14LATr9X.cjs → types-C8-WODFE.cjs} +24 -10
  32. package/dist/{types-D9LyZitb.mjs → types-lSeHEzPR.mjs} +23 -9
  33. package/package.json +7 -7
@@ -3,7 +3,7 @@
3
3
  var node_child_process = require('node:child_process');
4
4
  var sdk = require('@agentclientprotocol/sdk');
5
5
  var node_crypto = require('node:crypto');
6
- var persistence = require('./types-14LATr9X.cjs');
6
+ var persistence = require('./types-C8-WODFE.cjs');
7
7
 
8
8
  const DEFAULT_TIMEOUTS = {
9
9
  /** Default initialization timeout: 60 seconds */
@@ -1,7 +1,7 @@
1
1
  import { spawn } from 'node:child_process';
2
2
  import { ndJsonStream, ClientSideConnection } from '@agentclientprotocol/sdk';
3
3
  import { randomUUID } from 'node:crypto';
4
- import { l as logger, d as contentLogMetadata, e as errorLogMetadata, f as packageJson, g as delay } from './types-D9LyZitb.mjs';
4
+ import { l as logger, d as contentLogMetadata, e as errorLogMetadata, f as packageJson, g as delay } from './types-lSeHEzPR.mjs';
5
5
 
6
6
  const DEFAULT_TIMEOUTS = {
7
7
  /** Default initialization timeout: 60 seconds */
@@ -1,5 +1,5 @@
1
1
  import { createId } from '@paralleldrive/cuid2';
2
- import { b as createEnvelope } from './types-D9LyZitb.mjs';
2
+ import { b as createEnvelope } from './types-lSeHEzPR.mjs';
3
3
 
4
4
  function turnOptions(turnId, time) {
5
5
  return turnId ? { turn: turnId, time } : { time };
@@ -1,7 +1,7 @@
1
1
  'use strict';
2
2
 
3
3
  var cuid2 = require('@paralleldrive/cuid2');
4
- var persistence = require('./types-14LATr9X.cjs');
4
+ var persistence = require('./types-C8-WODFE.cjs');
5
5
 
6
6
  function turnOptions(turnId, time) {
7
7
  return turnId ? { turn: turnId, time } : { time };
@@ -2,8 +2,8 @@ import { existsSync, readFileSync, mkdirSync, writeFileSync } from 'fs';
2
2
  import { join } from 'path';
3
3
  import { homedir } from 'os';
4
4
  import { execSync } from 'child_process';
5
- import { l as logger } from './types-D9LyZitb.mjs';
6
- import { D as DEFAULT_GEMINI_MODEL, G as GEMINI_MODEL_ENV } from './index--TiLl7-A.mjs';
5
+ import { l as logger } from './types-lSeHEzPR.mjs';
6
+ import { D as DEFAULT_GEMINI_MODEL, G as GEMINI_MODEL_ENV } from './index-CgWdwkhB.mjs';
7
7
  import 'axios';
8
8
  import 'chalk';
9
9
  import 'node:util';
@@ -4,8 +4,8 @@ var fs = require('fs');
4
4
  var path = require('path');
5
5
  var os = require('os');
6
6
  var child_process = require('child_process');
7
- var persistence = require('./types-14LATr9X.cjs');
8
- var index = require('./index-CX_3uUem.cjs');
7
+ var persistence = require('./types-C8-WODFE.cjs');
8
+ var index = require('./index-BLW-smJu.cjs');
9
9
  require('axios');
10
10
  require('chalk');
11
11
  require('node:util');
@@ -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-14LATr9X.cjs');
6
+ var persistence = require('./types-C8-WODFE.cjs');
7
7
  var spawn = require('cross-spawn');
8
8
  var path = require('node:path');
9
9
  var node_readline = require('node:readline');
@@ -1929,6 +1929,18 @@ async function awaitFileExist(file, timeout = 1e4) {
1929
1929
  return false;
1930
1930
  }
1931
1931
 
1932
+ function modelTarget(model) {
1933
+ return model == null || model === "" ? void 0 : model;
1934
+ }
1935
+ function needsModelSwitch(current, next) {
1936
+ return modelTarget(current) !== modelTarget(next);
1937
+ }
1938
+ function modelSwitchFailureNotice(model, error) {
1939
+ const name = modelTarget(model) ?? "default";
1940
+ const detail = error instanceof Error ? error.message : String(error);
1941
+ return `\u26A0\uFE0F Could not switch to model "${name}" \u2014 continuing with the previous model. ${detail}`;
1942
+ }
1943
+
1932
1944
  async function claudeRemote(opts) {
1933
1945
  let startFrom = opts.sessionId;
1934
1946
  if (opts.sessionId && !claudeCheckSession(opts.sessionId, opts.path)) {
@@ -2035,11 +2047,12 @@ async function claudeRemote(opts) {
2035
2047
  if (opts.onQueryReady) {
2036
2048
  opts.onQueryReady({
2037
2049
  setPermissionMode: (mode2) => response.setPermissionMode(mode2),
2050
+ setModel: (model) => response.setModel(modelTarget(model)),
2038
2051
  interrupt: async () => {
2039
2052
  await response.interrupt();
2040
2053
  },
2041
2054
  steer: (message, nextMode) => {
2042
- mode = nextMode;
2055
+ mode = { ...nextMode, model: mode.model };
2043
2056
  messages.push({
2044
2057
  type: "user",
2045
2058
  parent_tool_use_id: null,
@@ -2071,7 +2084,10 @@ async function claudeRemote(opts) {
2071
2084
  mcpServers: systemInit.mcp_servers?.map((s) => ({ name: s.name, status: s.status })),
2072
2085
  skills: systemInit.skills,
2073
2086
  model: systemInit.model,
2074
- modelIsDefault: initial.mode.model == null,
2087
+ // `mode`, not `initial.mode`: the model can move mid-Query
2088
+ // via setModel, and init is re-emitted every turn with the
2089
+ // model actually in force.
2090
+ modelIsDefault: modelTarget(mode.model) === void 0,
2075
2091
  // The SDK's own verdict on the mode it will enforce —
2076
2092
  // settings (permissions.deny/ask/defaultMode/
2077
2093
  // disableBypassPermissionsMode) can override what we
@@ -2116,19 +2132,29 @@ async function claudeRemote(opts) {
2116
2132
  messages.end();
2117
2133
  continue;
2118
2134
  }
2119
- opts.nextMessage().then((next) => {
2135
+ opts.nextMessage().then(async (next) => {
2120
2136
  if (!next) {
2121
2137
  messages.end();
2122
- } else {
2123
- mode = next.mode;
2124
- updateThinking(true);
2125
- messages.push({
2126
- type: "user",
2127
- parent_tool_use_id: null,
2128
- origin: { kind: "human" },
2129
- message: { role: "user", content: next.message }
2130
- });
2138
+ return;
2139
+ }
2140
+ if (needsModelSwitch(mode.model, next.mode.model)) {
2141
+ try {
2142
+ await response.setModel(modelTarget(next.mode.model));
2143
+ persistence.logger.debug(`[claudeRemote] Model switched to ${modelTarget(next.mode.model) ?? "default"}`);
2144
+ } catch (e) {
2145
+ persistence.logger.debug(`[claudeRemote] setModel failed: ${e instanceof Error ? e.message : String(e)}`);
2146
+ opts.onCompletionEvent?.(modelSwitchFailureNotice(next.mode.model, e));
2147
+ next = { ...next, mode: { ...next.mode, model: mode.model } };
2148
+ }
2131
2149
  }
2150
+ mode = next.mode;
2151
+ updateThinking(true);
2152
+ messages.push({
2153
+ type: "user",
2154
+ parent_tool_use_id: null,
2155
+ origin: { kind: "human" },
2156
+ message: { role: "user", content: next.message }
2157
+ });
2132
2158
  }).catch(() => {
2133
2159
  messages.end();
2134
2160
  });
@@ -3409,6 +3435,12 @@ function applyClaudeSdkMetadata(current, update) {
3409
3435
  skills: update.skills,
3410
3436
  attachmentKinds: [...CLAUDE_ATTACHMENT_KINDS],
3411
3437
  queueCancellation: true,
3438
+ // The model Claude Code reports it is ACTUALLY running. system/init is
3439
+ // re-emitted at every turn boundary (verified against the pinned SDK,
3440
+ // 2026-09-03), including after a live setModel, so this is the web's
3441
+ // only ground truth for "did my switch take effect" — the picker
3442
+ // otherwise renders nothing but the client's own optimistic intent.
3443
+ ...update.model ? { currentModelCode: update.model } : {},
3412
3444
  ...update.modelIsDefault && update.model ? { defaultModelCode: update.model } : {}
3413
3445
  };
3414
3446
  }
@@ -3443,6 +3475,102 @@ function createTurnSteeringController() {
3443
3475
  };
3444
3476
  }
3445
3477
 
3478
+ class LaunchModeGate {
3479
+ constructor(hasher) {
3480
+ this.hasher = hasher;
3481
+ }
3482
+ currentMode = null;
3483
+ currentHash = null;
3484
+ parked = null;
3485
+ /** The mode this launch is running, or null before the first message. */
3486
+ get mode() {
3487
+ return this.currentMode;
3488
+ }
3489
+ /** Hash of {@link mode}; null means "not armed yet — accept anything". */
3490
+ get hash() {
3491
+ return this.currentHash;
3492
+ }
3493
+ /** Whether a message has been adopted into this launch yet. */
3494
+ get armed() {
3495
+ return this.currentHash !== null;
3496
+ }
3497
+ /** Bind the launch to `mode`. Idempotent; safe to call with the same mode. */
3498
+ adopt(mode) {
3499
+ this.currentMode = mode;
3500
+ this.currentHash = this.hasher(mode);
3501
+ }
3502
+ /**
3503
+ * Re-adopt the current mode with one field replaced. No-op before the first
3504
+ * adopt: there is nothing to derive from, and arming here would make the
3505
+ * first real message look like a mode change.
3506
+ */
3507
+ amend(patch) {
3508
+ if (this.currentMode === null) return null;
3509
+ this.adopt({ ...this.currentMode, ...patch });
3510
+ return this.currentMode;
3511
+ }
3512
+ /**
3513
+ * True when `incomingHash` cannot run on this launch's Query and must be
3514
+ * parked for a fresh one. An un-armed gate accepts anything — that is how a
3515
+ * new launch takes its first message, including a replayed parked one.
3516
+ */
3517
+ requiresRelaunch(incomingHash, isolate) {
3518
+ if (isolate) return true;
3519
+ return this.armed && incomingHash !== this.currentHash;
3520
+ }
3521
+ /** True when `mode` is exactly what this launch adopted (Steer's precondition). */
3522
+ matches(mode) {
3523
+ return this.armed && this.hasher(mode) === this.currentHash;
3524
+ }
3525
+ /**
3526
+ * Hold a message that cannot run on this launch until its successor picks
3527
+ * it up. Survives {@link reset} — the parked message is precisely what the
3528
+ * next launch exists to run.
3529
+ */
3530
+ park(message) {
3531
+ this.parked = message;
3532
+ }
3533
+ /** Whether a parked message is waiting for the next launch. */
3534
+ get hasParked() {
3535
+ return this.parked !== null;
3536
+ }
3537
+ /**
3538
+ * Take the parked message AND adopt its mode in one step.
3539
+ *
3540
+ * This pairing is the whole point of the class. When parking and adopting
3541
+ * were separate — a `pending` variable in the launcher next to a `modeHash`
3542
+ * one — the replay path took the message and forgot to adopt, so the gate
3543
+ * stayed un-armed and swallowed the NEXT mode change into a Query built for
3544
+ * the previous one. Nothing structural tied the two, and no unit test could
3545
+ * reach the wiring. Here they cannot come apart.
3546
+ */
3547
+ takeParked() {
3548
+ const message = this.parked;
3549
+ if (!message) return null;
3550
+ this.parked = null;
3551
+ this.adopt(message.mode);
3552
+ return message;
3553
+ }
3554
+ /**
3555
+ * Re-adopt the parked message with a patched mode. Used when an explicit
3556
+ * mode switch lands while a message is parked: the switch is newer than the
3557
+ * snapshot the message carried when it was queued.
3558
+ */
3559
+ amendParked(patch) {
3560
+ if (!this.parked) return;
3561
+ this.parked = { ...this.parked, mode: { ...this.parked.mode, ...patch } };
3562
+ }
3563
+ /**
3564
+ * Drop back to un-armed. Called when a launch ends. Deliberately does NOT
3565
+ * clear a parked message: parking happens in the launch that is ending, and
3566
+ * the message belongs to the one about to start.
3567
+ */
3568
+ reset() {
3569
+ this.currentMode = null;
3570
+ this.currentHash = null;
3571
+ }
3572
+ }
3573
+
3446
3574
  async function claudeRemoteLauncher(session, onPermissionModeChange, onEffectivePermissionMode) {
3447
3575
  persistence.logger.debug("[claudeRemoteLauncher] Starting remote launcher");
3448
3576
  const hasTTY = process.stdout.isTTY && process.stdin.isTTY;
@@ -3650,7 +3778,7 @@ async function claudeRemoteLauncher(session, onPermissionModeChange, onEffective
3650
3778
  }
3651
3779
  }
3652
3780
  try {
3653
- let pending = null;
3781
+ const modeGate = new LaunchModeGate(session.queue.modeHasher);
3654
3782
  let previousSessionId = null;
3655
3783
  while (!exitReason) {
3656
3784
  persistence.logger.debug("[remote]: launch");
@@ -3669,18 +3797,11 @@ async function claudeRemoteLauncher(session, onPermissionModeChange, onEffective
3669
3797
  const controller = new AbortController();
3670
3798
  abortController = controller;
3671
3799
  abortFuture = new Future();
3672
- let modeHash = null;
3673
- let mode = null;
3674
3800
  const commitPermissionMode = (nextMode) => {
3675
3801
  permissionHandler.handleModeChange(nextMode);
3676
- if (mode) {
3677
- mode = { ...mode, permissionMode: nextMode };
3678
- modeHash = session.queue.modeHasher(mode);
3679
- }
3802
+ modeGate.amend({ permissionMode: nextMode });
3680
3803
  rewriteQueuedPermissionMode(session.queue.queue, session.queue.modeHasher, nextMode);
3681
- if (pending) {
3682
- pending = { ...pending, mode: { ...pending.mode, permissionMode: nextMode } };
3683
- }
3804
+ modeGate.amendParked({ permissionMode: nextMode });
3684
3805
  onPermissionModeChange?.(nextMode);
3685
3806
  return nextMode;
3686
3807
  };
@@ -3706,22 +3827,28 @@ async function claudeRemoteLauncher(session, onPermissionModeChange, onEffective
3706
3827
  return permissionHandler.isAborted(toolCallId);
3707
3828
  },
3708
3829
  nextMessage: async () => {
3709
- if (pending) {
3710
- let p = pending;
3711
- pending = null;
3712
- permissionHandler.handleModeChange(p.mode.permissionMode);
3713
- return p;
3830
+ const parked = modeGate.takeParked();
3831
+ if (parked) {
3832
+ permissionHandler.handleModeChange(parked.mode.permissionMode);
3833
+ return parked;
3714
3834
  }
3715
3835
  let msg = await session.queue.waitForMessagesAndGetAsString(controller.signal);
3716
3836
  if (msg) {
3717
- if (modeHash && msg.hash !== modeHash || msg.isolate) {
3837
+ if (modeGate.requiresRelaunch(msg.hash, msg.isolate)) {
3718
3838
  persistence.logger.debug("[remote]: mode has changed, pending message");
3719
- pending = msg;
3839
+ const parkedAttachments = msg.attachments ?? [];
3840
+ const parkedStaged = parkedAttachments.length > 0 ? await stageClaudeAttachments(parkedAttachments, {
3841
+ happyHomeDir: persistence.configuration.happyHomeDir,
3842
+ sessionId: session.client.sessionId
3843
+ }) : [];
3844
+ modeGate.park({
3845
+ message: parkedStaged.length > 0 ? appendStagedAttachmentsToPrompt(msg.message, parkedStaged) : msg.message,
3846
+ mode: msg.mode
3847
+ });
3720
3848
  return null;
3721
3849
  }
3722
- modeHash = msg.hash;
3723
- mode = msg.mode;
3724
- permissionHandler.handleModeChange(mode.permissionMode);
3850
+ modeGate.adopt(msg.mode);
3851
+ permissionHandler.handleModeChange(msg.mode.permissionMode);
3725
3852
  const attachments = msg.attachments ?? [];
3726
3853
  if (attachments.length > 0) {
3727
3854
  const staged = await stageClaudeAttachments(attachments, {
@@ -3758,8 +3885,7 @@ async function claudeRemoteLauncher(session, onPermissionModeChange, onEffective
3758
3885
  onQueryReady: (q) => {
3759
3886
  turnSteering.setInterrupt(q.interrupt);
3760
3887
  session.setSteerHandler(async (input) => {
3761
- const expectedHash = session.queue.modeHasher(input.mode);
3762
- if (!modeHash || expectedHash !== modeHash) return false;
3888
+ if (!modeGate.matches(input.mode)) return false;
3763
3889
  let message = input.message;
3764
3890
  if (input.attachments?.length) {
3765
3891
  const staged = await stageClaudeAttachments(input.attachments, {
@@ -3768,19 +3894,16 @@ async function claudeRemoteLauncher(session, onPermissionModeChange, onEffective
3768
3894
  });
3769
3895
  message = appendStagedAttachmentsToPrompt(input.message, staged);
3770
3896
  }
3771
- if (!session.thinking || modeHash !== expectedHash) return false;
3897
+ if (!session.thinking || !modeGate.matches(input.mode)) return false;
3772
3898
  q.steer(message, input.mode);
3773
3899
  return true;
3774
3900
  });
3775
- permissionHandler.setPermissionModeUpdater(async (mode2) => {
3776
- await q.setPermissionMode(mode2);
3901
+ permissionHandler.setPermissionModeUpdater(async (mode) => {
3902
+ await q.setPermissionMode(mode);
3777
3903
  });
3778
3904
  livePermissionModeHandler = async (nextMode) => {
3779
3905
  await permissionHandler.setLivePermissionMode(nextMode);
3780
- if (mode) {
3781
- mode = { ...mode, permissionMode: nextMode };
3782
- modeHash = session.queue.modeHasher(mode);
3783
- }
3906
+ modeGate.amend({ permissionMode: nextMode });
3784
3907
  onPermissionModeChange?.(nextMode);
3785
3908
  return nextMode;
3786
3909
  };
@@ -3811,7 +3934,7 @@ async function claudeRemoteLauncher(session, onPermissionModeChange, onEffective
3811
3934
  closeFailed: (error) => session.client.closeClaudeSessionTurn("failed", { error }),
3812
3935
  onFailed: (error) => session.onSessionError(error),
3813
3936
  onCompleted: () => {
3814
- const idle = !pending && session.queue.size() === 0;
3937
+ const idle = !modeGate.hasParked && session.queue.size() === 0;
3815
3938
  session.onTurnEnd(idle);
3816
3939
  if (idle) {
3817
3940
  session.api.push().sendSessionNotification({
@@ -3870,8 +3993,7 @@ async function claudeRemoteLauncher(session, onPermissionModeChange, onEffective
3870
3993
  abortFuture = null;
3871
3994
  persistence.logger.debug("[remote]: launch done");
3872
3995
  permissionHandler.reset();
3873
- modeHash = null;
3874
- mode = null;
3996
+ modeGate.reset();
3875
3997
  }
3876
3998
  }
3877
3999
  } finally {
@@ -4168,6 +4290,7 @@ class MessageQueue2 {
4168
4290
  while (this.queue.length > 0 && this.queue[0].modeHash === targetModeHash && !this.queue[0].isolate) {
4169
4291
  const item = this.queue.shift();
4170
4292
  sameModeMessages.push(item.message);
4293
+ mode = item.mode;
4171
4294
  if (item.attachments) collectedAttachments.push(...item.attachments);
4172
4295
  }
4173
4296
  persistence.logger.debug(`[MessageQueue2] Collected batch of ${sameModeMessages.length} messages with mode hash: ${targetModeHash}`);
@@ -4309,6 +4432,18 @@ function hashObject(obj, options, encoding = "hex") {
4309
4432
  return crypto.createHash("sha256").update(jsonString).digest(encoding);
4310
4433
  }
4311
4434
 
4435
+ function claudeModeHash(mode) {
4436
+ return hashObject({
4437
+ isPlan: mode.permissionMode === "plan",
4438
+ fallbackModel: mode.fallbackModel,
4439
+ customSystemPrompt: mode.customSystemPrompt,
4440
+ appendSystemPrompt: mode.appendSystemPrompt,
4441
+ allowedTools: mode.allowedTools,
4442
+ disallowedTools: mode.disallowedTools,
4443
+ effort: mode.effort
4444
+ });
4445
+ }
4446
+
4312
4447
  function assistantSpawnTags(env = process.env) {
4313
4448
  if (env.HAPPY_SPAWNED_BY !== "assistant") return void 0;
4314
4449
  if (env.HAPPY_SESSION_VARIANT === "assistant") return void 0;
@@ -6778,7 +6913,7 @@ function parseJsonObject(text) {
6778
6913
  return null;
6779
6914
  }
6780
6915
  }
6781
- 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-CX_3uUem.cjs', document.baseURI).href))).resolve(s)) {
6916
+ 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-BLW-smJu.cjs', document.baseURI).href))).resolve(s)) {
6782
6917
  const platformArch = `${platform}-${arch}`;
6783
6918
  const candidates = [
6784
6919
  `@anthropic-ai/claude-agent-sdk-${platformArch}/claude`,
@@ -7858,6 +7993,12 @@ async function claimSessionOrExit(happySessionId, options) {
7858
7993
  }
7859
7994
 
7860
7995
  const UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
7996
+ function sanitizeImportTitle(value) {
7997
+ if (typeof value !== "string") return null;
7998
+ const collapsed = value.replace(/[\u0000-\u001f\u007f]/g, " ").replace(/\s+/g, " ").trim();
7999
+ if (collapsed.length === 0) return null;
8000
+ return collapsed.length > 200 ? `${collapsed.slice(0, 199)}\u2026` : collapsed;
8001
+ }
7861
8002
  const hostSuffix = process.env.HAPPY_VARIANT === "dev" ? "-dev" : "";
7862
8003
  const initialMachineMetadata = {
7863
8004
  host: os$1.hostname() + hostSuffix,
@@ -8196,6 +8337,10 @@ async function startDaemon() {
8196
8337
  if (options.importedFromClaudeSessionId && UUID_RE.test(options.importedFromClaudeSessionId)) {
8197
8338
  extraEnv.HAPPY_IMPORTED_FROM_CLAUDE_SESSION_ID = options.importedFromClaudeSessionId;
8198
8339
  }
8340
+ const importTitle = sanitizeImportTitle(options.importTitle);
8341
+ if (importTitle) {
8342
+ extraEnv.HAPPY_IMPORT_TITLE = importTitle;
8343
+ }
8199
8344
  if (options.resumeCodexThreadId) {
8200
8345
  extraEnv.HAPPY_FORK_CODEX_THREAD_ID = options.resumeCodexThreadId;
8201
8346
  }
@@ -10057,7 +10202,7 @@ function registerSideQuestionHandler(rpc, deps) {
10057
10202
  const retainMs = deps.retainMs ?? SIDE_QUESTION_RETAIN_MS;
10058
10203
  const maxRunMs = deps.maxRunMs ?? SIDE_QUESTION_MAX_RUN_MS;
10059
10204
  const run = deps.run ?? (async (input) => {
10060
- const { query } = await Promise.resolve().then(function () { return require('./index-De6H3U0N.cjs'); });
10205
+ const { query } = await Promise.resolve().then(function () { return require('./index-D48mWUTN.cjs'); });
10061
10206
  return runSideQuestion(query, input);
10062
10207
  });
10063
10208
  const slots = /* @__PURE__ */ new Map();
@@ -10159,7 +10304,7 @@ const MAX_TITLE_CHARS = 60;
10159
10304
  const GENERATION_TIMEOUT_MS = 3e4;
10160
10305
  function resolveClaudeBinary() {
10161
10306
  try {
10162
- 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-CX_3uUem.cjs', document.baseURI).href)));
10307
+ 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-BLW-smJu.cjs', document.baseURI).href)));
10163
10308
  const utilsPath = path.resolve(path.join(persistence.projectPath(), "scripts", "claude_version_utils.cjs"));
10164
10309
  const { getClaudeCliPath } = require$1(utilsPath);
10165
10310
  const path$1 = getClaudeCliPath();
@@ -10596,6 +10741,7 @@ async function runClaude(credentials, options = {}) {
10596
10741
  const forkedFromSessionId = process.env.HAPPY_FORKED_FROM_SESSION_ID;
10597
10742
  const forkedFromMessageId = process.env.HAPPY_FORKED_FROM_MESSAGE_ID;
10598
10743
  const importedFromClaudeSessionId = process.env.HAPPY_IMPORTED_FROM_CLAUDE_SESSION_ID;
10744
+ const importTitle = process.env.HAPPY_IMPORT_TITLE;
10599
10745
  let metadata = {
10600
10746
  path: workingDirectory,
10601
10747
  host: os.hostname(),
@@ -10626,6 +10772,7 @@ async function runClaude(credentials, options = {}) {
10626
10772
  ...forkedFromSessionId ? { parentSessionId: forkedFromSessionId } : {},
10627
10773
  ...forkedFromMessageId ? { forkedFromMessageId } : {},
10628
10774
  ...importedFromClaudeSessionId ? { importedFromClaudeSessionId } : {},
10775
+ ...importTitle ? { summary: { text: importTitle, updatedAt: Date.now() } } : {},
10629
10776
  ...isAssistantVariant ? { variant: "assistant" } : {},
10630
10777
  // B-091: sessions the assistant dispatched (daemon spawn RPC exports
10631
10778
  // HAPPY_SPAWNED_BY, B-069) are born with the 'assistant' tag so every
@@ -10856,16 +11003,7 @@ async function runClaude(credentials, options = {}) {
10856
11003
  ...currentState,
10857
11004
  controlledByUser: options.startingMode !== "remote"
10858
11005
  }));
10859
- const messageQueue = new MessageQueue2((mode) => hashObject({
10860
- isPlan: mode.permissionMode === "plan",
10861
- model: mode.model,
10862
- fallbackModel: mode.fallbackModel,
10863
- customSystemPrompt: mode.customSystemPrompt,
10864
- appendSystemPrompt: mode.appendSystemPrompt,
10865
- allowedTools: mode.allowedTools,
10866
- disallowedTools: mode.disallowedTools,
10867
- effort: mode.effort
10868
- }));
11006
+ const messageQueue = new MessageQueue2(claudeModeHash);
10869
11007
  session.rpcHandlerManager.registerHandler("cancelQueuedMessage", async (params) => ({
10870
11008
  removed: messageQueue.cancelPending(
10871
11009
  typeof params?.localKey === "string" ? params.localKey : void 0,
@@ -12366,9 +12504,9 @@ function resolveLocalSignupBootstrap(configuredMode, configuredInviteCodes, gene
12366
12504
  };
12367
12505
  }
12368
12506
 
12369
- 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-CX_3uUem.cjs', document.baseURI).href)));
12507
+ 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-BLW-smJu.cjs', document.baseURI).href)));
12370
12508
  const __dirname$1 = path.dirname(__filename$1);
12371
- const require_ = node_module.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index-CX_3uUem.cjs', document.baseURI).href)));
12509
+ const require_ = node_module.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index-BLW-smJu.cjs', document.baseURI).href)));
12372
12510
  const PRISMA_QUERY_ENGINE_FILES = {
12373
12511
  "arm64-darwin": "libquery_engine-darwin-arm64.dylib.node",
12374
12512
  "x64-darwin": "libquery_engine-darwin.dylib.node",
@@ -14992,7 +15130,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
14992
15130
  process.exit(0);
14993
15131
  } else if (subcommand === "install-terminal-hooks") {
14994
15132
  try {
14995
- const { installTerminalHooks, parseTerminalHooksArgs, TERMINAL_HOOKS_HELP } = await Promise.resolve().then(function () { return require('./installTerminalHooks-BXMBwrvq.cjs'); });
15133
+ const { installTerminalHooks, parseTerminalHooksArgs, TERMINAL_HOOKS_HELP } = await Promise.resolve().then(function () { return require('./installTerminalHooks-9rn15uP8.cjs'); });
14996
15134
  const command = parseTerminalHooksArgs(args.slice(1));
14997
15135
  if (command.action === "help") {
14998
15136
  console.log(TERMINAL_HOOKS_HELP);
@@ -15009,7 +15147,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
15009
15147
  }
15010
15148
  } else if (subcommand === "spawn") {
15011
15149
  try {
15012
- const { handleSpawnCommand } = await Promise.resolve().then(function () { return require('./spawn-BSdMkMPX.cjs'); });
15150
+ const { handleSpawnCommand } = await Promise.resolve().then(function () { return require('./spawn-ChmlP1Z_.cjs'); });
15013
15151
  await handleSpawnCommand(args.slice(1));
15014
15152
  } catch (error) {
15015
15153
  console.error(chalk.red("Error:"), error instanceof Error ? error.message : "Unknown error");
@@ -15021,7 +15159,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
15021
15159
  return;
15022
15160
  } else if (subcommand === "send") {
15023
15161
  try {
15024
- const { handleSendCommand } = await Promise.resolve().then(function () { return require('./send-Bog0YPxo.cjs'); });
15162
+ const { handleSendCommand } = await Promise.resolve().then(function () { return require('./send-B8YQyV3D.cjs'); });
15025
15163
  await handleSendCommand(args.slice(1));
15026
15164
  } catch (error) {
15027
15165
  console.error(chalk.red("Error:"), error instanceof Error ? error.message : "Unknown error");
@@ -15127,9 +15265,9 @@ Conversation history is preserved on the server, but in-flight tool calls are in
15127
15265
  if (geminiSubcommand === "project" && args[2] === "set" && args[3]) {
15128
15266
  const projectId = args[3];
15129
15267
  try {
15130
- const { saveGoogleCloudProjectToConfig } = await Promise.resolve().then(function () { return require('./config-CqM5UxVd.cjs'); });
15131
- const { readCredentialsForConfiguredRelay: readCredentialsForConfiguredRelay2 } = await Promise.resolve().then(function () { return require('./types-14LATr9X.cjs'); }).then(function (n) { return n.persistence; });
15132
- const { ApiClient: ApiClient2 } = await Promise.resolve().then(function () { return require('./types-14LATr9X.cjs'); }).then(function (n) { return n.api; });
15268
+ const { saveGoogleCloudProjectToConfig } = await Promise.resolve().then(function () { return require('./config-Dkn5KcXp.cjs'); });
15269
+ const { readCredentialsForConfiguredRelay: readCredentialsForConfiguredRelay2 } = await Promise.resolve().then(function () { return require('./types-C8-WODFE.cjs'); }).then(function (n) { return n.persistence; });
15270
+ const { ApiClient: ApiClient2 } = await Promise.resolve().then(function () { return require('./types-C8-WODFE.cjs'); }).then(function (n) { return n.api; });
15133
15271
  let userEmail = void 0;
15134
15272
  try {
15135
15273
  const credentials = await readCredentialsForConfiguredRelay2();
@@ -15160,7 +15298,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
15160
15298
  }
15161
15299
  if (geminiSubcommand === "project" && args[2] === "get") {
15162
15300
  try {
15163
- const { readGeminiLocalConfig } = await Promise.resolve().then(function () { return require('./config-CqM5UxVd.cjs'); });
15301
+ const { readGeminiLocalConfig } = await Promise.resolve().then(function () { return require('./config-Dkn5KcXp.cjs'); });
15164
15302
  const config = readGeminiLocalConfig();
15165
15303
  if (config.googleCloudProject) {
15166
15304
  console.log(`Current Google Cloud Project: ${config.googleCloudProject}`);
@@ -15200,7 +15338,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
15200
15338
  process.exit(0);
15201
15339
  }
15202
15340
  try {
15203
- const { runGemini } = await Promise.resolve().then(function () { return require('./runGemini-DFvjh8cO.cjs'); });
15341
+ const { runGemini } = await Promise.resolve().then(function () { return require('./runGemini-q20IdxQV.cjs'); });
15204
15342
  let startedBy = void 0;
15205
15343
  for (let i = 1; i < args.length; i++) {
15206
15344
  if (args[i] === "--started-by") {
@@ -15222,7 +15360,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
15222
15360
  return;
15223
15361
  } else if (subcommand === "acp") {
15224
15362
  try {
15225
- const { runAcp, resolveAcpAgentConfig } = await Promise.resolve().then(function () { return require('./index-fuavV8uc.cjs'); });
15363
+ const { runAcp, resolveAcpAgentConfig } = await Promise.resolve().then(function () { return require('./index-Do3JnAi7.cjs'); });
15226
15364
  let startedBy = void 0;
15227
15365
  let verbose = false;
15228
15366
  const acpArgs = [];
@@ -15262,7 +15400,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
15262
15400
  return;
15263
15401
  } else if (subcommand === "openclaw") {
15264
15402
  try {
15265
- const { runOpenClaw } = await Promise.resolve().then(function () { return require('./runOpenClaw-B5Og1FED.cjs'); });
15403
+ const { runOpenClaw } = await Promise.resolve().then(function () { return require('./runOpenClaw-CtWkyvDJ.cjs'); });
15266
15404
  let startedBy = void 0;
15267
15405
  let verbose = false;
15268
15406
  let gatewayUrl;
@@ -15313,7 +15451,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
15313
15451
  return;
15314
15452
  } else if (subcommand === "mcp" && args.length === 1) {
15315
15453
  try {
15316
- const { handleMcpCommand } = await Promise.resolve().then(function () { return require('./mcp-Cq3On_Qo.cjs'); });
15454
+ const { handleMcpCommand } = await Promise.resolve().then(function () { return require('./mcp-C3zpbx-m.cjs'); });
15317
15455
  await handleMcpCommand();
15318
15456
  } catch (error) {
15319
15457
  process.stderr.write(`[very-happy mcp] Fatal: ${error instanceof Error ? error.message : String(error)}