very-happy-cli 0.2.103 → 0.2.105

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-Zt10QM8S.cjs → AcpBackend-CbMPn2Sx.cjs} +1 -1
  2. package/dist/{AcpBackend-C8CgzRI_.mjs → AcpBackend-zefm5lwc.mjs} +1 -1
  3. package/dist/{AcpSessionManager-BAinHcHh.mjs → AcpSessionManager-DFeZAfz4.mjs} +1 -1
  4. package/dist/{AcpSessionManager-D_iGrEbD.cjs → AcpSessionManager-lM9HBlOx.cjs} +1 -1
  5. package/dist/{config-11py0X-q.mjs → config-CRCUgh2E.mjs} +2 -2
  6. package/dist/{config-CG4aqDiu.cjs → config-CYpWD6Tc.cjs} +2 -2
  7. package/dist/{index-VvPyRTet.cjs → index-Bmv3lZU7.cjs} +2 -2
  8. package/dist/{index-CimI2p1M.cjs → index-Cietz-nU.cjs} +197 -71
  9. package/dist/{index-Dnma0J5k.mjs → index-NiUS5t0N.mjs} +193 -67
  10. package/dist/{index-BjDfS9DT.mjs → index-_t9O9dGp.mjs} +5 -5
  11. package/dist/{index-B_soRPsA.cjs → index-m9BL5ZWn.cjs} +4 -4
  12. package/dist/{index-B9SnF1mG.mjs → index-neppKLsI.mjs} +2 -2
  13. package/dist/index.cjs +2 -2
  14. package/dist/index.mjs +2 -2
  15. package/dist/{installTerminalHooks-BP9uu1Xn.cjs → installTerminalHooks-BMDcB8nc.cjs} +2 -2
  16. package/dist/{installTerminalHooks-UL5Zfif6.mjs → installTerminalHooks-Czv6GUOw.mjs} +2 -2
  17. package/dist/lib.cjs +1 -1
  18. package/dist/lib.d.cts +1 -0
  19. package/dist/lib.d.mts +1 -0
  20. package/dist/lib.mjs +1 -1
  21. package/dist/{mcp-CxepBrGm.mjs → mcp-Bt4btDMD.mjs} +2 -2
  22. package/dist/{mcp-mX6g7PpH.cjs → mcp-Cn4icOYK.cjs} +2 -2
  23. package/dist/{runGemini-BPAUC7TY.cjs → runGemini-5Rgckz_I.cjs} +4 -4
  24. package/dist/{runGemini-Cxa0Tj_7.mjs → runGemini-wMF-U7zR.mjs} +4 -4
  25. package/dist/{runOpenClaw-QJ8YzPvo.cjs → runOpenClaw-DnbKLi5s.cjs} +3 -3
  26. package/dist/{runOpenClaw-DMAn3-Hq.mjs → runOpenClaw-Za9vMsSB.mjs} +3 -3
  27. package/dist/{send-D6NLQaYt.mjs → send-DliNFuy7.mjs} +2 -2
  28. package/dist/{send-CwRV7cbV.cjs → send-v6085rvq.cjs} +2 -2
  29. package/dist/{spawn-DIW1I72G.mjs → spawn-D3D-H-VF.mjs} +2 -2
  30. package/dist/{spawn-Db22DkVT.cjs → spawn-DUU9rhJa.cjs} +2 -2
  31. package/dist/{types-D9ORBxOD.mjs → types-CFIlcwe9.mjs} +38 -8
  32. package/dist/{types-DKO60j29.cjs → types-Cq7yzNWv.cjs} +39 -9
  33. package/package.json +7 -7
@@ -1,7 +1,7 @@
1
1
  import{createRequire as _pkgrollCR}from"node:module";const require=_pkgrollCR(import.meta.url);import chalk from 'chalk';
2
2
  import os, { homedir, userInfo } from 'node:os';
3
3
  import { randomUUID, randomBytes, createHash as createHash$1, timingSafeEqual } from 'node:crypto';
4
- import { n as readDaemonState, l as logger, c as configuration, o as clearDaemonState, q as getProjectPath, p as projectPath, s as initializeSandbox, t as wrapCommand, d as contentLogMetadata, I as InvalidateSync, R as RawJSONLinesSchema, g as delay, u as AsyncLock, v as ensurePrivateDirectory, M as MAX_CHAT_ATTACHMENT_SOURCE_BYTES, x as hardenPrivateFile, f as packageJson, i as readSettings, y as readCredentials, z as credentialRelayProblem, B as deriveLocalCliUpdateSummary, j as encodeBase64, C as updateSettings, D as encodeBase64Url, E as decodeBase64, F as writeCredentialsLegacy, G as writeCredentialsDataKey, H as readCredentialsForConfiguredRelay, J as encrypt, r as readPersistedSessions, K as isClaudeSessionId, L as getLocalHappyAgentCredentialPath, N as readLocalHappyAgentCredentials, O as decryptWithDataKey, P as decryptLegacy, Q as extractCompleteLines, S as decideBackfill, T as parseTerminalHookPayload, U as tmuxArgs, V as scrubTmuxClientEnv, W as decideMirrorBinding, X as MIRROR_BACKFILL_LINES_DEFAULT, Y as persistSession, Z as mirrorLineKey, _ as mirrorLocalId, w as writePrivateFileSync, $ as detectResumeSupport, a0 as detectCLIAvailability, a1 as acquireDaemonLock, a2 as summarizeSpawnSessionForLog, a3 as deletePersistedSessions, a4 as shellescape, a5 as decrypt, a6 as writeDaemonState, A as ApiClient, a7 as writeSettings, a8 as fetchCliUpdateState, a9 as resolveCliUpdateCheckInterval, aa as DEFAULT_CLI_UPDATE_CHECK_INTERVAL_MS, ab as releaseDaemonLock, ac as isValidSessionId, ad as listVhTerminals, ae as isValidTerminalId, af as readVhTerminal, ag as sendToVhTerminal, ah as TITLE_PROMPT_PREFIX, ai as BOARD_ANALYZER_PROMPT_PREFIX, h as connectionState, aj as startOfflineReconnection, ak as clearCredentials, al as clearMachineId, k as ensurePrivateDirectorySync, am as SandboxConfigSchema, b as createEnvelope, an as CodexAppServerClient, ao as getLatestDaemonLog } from './types-D9ORBxOD.mjs';
4
+ import { n as readDaemonState, l as logger, c as configuration, o as clearDaemonState, q as getProjectPath, p as projectPath, s as initializeSandbox, t as wrapCommand, d as contentLogMetadata, I as InvalidateSync, R as RawJSONLinesSchema, g as delay, u as AsyncLock, v as ensurePrivateDirectory, M as MAX_CHAT_ATTACHMENT_SOURCE_BYTES, x as hardenPrivateFile, f as packageJson, i as readSettings, y as readCredentials, z as credentialRelayProblem, B as deriveLocalCliUpdateSummary, j as encodeBase64, C as updateSettings, D as encodeBase64Url, E as decodeBase64, F as writeCredentialsLegacy, G as writeCredentialsDataKey, H as readCredentialsForConfiguredRelay, J as encrypt, r as readPersistedSessions, K as isClaudeSessionId, L as getLocalHappyAgentCredentialPath, N as readLocalHappyAgentCredentials, O as decryptWithDataKey, P as decryptLegacy, Q as extractCompleteLines, S as decideBackfill, T as parseTerminalHookPayload, U as tmuxArgs, V as scrubTmuxClientEnv, W as decideMirrorBinding, X as MIRROR_BACKFILL_LINES_DEFAULT, Y as persistSession, Z as mirrorLineKey, _ as mirrorLocalId, w as writePrivateFileSync, $ as detectResumeSupport, a0 as detectCLIAvailability, a1 as acquireDaemonLock, a2 as summarizeSpawnSessionForLog, a3 as deletePersistedSessions, a4 as shellescape, a5 as decrypt, a6 as writeDaemonState, A as ApiClient, a7 as writeSettings, a8 as fetchCliUpdateState, a9 as resolveCliUpdateCheckInterval, aa as DEFAULT_CLI_UPDATE_CHECK_INTERVAL_MS, ab as releaseDaemonLock, ac as isValidSessionId, ad as listVhTerminals, ae as isValidTerminalId, af as readVhTerminal, ag as sendToVhTerminal, ah as TITLE_PROMPT_PREFIX, ai as BOARD_ANALYZER_PROMPT_PREFIX, h as connectionState, aj as startOfflineReconnection, ak as clearCredentials, al as clearMachineId, k as ensurePrivateDirectorySync, am as SandboxConfigSchema, b as createEnvelope, an as CodexAppServerClient, ao as getLatestDaemonLog } from './types-CFIlcwe9.mjs';
5
5
  import spawn$1, { spawn } from 'cross-spawn';
6
6
  import path, { join, resolve, basename, delimiter, isAbsolute, normalize, sep, dirname } from 'node:path';
7
7
  import { createInterface } from 'node:readline';
@@ -1907,6 +1907,18 @@ async function awaitFileExist(file, timeout = 1e4) {
1907
1907
  return false;
1908
1908
  }
1909
1909
 
1910
+ function modelTarget(model) {
1911
+ return model == null || model === "" ? void 0 : model;
1912
+ }
1913
+ function needsModelSwitch(current, next) {
1914
+ return modelTarget(current) !== modelTarget(next);
1915
+ }
1916
+ function modelSwitchFailureNotice(model, error) {
1917
+ const name = modelTarget(model) ?? "default";
1918
+ const detail = error instanceof Error ? error.message : String(error);
1919
+ return `\u26A0\uFE0F Could not switch to model "${name}" \u2014 continuing with the previous model. ${detail}`;
1920
+ }
1921
+
1910
1922
  async function claudeRemote(opts) {
1911
1923
  let startFrom = opts.sessionId;
1912
1924
  if (opts.sessionId && !claudeCheckSession(opts.sessionId, opts.path)) {
@@ -2013,11 +2025,12 @@ async function claudeRemote(opts) {
2013
2025
  if (opts.onQueryReady) {
2014
2026
  opts.onQueryReady({
2015
2027
  setPermissionMode: (mode2) => response.setPermissionMode(mode2),
2028
+ setModel: (model) => response.setModel(modelTarget(model)),
2016
2029
  interrupt: async () => {
2017
2030
  await response.interrupt();
2018
2031
  },
2019
2032
  steer: (message, nextMode) => {
2020
- mode = nextMode;
2033
+ mode = { ...nextMode, model: mode.model };
2021
2034
  messages.push({
2022
2035
  type: "user",
2023
2036
  parent_tool_use_id: null,
@@ -2049,7 +2062,10 @@ async function claudeRemote(opts) {
2049
2062
  mcpServers: systemInit.mcp_servers?.map((s) => ({ name: s.name, status: s.status })),
2050
2063
  skills: systemInit.skills,
2051
2064
  model: systemInit.model,
2052
- modelIsDefault: initial.mode.model == null,
2065
+ // `mode`, not `initial.mode`: the model can move mid-Query
2066
+ // via setModel, and init is re-emitted every turn with the
2067
+ // model actually in force.
2068
+ modelIsDefault: modelTarget(mode.model) === void 0,
2053
2069
  // The SDK's own verdict on the mode it will enforce —
2054
2070
  // settings (permissions.deny/ask/defaultMode/
2055
2071
  // disableBypassPermissionsMode) can override what we
@@ -2094,19 +2110,29 @@ async function claudeRemote(opts) {
2094
2110
  messages.end();
2095
2111
  continue;
2096
2112
  }
2097
- opts.nextMessage().then((next) => {
2113
+ opts.nextMessage().then(async (next) => {
2098
2114
  if (!next) {
2099
2115
  messages.end();
2100
- } else {
2101
- mode = next.mode;
2102
- updateThinking(true);
2103
- messages.push({
2104
- type: "user",
2105
- parent_tool_use_id: null,
2106
- origin: { kind: "human" },
2107
- message: { role: "user", content: next.message }
2108
- });
2116
+ return;
2117
+ }
2118
+ if (needsModelSwitch(mode.model, next.mode.model)) {
2119
+ try {
2120
+ await response.setModel(modelTarget(next.mode.model));
2121
+ logger.debug(`[claudeRemote] Model switched to ${modelTarget(next.mode.model) ?? "default"}`);
2122
+ } catch (e) {
2123
+ logger.debug(`[claudeRemote] setModel failed: ${e instanceof Error ? e.message : String(e)}`);
2124
+ opts.onCompletionEvent?.(modelSwitchFailureNotice(next.mode.model, e));
2125
+ next = { ...next, mode: { ...next.mode, model: mode.model } };
2126
+ }
2109
2127
  }
2128
+ mode = next.mode;
2129
+ updateThinking(true);
2130
+ messages.push({
2131
+ type: "user",
2132
+ parent_tool_use_id: null,
2133
+ origin: { kind: "human" },
2134
+ message: { role: "user", content: next.message }
2135
+ });
2110
2136
  }).catch(() => {
2111
2137
  messages.end();
2112
2138
  });
@@ -3387,6 +3413,12 @@ function applyClaudeSdkMetadata(current, update) {
3387
3413
  skills: update.skills,
3388
3414
  attachmentKinds: [...CLAUDE_ATTACHMENT_KINDS],
3389
3415
  queueCancellation: true,
3416
+ // The model Claude Code reports it is ACTUALLY running. system/init is
3417
+ // re-emitted at every turn boundary (verified against the pinned SDK,
3418
+ // 2026-09-03), including after a live setModel, so this is the web's
3419
+ // only ground truth for "did my switch take effect" — the picker
3420
+ // otherwise renders nothing but the client's own optimistic intent.
3421
+ ...update.model ? { currentModelCode: update.model } : {},
3390
3422
  ...update.modelIsDefault && update.model ? { defaultModelCode: update.model } : {}
3391
3423
  };
3392
3424
  }
@@ -3421,6 +3453,102 @@ function createTurnSteeringController() {
3421
3453
  };
3422
3454
  }
3423
3455
 
3456
+ class LaunchModeGate {
3457
+ constructor(hasher) {
3458
+ this.hasher = hasher;
3459
+ }
3460
+ currentMode = null;
3461
+ currentHash = null;
3462
+ parked = null;
3463
+ /** The mode this launch is running, or null before the first message. */
3464
+ get mode() {
3465
+ return this.currentMode;
3466
+ }
3467
+ /** Hash of {@link mode}; null means "not armed yet — accept anything". */
3468
+ get hash() {
3469
+ return this.currentHash;
3470
+ }
3471
+ /** Whether a message has been adopted into this launch yet. */
3472
+ get armed() {
3473
+ return this.currentHash !== null;
3474
+ }
3475
+ /** Bind the launch to `mode`. Idempotent; safe to call with the same mode. */
3476
+ adopt(mode) {
3477
+ this.currentMode = mode;
3478
+ this.currentHash = this.hasher(mode);
3479
+ }
3480
+ /**
3481
+ * Re-adopt the current mode with one field replaced. No-op before the first
3482
+ * adopt: there is nothing to derive from, and arming here would make the
3483
+ * first real message look like a mode change.
3484
+ */
3485
+ amend(patch) {
3486
+ if (this.currentMode === null) return null;
3487
+ this.adopt({ ...this.currentMode, ...patch });
3488
+ return this.currentMode;
3489
+ }
3490
+ /**
3491
+ * True when `incomingHash` cannot run on this launch's Query and must be
3492
+ * parked for a fresh one. An un-armed gate accepts anything — that is how a
3493
+ * new launch takes its first message, including a replayed parked one.
3494
+ */
3495
+ requiresRelaunch(incomingHash, isolate) {
3496
+ if (isolate) return true;
3497
+ return this.armed && incomingHash !== this.currentHash;
3498
+ }
3499
+ /** True when `mode` is exactly what this launch adopted (Steer's precondition). */
3500
+ matches(mode) {
3501
+ return this.armed && this.hasher(mode) === this.currentHash;
3502
+ }
3503
+ /**
3504
+ * Hold a message that cannot run on this launch until its successor picks
3505
+ * it up. Survives {@link reset} — the parked message is precisely what the
3506
+ * next launch exists to run.
3507
+ */
3508
+ park(message) {
3509
+ this.parked = message;
3510
+ }
3511
+ /** Whether a parked message is waiting for the next launch. */
3512
+ get hasParked() {
3513
+ return this.parked !== null;
3514
+ }
3515
+ /**
3516
+ * Take the parked message AND adopt its mode in one step.
3517
+ *
3518
+ * This pairing is the whole point of the class. When parking and adopting
3519
+ * were separate — a `pending` variable in the launcher next to a `modeHash`
3520
+ * one — the replay path took the message and forgot to adopt, so the gate
3521
+ * stayed un-armed and swallowed the NEXT mode change into a Query built for
3522
+ * the previous one. Nothing structural tied the two, and no unit test could
3523
+ * reach the wiring. Here they cannot come apart.
3524
+ */
3525
+ takeParked() {
3526
+ const message = this.parked;
3527
+ if (!message) return null;
3528
+ this.parked = null;
3529
+ this.adopt(message.mode);
3530
+ return message;
3531
+ }
3532
+ /**
3533
+ * Re-adopt the parked message with a patched mode. Used when an explicit
3534
+ * mode switch lands while a message is parked: the switch is newer than the
3535
+ * snapshot the message carried when it was queued.
3536
+ */
3537
+ amendParked(patch) {
3538
+ if (!this.parked) return;
3539
+ this.parked = { ...this.parked, mode: { ...this.parked.mode, ...patch } };
3540
+ }
3541
+ /**
3542
+ * Drop back to un-armed. Called when a launch ends. Deliberately does NOT
3543
+ * clear a parked message: parking happens in the launch that is ending, and
3544
+ * the message belongs to the one about to start.
3545
+ */
3546
+ reset() {
3547
+ this.currentMode = null;
3548
+ this.currentHash = null;
3549
+ }
3550
+ }
3551
+
3424
3552
  async function claudeRemoteLauncher(session, onPermissionModeChange, onEffectivePermissionMode) {
3425
3553
  logger.debug("[claudeRemoteLauncher] Starting remote launcher");
3426
3554
  const hasTTY = process.stdout.isTTY && process.stdin.isTTY;
@@ -3628,7 +3756,7 @@ async function claudeRemoteLauncher(session, onPermissionModeChange, onEffective
3628
3756
  }
3629
3757
  }
3630
3758
  try {
3631
- let pending = null;
3759
+ const modeGate = new LaunchModeGate(session.queue.modeHasher);
3632
3760
  let previousSessionId = null;
3633
3761
  while (!exitReason) {
3634
3762
  logger.debug("[remote]: launch");
@@ -3647,18 +3775,11 @@ async function claudeRemoteLauncher(session, onPermissionModeChange, onEffective
3647
3775
  const controller = new AbortController();
3648
3776
  abortController = controller;
3649
3777
  abortFuture = new Future();
3650
- let modeHash = null;
3651
- let mode = null;
3652
3778
  const commitPermissionMode = (nextMode) => {
3653
3779
  permissionHandler.handleModeChange(nextMode);
3654
- if (mode) {
3655
- mode = { ...mode, permissionMode: nextMode };
3656
- modeHash = session.queue.modeHasher(mode);
3657
- }
3780
+ modeGate.amend({ permissionMode: nextMode });
3658
3781
  rewriteQueuedPermissionMode(session.queue.queue, session.queue.modeHasher, nextMode);
3659
- if (pending) {
3660
- pending = { ...pending, mode: { ...pending.mode, permissionMode: nextMode } };
3661
- }
3782
+ modeGate.amendParked({ permissionMode: nextMode });
3662
3783
  onPermissionModeChange?.(nextMode);
3663
3784
  return nextMode;
3664
3785
  };
@@ -3684,22 +3805,28 @@ async function claudeRemoteLauncher(session, onPermissionModeChange, onEffective
3684
3805
  return permissionHandler.isAborted(toolCallId);
3685
3806
  },
3686
3807
  nextMessage: async () => {
3687
- if (pending) {
3688
- let p = pending;
3689
- pending = null;
3690
- permissionHandler.handleModeChange(p.mode.permissionMode);
3691
- return p;
3808
+ const parked = modeGate.takeParked();
3809
+ if (parked) {
3810
+ permissionHandler.handleModeChange(parked.mode.permissionMode);
3811
+ return parked;
3692
3812
  }
3693
3813
  let msg = await session.queue.waitForMessagesAndGetAsString(controller.signal);
3694
3814
  if (msg) {
3695
- if (modeHash && msg.hash !== modeHash || msg.isolate) {
3815
+ if (modeGate.requiresRelaunch(msg.hash, msg.isolate)) {
3696
3816
  logger.debug("[remote]: mode has changed, pending message");
3697
- pending = msg;
3817
+ const parkedAttachments = msg.attachments ?? [];
3818
+ const parkedStaged = parkedAttachments.length > 0 ? await stageClaudeAttachments(parkedAttachments, {
3819
+ happyHomeDir: configuration.happyHomeDir,
3820
+ sessionId: session.client.sessionId
3821
+ }) : [];
3822
+ modeGate.park({
3823
+ message: parkedStaged.length > 0 ? appendStagedAttachmentsToPrompt(msg.message, parkedStaged) : msg.message,
3824
+ mode: msg.mode
3825
+ });
3698
3826
  return null;
3699
3827
  }
3700
- modeHash = msg.hash;
3701
- mode = msg.mode;
3702
- permissionHandler.handleModeChange(mode.permissionMode);
3828
+ modeGate.adopt(msg.mode);
3829
+ permissionHandler.handleModeChange(msg.mode.permissionMode);
3703
3830
  const attachments = msg.attachments ?? [];
3704
3831
  if (attachments.length > 0) {
3705
3832
  const staged = await stageClaudeAttachments(attachments, {
@@ -3736,8 +3863,7 @@ async function claudeRemoteLauncher(session, onPermissionModeChange, onEffective
3736
3863
  onQueryReady: (q) => {
3737
3864
  turnSteering.setInterrupt(q.interrupt);
3738
3865
  session.setSteerHandler(async (input) => {
3739
- const expectedHash = session.queue.modeHasher(input.mode);
3740
- if (!modeHash || expectedHash !== modeHash) return false;
3866
+ if (!modeGate.matches(input.mode)) return false;
3741
3867
  let message = input.message;
3742
3868
  if (input.attachments?.length) {
3743
3869
  const staged = await stageClaudeAttachments(input.attachments, {
@@ -3746,19 +3872,16 @@ async function claudeRemoteLauncher(session, onPermissionModeChange, onEffective
3746
3872
  });
3747
3873
  message = appendStagedAttachmentsToPrompt(input.message, staged);
3748
3874
  }
3749
- if (!session.thinking || modeHash !== expectedHash) return false;
3875
+ if (!session.thinking || !modeGate.matches(input.mode)) return false;
3750
3876
  q.steer(message, input.mode);
3751
3877
  return true;
3752
3878
  });
3753
- permissionHandler.setPermissionModeUpdater(async (mode2) => {
3754
- await q.setPermissionMode(mode2);
3879
+ permissionHandler.setPermissionModeUpdater(async (mode) => {
3880
+ await q.setPermissionMode(mode);
3755
3881
  });
3756
3882
  livePermissionModeHandler = async (nextMode) => {
3757
3883
  await permissionHandler.setLivePermissionMode(nextMode);
3758
- if (mode) {
3759
- mode = { ...mode, permissionMode: nextMode };
3760
- modeHash = session.queue.modeHasher(mode);
3761
- }
3884
+ modeGate.amend({ permissionMode: nextMode });
3762
3885
  onPermissionModeChange?.(nextMode);
3763
3886
  return nextMode;
3764
3887
  };
@@ -3789,7 +3912,7 @@ async function claudeRemoteLauncher(session, onPermissionModeChange, onEffective
3789
3912
  closeFailed: (error) => session.client.closeClaudeSessionTurn("failed", { error }),
3790
3913
  onFailed: (error) => session.onSessionError(error),
3791
3914
  onCompleted: () => {
3792
- const idle = !pending && session.queue.size() === 0;
3915
+ const idle = !modeGate.hasParked && session.queue.size() === 0;
3793
3916
  session.onTurnEnd(idle);
3794
3917
  if (idle) {
3795
3918
  session.api.push().sendSessionNotification({
@@ -3848,8 +3971,7 @@ async function claudeRemoteLauncher(session, onPermissionModeChange, onEffective
3848
3971
  abortFuture = null;
3849
3972
  logger.debug("[remote]: launch done");
3850
3973
  permissionHandler.reset();
3851
- modeHash = null;
3852
- mode = null;
3974
+ modeGate.reset();
3853
3975
  }
3854
3976
  }
3855
3977
  } finally {
@@ -4146,6 +4268,7 @@ class MessageQueue2 {
4146
4268
  while (this.queue.length > 0 && this.queue[0].modeHash === targetModeHash && !this.queue[0].isolate) {
4147
4269
  const item = this.queue.shift();
4148
4270
  sameModeMessages.push(item.message);
4271
+ mode = item.mode;
4149
4272
  if (item.attachments) collectedAttachments.push(...item.attachments);
4150
4273
  }
4151
4274
  logger.debug(`[MessageQueue2] Collected batch of ${sameModeMessages.length} messages with mode hash: ${targetModeHash}`);
@@ -4287,6 +4410,18 @@ function hashObject(obj, options, encoding = "hex") {
4287
4410
  return createHash("sha256").update(jsonString).digest(encoding);
4288
4411
  }
4289
4412
 
4413
+ function claudeModeHash(mode) {
4414
+ return hashObject({
4415
+ isPlan: mode.permissionMode === "plan",
4416
+ fallbackModel: mode.fallbackModel,
4417
+ customSystemPrompt: mode.customSystemPrompt,
4418
+ appendSystemPrompt: mode.appendSystemPrompt,
4419
+ allowedTools: mode.allowedTools,
4420
+ disallowedTools: mode.disallowedTools,
4421
+ effort: mode.effort
4422
+ });
4423
+ }
4424
+
4290
4425
  function assistantSpawnTags(env = process.env) {
4291
4426
  if (env.HAPPY_SPAWNED_BY !== "assistant") return void 0;
4292
4427
  if (env.HAPPY_SESSION_VARIANT === "assistant") return void 0;
@@ -10035,7 +10170,7 @@ function registerSideQuestionHandler(rpc, deps) {
10035
10170
  const retainMs = deps.retainMs ?? SIDE_QUESTION_RETAIN_MS;
10036
10171
  const maxRunMs = deps.maxRunMs ?? SIDE_QUESTION_MAX_RUN_MS;
10037
10172
  const run = deps.run ?? (async (input) => {
10038
- const { query } = await import('./index-B9SnF1mG.mjs');
10173
+ const { query } = await import('./index-neppKLsI.mjs');
10039
10174
  return runSideQuestion(query, input);
10040
10175
  });
10041
10176
  const slots = /* @__PURE__ */ new Map();
@@ -10834,16 +10969,7 @@ async function runClaude(credentials, options = {}) {
10834
10969
  ...currentState,
10835
10970
  controlledByUser: options.startingMode !== "remote"
10836
10971
  }));
10837
- const messageQueue = new MessageQueue2((mode) => hashObject({
10838
- isPlan: mode.permissionMode === "plan",
10839
- model: mode.model,
10840
- fallbackModel: mode.fallbackModel,
10841
- customSystemPrompt: mode.customSystemPrompt,
10842
- appendSystemPrompt: mode.appendSystemPrompt,
10843
- allowedTools: mode.allowedTools,
10844
- disallowedTools: mode.disallowedTools,
10845
- effort: mode.effort
10846
- }));
10972
+ const messageQueue = new MessageQueue2(claudeModeHash);
10847
10973
  session.rpcHandlerManager.registerHandler("cancelQueuedMessage", async (params) => ({
10848
10974
  removed: messageQueue.cancelPending(
10849
10975
  typeof params?.localKey === "string" ? params.localKey : void 0,
@@ -14970,7 +15096,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
14970
15096
  process.exit(0);
14971
15097
  } else if (subcommand === "install-terminal-hooks") {
14972
15098
  try {
14973
- const { installTerminalHooks, parseTerminalHooksArgs, TERMINAL_HOOKS_HELP } = await import('./installTerminalHooks-UL5Zfif6.mjs');
15099
+ const { installTerminalHooks, parseTerminalHooksArgs, TERMINAL_HOOKS_HELP } = await import('./installTerminalHooks-Czv6GUOw.mjs');
14974
15100
  const command = parseTerminalHooksArgs(args.slice(1));
14975
15101
  if (command.action === "help") {
14976
15102
  console.log(TERMINAL_HOOKS_HELP);
@@ -14987,7 +15113,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
14987
15113
  }
14988
15114
  } else if (subcommand === "spawn") {
14989
15115
  try {
14990
- const { handleSpawnCommand } = await import('./spawn-DIW1I72G.mjs');
15116
+ const { handleSpawnCommand } = await import('./spawn-D3D-H-VF.mjs');
14991
15117
  await handleSpawnCommand(args.slice(1));
14992
15118
  } catch (error) {
14993
15119
  console.error(chalk.red("Error:"), error instanceof Error ? error.message : "Unknown error");
@@ -14999,7 +15125,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
14999
15125
  return;
15000
15126
  } else if (subcommand === "send") {
15001
15127
  try {
15002
- const { handleSendCommand } = await import('./send-D6NLQaYt.mjs');
15128
+ const { handleSendCommand } = await import('./send-DliNFuy7.mjs');
15003
15129
  await handleSendCommand(args.slice(1));
15004
15130
  } catch (error) {
15005
15131
  console.error(chalk.red("Error:"), error instanceof Error ? error.message : "Unknown error");
@@ -15105,9 +15231,9 @@ Conversation history is preserved on the server, but in-flight tool calls are in
15105
15231
  if (geminiSubcommand === "project" && args[2] === "set" && args[3]) {
15106
15232
  const projectId = args[3];
15107
15233
  try {
15108
- const { saveGoogleCloudProjectToConfig } = await import('./config-11py0X-q.mjs');
15109
- const { readCredentialsForConfiguredRelay: readCredentialsForConfiguredRelay2 } = await import('./types-D9ORBxOD.mjs').then(function (n) { return n.ap; });
15110
- const { ApiClient: ApiClient2 } = await import('./types-D9ORBxOD.mjs').then(function (n) { return n.aq; });
15234
+ const { saveGoogleCloudProjectToConfig } = await import('./config-CRCUgh2E.mjs');
15235
+ const { readCredentialsForConfiguredRelay: readCredentialsForConfiguredRelay2 } = await import('./types-CFIlcwe9.mjs').then(function (n) { return n.ap; });
15236
+ const { ApiClient: ApiClient2 } = await import('./types-CFIlcwe9.mjs').then(function (n) { return n.aq; });
15111
15237
  let userEmail = void 0;
15112
15238
  try {
15113
15239
  const credentials = await readCredentialsForConfiguredRelay2();
@@ -15138,7 +15264,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
15138
15264
  }
15139
15265
  if (geminiSubcommand === "project" && args[2] === "get") {
15140
15266
  try {
15141
- const { readGeminiLocalConfig } = await import('./config-11py0X-q.mjs');
15267
+ const { readGeminiLocalConfig } = await import('./config-CRCUgh2E.mjs');
15142
15268
  const config = readGeminiLocalConfig();
15143
15269
  if (config.googleCloudProject) {
15144
15270
  console.log(`Current Google Cloud Project: ${config.googleCloudProject}`);
@@ -15178,7 +15304,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
15178
15304
  process.exit(0);
15179
15305
  }
15180
15306
  try {
15181
- const { runGemini } = await import('./runGemini-Cxa0Tj_7.mjs');
15307
+ const { runGemini } = await import('./runGemini-wMF-U7zR.mjs');
15182
15308
  let startedBy = void 0;
15183
15309
  for (let i = 1; i < args.length; i++) {
15184
15310
  if (args[i] === "--started-by") {
@@ -15200,7 +15326,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
15200
15326
  return;
15201
15327
  } else if (subcommand === "acp") {
15202
15328
  try {
15203
- const { runAcp, resolveAcpAgentConfig } = await import('./index-BjDfS9DT.mjs');
15329
+ const { runAcp, resolveAcpAgentConfig } = await import('./index-_t9O9dGp.mjs');
15204
15330
  let startedBy = void 0;
15205
15331
  let verbose = false;
15206
15332
  const acpArgs = [];
@@ -15240,7 +15366,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
15240
15366
  return;
15241
15367
  } else if (subcommand === "openclaw") {
15242
15368
  try {
15243
- const { runOpenClaw } = await import('./runOpenClaw-DMAn3-Hq.mjs');
15369
+ const { runOpenClaw } = await import('./runOpenClaw-Za9vMsSB.mjs');
15244
15370
  let startedBy = void 0;
15245
15371
  let verbose = false;
15246
15372
  let gatewayUrl;
@@ -15291,7 +15417,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
15291
15417
  return;
15292
15418
  } else if (subcommand === "mcp" && args.length === 1) {
15293
15419
  try {
15294
- const { handleMcpCommand } = await import('./mcp-CxepBrGm.mjs');
15420
+ const { handleMcpCommand } = await import('./mcp-Bt4btDMD.mjs');
15295
15421
  await handleMcpCommand();
15296
15422
  } catch (error) {
15297
15423
  process.stderr.write(`[very-happy mcp] Fatal: ${error instanceof Error ? error.message : String(error)}
@@ -1,10 +1,10 @@
1
- import { D as DefaultTransport, A as AcpBackend } from './AcpBackend-C8CgzRI_.mjs';
2
- export { a as DEFAULT_IDLE_TIMEOUT_MS, b as DEFAULT_TOOL_CALL_TIMEOUT_MS, e as extractErrorDetail, f as formatDuration, c as formatDurationMinutes, h as handleAgentMessageChunk, d as handleAgentThoughtChunk, g as handleLegacyMessageChunk, i as handlePlanUpdate, j as handleThinkingUpdate, k as handleToolCall, l as handleToolCallUpdate, p as parseArgsFromContent } from './AcpBackend-C8CgzRI_.mjs';
3
- import { h as connectionState, A as ApiClient, i as readSettings, j as encodeBase64, l as logger, p as projectPath } from './types-D9ORBxOD.mjs';
4
- import { A as AcpSessionManager } from './AcpSessionManager-BAinHcHh.mjs';
1
+ import { D as DefaultTransport, A as AcpBackend } from './AcpBackend-zefm5lwc.mjs';
2
+ export { a as DEFAULT_IDLE_TIMEOUT_MS, b as DEFAULT_TOOL_CALL_TIMEOUT_MS, e as extractErrorDetail, f as formatDuration, c as formatDurationMinutes, h as handleAgentMessageChunk, d as handleAgentThoughtChunk, g as handleLegacyMessageChunk, i as handlePlanUpdate, j as handleThinkingUpdate, k as handleToolCall, l as handleToolCallUpdate, p as parseArgsFromContent } from './AcpBackend-zefm5lwc.mjs';
3
+ import { h as connectionState, A as ApiClient, i as readSettings, j as encodeBase64, l as logger, p as projectPath } from './types-CFIlcwe9.mjs';
4
+ import { A as AcpSessionManager } from './AcpSessionManager-DFeZAfz4.mjs';
5
5
  import { randomUUID } from 'node:crypto';
6
6
  import { join } from 'node:path';
7
- import { i as initialMachineMetadata, d as createSessionMetadata, e as setupOfflineReconnection, n as notifyDaemonSessionStarted, M as MessageQueue2, h as hashObject, f as startHappyServer, r as registerKillSessionHandler, B as BasePermissionHandler } from './index-Dnma0J5k.mjs';
7
+ import { i as initialMachineMetadata, d as createSessionMetadata, e as setupOfflineReconnection, n as notifyDaemonSessionStarted, M as MessageQueue2, h as hashObject, f as startHappyServer, r as registerKillSessionHandler, B as BasePermissionHandler } from './index-NiUS5t0N.mjs';
8
8
  import 'node:child_process';
9
9
  import '@agentclientprotocol/sdk';
10
10
  import 'axios';
@@ -1,11 +1,11 @@
1
1
  'use strict';
2
2
 
3
- var AcpBackend = require('./AcpBackend-Zt10QM8S.cjs');
4
- var persistence = require('./types-DKO60j29.cjs');
5
- var AcpSessionManager = require('./AcpSessionManager-D_iGrEbD.cjs');
3
+ var AcpBackend = require('./AcpBackend-CbMPn2Sx.cjs');
4
+ var persistence = require('./types-Cq7yzNWv.cjs');
5
+ var AcpSessionManager = require('./AcpSessionManager-lM9HBlOx.cjs');
6
6
  var node_crypto = require('node:crypto');
7
7
  var path = require('node:path');
8
- var index = require('./index-CimI2p1M.cjs');
8
+ var index = require('./index-Cietz-nU.cjs');
9
9
  require('node:child_process');
10
10
  require('@agentclientprotocol/sdk');
11
11
  require('axios');
@@ -1,9 +1,9 @@
1
- import { q as query } from './index-Dnma0J5k.mjs';
1
+ import { q as query } from './index-NiUS5t0N.mjs';
2
2
  export { AbortError } from '@anthropic-ai/claude-agent-sdk';
3
3
  import 'chalk';
4
4
  import 'node:os';
5
5
  import 'node:crypto';
6
- import './types-D9ORBxOD.mjs';
6
+ import './types-CFIlcwe9.mjs';
7
7
  import 'axios';
8
8
  import 'node:util';
9
9
  import 'node:fs';
package/dist/index.cjs CHANGED
@@ -1,8 +1,8 @@
1
1
  'use strict';
2
2
 
3
3
  require('chalk');
4
- require('./index-CimI2p1M.cjs');
5
- require('./types-DKO60j29.cjs');
4
+ require('./index-Cietz-nU.cjs');
5
+ require('./types-Cq7yzNWv.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-Dnma0J5k.mjs';
3
- import './types-D9ORBxOD.mjs';
2
+ import './index-NiUS5t0N.mjs';
3
+ import './types-CFIlcwe9.mjs';
4
4
  import 'zod';
5
5
  import 'node:child_process';
6
6
  import 'node:os';
@@ -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-DKO60j29.cjs');
9
- var index = require('./index-CimI2p1M.cjs');
8
+ var persistence = require('./types-Cq7yzNWv.cjs');
9
+ var index = require('./index-Cietz-nU.cjs');
10
10
  require('axios');
11
11
  require('node:util');
12
12
  require('node:fs/promises');
@@ -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-D9ORBxOD.mjs';
7
- import { t as tmuxSupportsSessionEnv } from './index-Dnma0J5k.mjs';
6
+ import { p as projectPath } from './types-CFIlcwe9.mjs';
7
+ import { t as tmuxSupportsSessionEnv } from './index-NiUS5t0N.mjs';
8
8
  import 'axios';
9
9
  import 'node:util';
10
10
  import 'node:fs/promises';
package/dist/lib.cjs CHANGED
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- var persistence = require('./types-DKO60j29.cjs');
3
+ var persistence = require('./types-Cq7yzNWv.cjs');
4
4
  require('axios');
5
5
  require('chalk');
6
6
  require('node:util');
package/dist/lib.d.cts CHANGED
@@ -444,6 +444,7 @@ declare const UserMessageSchema: z$1.ZodObject<{
444
444
  appendSystemPrompt: z$1.ZodOptional<z$1.ZodNullable<z$1.ZodString>>;
445
445
  allowedTools: z$1.ZodOptional<z$1.ZodNullable<z$1.ZodArray<z$1.ZodString>>>;
446
446
  disallowedTools: z$1.ZodOptional<z$1.ZodNullable<z$1.ZodArray<z$1.ZodString>>>;
447
+ effort: z$1.ZodOptional<z$1.ZodNullable<z$1.ZodString>>;
447
448
  delivery: z$1.ZodOptional<z$1.ZodEnum<{
448
449
  queue: "queue";
449
450
  steer: "steer";
package/dist/lib.d.mts CHANGED
@@ -444,6 +444,7 @@ declare const UserMessageSchema: z$1.ZodObject<{
444
444
  appendSystemPrompt: z$1.ZodOptional<z$1.ZodNullable<z$1.ZodString>>;
445
445
  allowedTools: z$1.ZodOptional<z$1.ZodNullable<z$1.ZodArray<z$1.ZodString>>>;
446
446
  disallowedTools: z$1.ZodOptional<z$1.ZodNullable<z$1.ZodArray<z$1.ZodString>>>;
447
+ effort: z$1.ZodOptional<z$1.ZodNullable<z$1.ZodString>>;
447
448
  delivery: z$1.ZodOptional<z$1.ZodEnum<{
448
449
  queue: "queue";
449
450
  steer: "steer";
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-D9ORBxOD.mjs';
1
+ export { A as ApiClient, a as ApiSessionClient, R as RawJSONLinesSchema, c as configuration, l as logger } from './types-CFIlcwe9.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-Dnma0J5k.mjs';
4
+ import { p as pushClipboardViaDaemon } from './index-NiUS5t0N.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-D9ORBxOD.mjs';
6
+ import { l as logger } from './types-CFIlcwe9.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-CimI2p1M.cjs');
6
+ var index = require('./index-Cietz-nU.cjs');
7
7
  var limits = require('./limits-KdWKmwtH.cjs');
8
- var persistence = require('./types-DKO60j29.cjs');
8
+ var persistence = require('./types-Cq7yzNWv.cjs');
9
9
  require('chalk');
10
10
  require('node:os');
11
11
  require('node:crypto');
@@ -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-DKO60j29.cjs');
8
- var index = require('./index-CimI2p1M.cjs');
9
- var AcpBackend = require('./AcpBackend-Zt10QM8S.cjs');
10
- var config = require('./config-CG4aqDiu.cjs');
7
+ var persistence = require('./types-Cq7yzNWv.cjs');
8
+ var index = require('./index-Cietz-nU.cjs');
9
+ var AcpBackend = require('./AcpBackend-CbMPn2Sx.cjs');
10
+ var config = require('./config-CYpWD6Tc.cjs');
11
11
  require('axios');
12
12
  require('chalk');
13
13
  require('node:util');