very-happy-cli 0.2.84 → 0.2.85

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 (31) hide show
  1. package/dist/{AcpBackend-DxoxNKOM.cjs → AcpBackend-B1l_WyZy.cjs} +1 -1
  2. package/dist/{AcpBackend-BgOEcqMG.mjs → AcpBackend-CDclNgxu.mjs} +1 -1
  3. package/dist/{AcpSessionManager-Ba9ON7eK.mjs → AcpSessionManager-PCdfo4gz.mjs} +1 -1
  4. package/dist/{AcpSessionManager-_bG1kjZz.cjs → AcpSessionManager-dVX0uTo8.cjs} +1 -1
  5. package/dist/{config-Dv2kzos6.cjs → config-Ce5hbWlg.cjs} +2 -2
  6. package/dist/{config-CQjk8rce.mjs → config-DDsvmCxL.mjs} +2 -2
  7. package/dist/{index-Cc2VYKqa.mjs → index-CCQ2mqkA.mjs} +5 -5
  8. package/dist/{index-B8UoTir2.cjs → index-DUcWAKZ0.cjs} +148 -27
  9. package/dist/{index-Cnb_eI7Q.mjs → index-DVKieWPR.mjs} +145 -24
  10. package/dist/{index-CULwez6o.cjs → index-Syfrd3oP.cjs} +4 -4
  11. package/dist/index.cjs +2 -2
  12. package/dist/index.mjs +2 -2
  13. package/dist/{installTerminalHooks-C-8Vuwlu.mjs → installTerminalHooks-BMTBsCfi.mjs} +2 -2
  14. package/dist/{installTerminalHooks-mk1QIEvp.cjs → installTerminalHooks-hcCRjxNy.cjs} +2 -2
  15. package/dist/lib.cjs +1 -1
  16. package/dist/lib.d.cts +6 -0
  17. package/dist/lib.d.mts +6 -0
  18. package/dist/lib.mjs +1 -1
  19. package/dist/{mcp-BZba259A.mjs → mcp-C2bERsV2.mjs} +2 -2
  20. package/dist/{mcp-X7yyQ2d_.cjs → mcp-DGHMyTt-.cjs} +2 -2
  21. package/dist/{runGemini-Nig1hb70.mjs → runGemini-CUpp6u-S.mjs} +4 -4
  22. package/dist/{runGemini-Cf_FQOrg.cjs → runGemini-U5JI6rsK.cjs} +4 -4
  23. package/dist/{runOpenClaw-DllszOSy.mjs → runOpenClaw-BHR7emaO.mjs} +3 -3
  24. package/dist/{runOpenClaw-BlZkYWEQ.cjs → runOpenClaw-DJYiIMrs.cjs} +3 -3
  25. package/dist/{send-C6-E03t-.mjs → send-AIDeVBON.mjs} +2 -2
  26. package/dist/{send-DZIY545W.cjs → send-iDuDd7yC.cjs} +2 -2
  27. package/dist/{spawn-hjPuTkvH.mjs → spawn-DPz_3Q6B.mjs} +2 -2
  28. package/dist/{spawn-Cm52jfN6.cjs → spawn-Kklokpjz.cjs} +2 -2
  29. package/dist/{types-Bv1nc9M1.mjs → types-CkUHjxKz.mjs} +13 -9
  30. package/dist/{types-Dudpkl_i.cjs → types-DJGEti9c.cjs} +14 -10
  31. 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-Dudpkl_i.cjs');
6
+ var persistence = require('./types-DJGEti9c.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-Bv1nc9M1.mjs';
4
+ import { l as logger, d as contentLogMetadata, e as errorLogMetadata, f as packageJson, g as delay } from './types-CkUHjxKz.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-Bv1nc9M1.mjs';
2
+ import { b as createEnvelope } from './types-CkUHjxKz.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-Dudpkl_i.cjs');
4
+ var persistence = require('./types-DJGEti9c.cjs');
5
5
 
6
6
  function turnOptions(turnId, time) {
7
7
  return turnId ? { turn: turnId, time } : { time };
@@ -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-Dudpkl_i.cjs');
8
- var index = require('./index-B8UoTir2.cjs');
7
+ var persistence = require('./types-DJGEti9c.cjs');
8
+ var index = require('./index-DUcWAKZ0.cjs');
9
9
  require('axios');
10
10
  require('chalk');
11
11
  require('node:util');
@@ -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-Bv1nc9M1.mjs';
6
- import { D as DEFAULT_GEMINI_MODEL, G as GEMINI_MODEL_ENV } from './index-Cnb_eI7Q.mjs';
5
+ import { l as logger } from './types-CkUHjxKz.mjs';
6
+ import { D as DEFAULT_GEMINI_MODEL, G as GEMINI_MODEL_ENV } from './index-DVKieWPR.mjs';
7
7
  import 'axios';
8
8
  import 'chalk';
9
9
  import 'node:util';
@@ -1,10 +1,10 @@
1
- import { D as DefaultTransport, A as AcpBackend } from './AcpBackend-BgOEcqMG.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-BgOEcqMG.mjs';
3
- import { h as connectionState, A as ApiClient, i as readSettings, j as encodeBase64, l as logger, p as projectPath } from './types-Bv1nc9M1.mjs';
4
- import { A as AcpSessionManager } from './AcpSessionManager-Ba9ON7eK.mjs';
1
+ import { D as DefaultTransport, A as AcpBackend } from './AcpBackend-CDclNgxu.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-CDclNgxu.mjs';
3
+ import { h as connectionState, A as ApiClient, i as readSettings, j as encodeBase64, l as logger, p as projectPath } from './types-CkUHjxKz.mjs';
4
+ import { A as AcpSessionManager } from './AcpSessionManager-PCdfo4gz.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-Cnb_eI7Q.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-DVKieWPR.mjs';
8
8
  import 'node:child_process';
9
9
  import '@agentclientprotocol/sdk';
10
10
  import 'axios';
@@ -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-Dudpkl_i.cjs');
6
+ var persistence = require('./types-DJGEti9c.cjs');
7
7
  var spawn = require('cross-spawn');
8
8
  var path = require('node:path');
9
9
  var node_readline = require('node:readline');
@@ -286,6 +286,8 @@ class Session {
286
286
  hadAssistantOutputThisTurn = false;
287
287
  /** Last assistant text snippet seen this turn, used as the reply_done body. */
288
288
  lastAssistantSnippet;
289
+ /** Live remote-query input sink. Absent in local mode and between SDK queries. */
290
+ steerHandler = null;
289
291
  /** Callbacks to be notified when session ID is found/changed */
290
292
  sessionFoundCallbacks = [];
291
293
  /** Keep alive interval reference for cleanup */
@@ -326,8 +328,22 @@ class Session {
326
328
  cleanup = () => {
327
329
  clearInterval(this.keepAliveInterval);
328
330
  this.sessionFoundCallbacks = [];
331
+ this.steerHandler = null;
329
332
  persistence.logger.debug("[Session] Cleaned up resources");
330
333
  };
334
+ /** Register the current remote query's Steer sink; null removes it. */
335
+ setSteerHandler = (handler) => {
336
+ this.steerHandler = handler;
337
+ };
338
+ /**
339
+ * Attempt same-turn delivery. A stale Web "working" snapshot must never
340
+ * lose a message: once the turn is no longer thinking, return false and
341
+ * let runClaude fall back to the ordinary next-turn queue.
342
+ */
343
+ trySteer = async (input) => {
344
+ if (!this.thinking || !this.steerHandler) return false;
345
+ return this.steerHandler(input);
346
+ };
331
347
  onThinkingChange = (thinking) => {
332
348
  if (thinking && !this.thinking) {
333
349
  this.hadAssistantOutputThisTurn = false;
@@ -1916,6 +1932,7 @@ async function claudeRemote(opts) {
1916
1932
  messages.push({
1917
1933
  type: "user",
1918
1934
  parent_tool_use_id: null,
1935
+ origin: { kind: "human" },
1919
1936
  message: {
1920
1937
  role: "user",
1921
1938
  content: initial.message
@@ -1930,6 +1947,16 @@ async function claudeRemote(opts) {
1930
1947
  setPermissionMode: (mode2) => response.setPermissionMode(mode2),
1931
1948
  interrupt: async () => {
1932
1949
  await response.interrupt();
1950
+ },
1951
+ steer: (message, nextMode) => {
1952
+ mode = nextMode;
1953
+ messages.push({
1954
+ type: "user",
1955
+ parent_tool_use_id: null,
1956
+ priority: "now",
1957
+ origin: { kind: "human" },
1958
+ message: { role: "user", content: message }
1959
+ });
1933
1960
  }
1934
1961
  });
1935
1962
  }
@@ -1982,7 +2009,13 @@ async function claudeRemote(opts) {
1982
2009
  messages.end();
1983
2010
  } else {
1984
2011
  mode = next.mode;
1985
- messages.push({ type: "user", parent_tool_use_id: null, message: { role: "user", content: next.message } });
2012
+ updateThinking(true);
2013
+ messages.push({
2014
+ type: "user",
2015
+ parent_tool_use_id: null,
2016
+ origin: { kind: "human" },
2017
+ message: { role: "user", content: next.message }
2018
+ });
1986
2019
  }
1987
2020
  }).catch(() => {
1988
2021
  messages.end();
@@ -2079,16 +2112,7 @@ class PermissionHandler {
2079
2112
  });
2080
2113
  if (response.approved) {
2081
2114
  const newMode = response.mode && ["default", "acceptEdits", "bypassPermissions"].includes(response.mode) ? response.mode : "default";
2082
- persistence.logger.debug(`Plan approved - switching to ${newMode} mode and allowing ExitPlanMode`);
2083
- try {
2084
- if (!this.setPermissionModeCallback) throw new Error("permission mode updater unavailable");
2085
- await this.setPermissionModeCallback(newMode);
2086
- } catch (err) {
2087
- const reason = `Failed to switch permission mode: ${err instanceof Error ? err.message : String(err)}`;
2088
- persistence.logger.debug(reason);
2089
- pending.resolve({ behavior: "deny", message: reason });
2090
- return { ...response, approved: false, reason };
2091
- }
2115
+ persistence.logger.debug(`Plan approved - allowing ExitPlanMode with ${newMode} as the local follow-up mode`);
2092
2116
  this.permissionMode = newMode;
2093
2117
  pending.resolve({ behavior: "allow", updatedInput: pending.input || {} });
2094
2118
  } else {
@@ -2548,6 +2572,50 @@ function formatClaudeMessageForInk(message, messageBuffer, onAssistantResult) {
2548
2572
  }
2549
2573
  }
2550
2574
 
2575
+ const INTERRUPT_SENTINEL = /^\[Request interrupted by user(?: for tool use)?\]$/i;
2576
+ const EDE_DIAGNOSTIC_PREFIX = "[ede_diagnostic]";
2577
+ const SDK_ERROR_PREFIX = "Claude Code returned an error result:";
2578
+ function textBlocks(content) {
2579
+ if (!Array.isArray(content) || content.length === 0) return null;
2580
+ const texts = [];
2581
+ for (const block of content) {
2582
+ if (!block || typeof block !== "object" || block.type !== "text") {
2583
+ return null;
2584
+ }
2585
+ const text = block.text;
2586
+ if (typeof text !== "string") return null;
2587
+ texts.push(text.trim());
2588
+ }
2589
+ return texts;
2590
+ }
2591
+ function isClaudeInterruptSentinelContent(content) {
2592
+ if (typeof content === "string") {
2593
+ return INTERRUPT_SENTINEL.test(content.trim());
2594
+ }
2595
+ const texts = textBlocks(content);
2596
+ return texts !== null && texts.length > 0 && texts.every((text) => INTERRUPT_SENTINEL.test(text));
2597
+ }
2598
+ function resultErrors(value) {
2599
+ if (!value || typeof value !== "object") return [];
2600
+ const errors = value.errors;
2601
+ if (!Array.isArray(errors) || errors.length === 0 || errors.some((error) => typeof error !== "string")) {
2602
+ return [];
2603
+ }
2604
+ return errors.map((error) => error.trim()).filter(Boolean);
2605
+ }
2606
+ function isClaudeEdeOnlyResult(value) {
2607
+ const errors = resultErrors(value);
2608
+ return errors.length > 0 && errors.every((error) => error.startsWith(EDE_DIAGNOSTIC_PREFIX));
2609
+ }
2610
+ function isClaudeEdeOnlySdkError(error) {
2611
+ if (!(error instanceof Error)) return false;
2612
+ const message = error.message.trim();
2613
+ if (!message.startsWith(SDK_ERROR_PREFIX)) return false;
2614
+ const payload = message.slice(SDK_ERROR_PREFIX.length).trim();
2615
+ const entries = payload.split(/[;\n]+/).map((entry) => entry.trim()).filter(Boolean);
2616
+ return entries.length > 0 && entries.every((entry) => entry.startsWith(EDE_DIAGNOSTIC_PREFIX));
2617
+ }
2618
+
2551
2619
  function getGitBranch(cwd) {
2552
2620
  try {
2553
2621
  const branch = node_child_process.execSync("git rev-parse --abbrev-ref HEAD", {
@@ -2566,6 +2634,7 @@ class SDKToLogConverter {
2566
2634
  context;
2567
2635
  responses;
2568
2636
  sidechainLastUUID = /* @__PURE__ */ new Map();
2637
+ sawInterruptSentinel = false;
2569
2638
  constructor(context, responses) {
2570
2639
  this.context = {
2571
2640
  ...context,
@@ -2588,6 +2657,10 @@ class SDKToLogConverter {
2588
2657
  this.lastUuid = null;
2589
2658
  this.context.parentUuid = null;
2590
2659
  }
2660
+ /** Drop per-query markers that must never leak into the next SDK query. */
2661
+ resetTransientState() {
2662
+ this.sawInterruptSentinel = false;
2663
+ }
2591
2664
  /**
2592
2665
  * Convert SDK message to log format
2593
2666
  */
@@ -2617,6 +2690,10 @@ class SDKToLogConverter {
2617
2690
  switch (sdkMessage.type) {
2618
2691
  case "user": {
2619
2692
  const userMsg = sdkMessage;
2693
+ if (isClaudeInterruptSentinelContent(userMsg.message.content)) {
2694
+ this.sawInterruptSentinel = true;
2695
+ return null;
2696
+ }
2620
2697
  const meta = userMsg.isSynthetic === true || userMsg.isMeta === true;
2621
2698
  logMessage = {
2622
2699
  ...baseFields,
@@ -2669,6 +2746,8 @@ class SDKToLogConverter {
2669
2746
  }
2670
2747
  case "result": {
2671
2748
  const resultMsg = sdkMessage;
2749
+ const interrupted = this.sawInterruptSentinel || isClaudeEdeOnlyResult(resultMsg);
2750
+ this.sawInterruptSentinel = false;
2672
2751
  logMessage = {
2673
2752
  ...baseFields,
2674
2753
  type: "result",
@@ -2680,7 +2759,8 @@ class SDKToLogConverter {
2680
2759
  num_turns: resultMsg.num_turns,
2681
2760
  usage: resultMsg.usage,
2682
2761
  ..."errors" in resultMsg ? { errors: resultMsg.errors } : {},
2683
- ..."terminal_reason" in resultMsg && resultMsg.terminal_reason ? { terminal_reason: resultMsg.terminal_reason } : {}
2762
+ ..."terminal_reason" in resultMsg && resultMsg.terminal_reason ? { terminal_reason: resultMsg.terminal_reason } : {},
2763
+ ...interrupted ? { interrupted: true } : {}
2684
2764
  };
2685
2765
  break;
2686
2766
  }
@@ -3196,6 +3276,10 @@ async function claudeRemoteLauncher(session) {
3196
3276
  let ongoingToolCalls = /* @__PURE__ */ new Map();
3197
3277
  let notifiedQuestionToolCalls = /* @__PURE__ */ new Set();
3198
3278
  function onMessage(message) {
3279
+ if (message.type === "user" && isClaudeInterruptSentinelContent(message.message.content)) {
3280
+ sdkToLogConverter.convert(message);
3281
+ return;
3282
+ }
3199
3283
  formatClaudeMessageForInk(message, messageBuffer);
3200
3284
  if (message.type === "assistant") {
3201
3285
  let umessage = message;
@@ -3394,6 +3478,21 @@ async function claudeRemoteLauncher(session) {
3394
3478
  },
3395
3479
  onQueryReady: (q) => {
3396
3480
  turnSteering.setInterrupt(q.interrupt);
3481
+ session.setSteerHandler(async (input) => {
3482
+ const expectedHash = session.queue.modeHasher(input.mode);
3483
+ if (!modeHash || expectedHash !== modeHash) return false;
3484
+ let message = input.message;
3485
+ if (input.attachments?.length) {
3486
+ const staged = await stageClaudeAttachments(input.attachments, {
3487
+ happyHomeDir: persistence.configuration.happyHomeDir,
3488
+ sessionId: session.client.sessionId
3489
+ });
3490
+ message = appendStagedAttachmentsToPrompt(input.message, staged);
3491
+ }
3492
+ if (!session.thinking || modeHash !== expectedHash) return false;
3493
+ q.steer(message, input.mode);
3494
+ return true;
3495
+ });
3397
3496
  permissionHandler.setPermissionModeUpdater(async (mode2) => {
3398
3497
  await q.setPermissionMode(mode2);
3399
3498
  });
@@ -3446,6 +3545,10 @@ async function claudeRemoteLauncher(session) {
3446
3545
  } catch (e) {
3447
3546
  persistence.logger.debug("[remote]: launch error", e);
3448
3547
  if (!exitReason) {
3548
+ if (isClaudeEdeOnlySdkError(e)) {
3549
+ session.client.closeClaudeSessionTurn("cancelled");
3550
+ continue;
3551
+ }
3449
3552
  session.client.closeClaudeSessionTurn("failed");
3450
3553
  session.client.sendSessionEvent({ type: "message", message: "Process exited unexpectedly" });
3451
3554
  session.onSessionError(e instanceof Error ? e.message : "Process exited unexpectedly");
@@ -3453,6 +3556,8 @@ async function claudeRemoteLauncher(session) {
3453
3556
  }
3454
3557
  } finally {
3455
3558
  turnSteering.reset();
3559
+ session.setSteerHandler(null);
3560
+ sdkToLogConverter.resetTransientState();
3456
3561
  persistence.logger.debug("[remote]: launch finally");
3457
3562
  for (let [toolCallId, { parentToolCallId }] of ongoingToolCalls) {
3458
3563
  const converted = sdkToLogConverter.generateInterruptedToolResult(toolCallId, parentToolCallId);
@@ -8569,7 +8674,7 @@ const MAX_TITLE_CHARS = 60;
8569
8674
  const GENERATION_TIMEOUT_MS = 3e4;
8570
8675
  function resolveClaudeBinary() {
8571
8676
  try {
8572
- 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-B8UoTir2.cjs', document.baseURI).href)));
8677
+ 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-DUcWAKZ0.cjs', document.baseURI).href)));
8573
8678
  const utilsPath = path.resolve(path.join(persistence.projectPath(), "scripts", "claude_version_utils.cjs"));
8574
8679
  const { getClaudeCliPath } = require$1(utilsPath);
8575
8680
  const path$1 = getClaudeCliPath();
@@ -9026,6 +9131,7 @@ async function runClaude(credentials, options = {}) {
9026
9131
  // a brand-new session cannot pick a PDF until after sending once.
9027
9132
  attachmentKinds: [...CLAUDE_ATTACHMENT_KINDS],
9028
9133
  queueCancellation: true,
9134
+ capabilities: ["claude-steer-v1"],
9029
9135
  sandbox: sandboxConfig?.enabled ? sandboxConfig : null,
9030
9136
  dangerouslySkipPermissions,
9031
9137
  ...forkedFromSessionId ? { parentSessionId: forkedFromSessionId } : {},
@@ -9479,6 +9585,21 @@ async function runClaude(credentials, options = {}) {
9479
9585
  disallowedTools: messageDisallowedTools,
9480
9586
  effort: messageEffort
9481
9587
  };
9588
+ if (message.meta?.delivery === "steer" && currentRunMode === "remote") {
9589
+ const accepted = await currentSession?.trySteer({
9590
+ message: message.content.text,
9591
+ mode: enhancedMode,
9592
+ attachments: attachmentsForThisMessage
9593
+ }) === true;
9594
+ if (accepted) {
9595
+ persistence.logger.debug("User message steered into current turn:", {
9596
+ ...persistence.contentLogMetadata(message.content.text),
9597
+ attachmentCount: attachmentsForThisMessage?.length ?? 0
9598
+ });
9599
+ return;
9600
+ }
9601
+ persistence.logger.debug("[start] Steer arrived without a compatible live turn; falling back to queue");
9602
+ }
9482
9603
  messageQueue.push(message.content.text, enhancedMode, attachmentsForThisMessage, message.localKey);
9483
9604
  persistence.logger.debug("User message pushed to queue:", {
9484
9605
  ...persistence.contentLogMetadata(message.content.text),
@@ -10697,9 +10818,9 @@ function resolveLocalSignupBootstrap(configuredMode, configuredInviteCodes, gene
10697
10818
  };
10698
10819
  }
10699
10820
 
10700
- 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-B8UoTir2.cjs', document.baseURI).href)));
10821
+ 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-DUcWAKZ0.cjs', document.baseURI).href)));
10701
10822
  const __dirname$1 = path.dirname(__filename$1);
10702
- const require_ = node_module.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index-B8UoTir2.cjs', document.baseURI).href)));
10823
+ const require_ = node_module.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index-DUcWAKZ0.cjs', document.baseURI).href)));
10703
10824
  const PRISMA_QUERY_ENGINE_FILES = {
10704
10825
  "arm64-darwin": "libquery_engine-darwin-arm64.dylib.node",
10705
10826
  "x64-darwin": "libquery_engine-darwin.dylib.node",
@@ -13311,7 +13432,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
13311
13432
  process.exit(0);
13312
13433
  } else if (subcommand === "install-terminal-hooks") {
13313
13434
  try {
13314
- const { installTerminalHooks, parseTerminalHooksArgs, TERMINAL_HOOKS_HELP } = await Promise.resolve().then(function () { return require('./installTerminalHooks-mk1QIEvp.cjs'); });
13435
+ const { installTerminalHooks, parseTerminalHooksArgs, TERMINAL_HOOKS_HELP } = await Promise.resolve().then(function () { return require('./installTerminalHooks-hcCRjxNy.cjs'); });
13315
13436
  const command = parseTerminalHooksArgs(args.slice(1));
13316
13437
  if (command.action === "help") {
13317
13438
  console.log(TERMINAL_HOOKS_HELP);
@@ -13328,7 +13449,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
13328
13449
  }
13329
13450
  } else if (subcommand === "spawn") {
13330
13451
  try {
13331
- const { handleSpawnCommand } = await Promise.resolve().then(function () { return require('./spawn-Cm52jfN6.cjs'); });
13452
+ const { handleSpawnCommand } = await Promise.resolve().then(function () { return require('./spawn-Kklokpjz.cjs'); });
13332
13453
  await handleSpawnCommand(args.slice(1));
13333
13454
  } catch (error) {
13334
13455
  console.error(chalk.red("Error:"), error instanceof Error ? error.message : "Unknown error");
@@ -13340,7 +13461,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
13340
13461
  return;
13341
13462
  } else if (subcommand === "send") {
13342
13463
  try {
13343
- const { handleSendCommand } = await Promise.resolve().then(function () { return require('./send-DZIY545W.cjs'); });
13464
+ const { handleSendCommand } = await Promise.resolve().then(function () { return require('./send-iDuDd7yC.cjs'); });
13344
13465
  await handleSendCommand(args.slice(1));
13345
13466
  } catch (error) {
13346
13467
  console.error(chalk.red("Error:"), error instanceof Error ? error.message : "Unknown error");
@@ -13446,9 +13567,9 @@ Conversation history is preserved on the server, but in-flight tool calls are in
13446
13567
  if (geminiSubcommand === "project" && args[2] === "set" && args[3]) {
13447
13568
  const projectId = args[3];
13448
13569
  try {
13449
- const { saveGoogleCloudProjectToConfig } = await Promise.resolve().then(function () { return require('./config-Dv2kzos6.cjs'); });
13450
- const { readCredentialsForConfiguredRelay: readCredentialsForConfiguredRelay2 } = await Promise.resolve().then(function () { return require('./types-Dudpkl_i.cjs'); }).then(function (n) { return n.persistence; });
13451
- const { ApiClient: ApiClient2 } = await Promise.resolve().then(function () { return require('./types-Dudpkl_i.cjs'); }).then(function (n) { return n.api; });
13570
+ const { saveGoogleCloudProjectToConfig } = await Promise.resolve().then(function () { return require('./config-Ce5hbWlg.cjs'); });
13571
+ const { readCredentialsForConfiguredRelay: readCredentialsForConfiguredRelay2 } = await Promise.resolve().then(function () { return require('./types-DJGEti9c.cjs'); }).then(function (n) { return n.persistence; });
13572
+ const { ApiClient: ApiClient2 } = await Promise.resolve().then(function () { return require('./types-DJGEti9c.cjs'); }).then(function (n) { return n.api; });
13452
13573
  let userEmail = void 0;
13453
13574
  try {
13454
13575
  const credentials = await readCredentialsForConfiguredRelay2();
@@ -13479,7 +13600,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
13479
13600
  }
13480
13601
  if (geminiSubcommand === "project" && args[2] === "get") {
13481
13602
  try {
13482
- const { readGeminiLocalConfig } = await Promise.resolve().then(function () { return require('./config-Dv2kzos6.cjs'); });
13603
+ const { readGeminiLocalConfig } = await Promise.resolve().then(function () { return require('./config-Ce5hbWlg.cjs'); });
13483
13604
  const config = readGeminiLocalConfig();
13484
13605
  if (config.googleCloudProject) {
13485
13606
  console.log(`Current Google Cloud Project: ${config.googleCloudProject}`);
@@ -13519,7 +13640,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
13519
13640
  process.exit(0);
13520
13641
  }
13521
13642
  try {
13522
- const { runGemini } = await Promise.resolve().then(function () { return require('./runGemini-Cf_FQOrg.cjs'); });
13643
+ const { runGemini } = await Promise.resolve().then(function () { return require('./runGemini-U5JI6rsK.cjs'); });
13523
13644
  let startedBy = void 0;
13524
13645
  for (let i = 1; i < args.length; i++) {
13525
13646
  if (args[i] === "--started-by") {
@@ -13541,7 +13662,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
13541
13662
  return;
13542
13663
  } else if (subcommand === "acp") {
13543
13664
  try {
13544
- const { runAcp, resolveAcpAgentConfig } = await Promise.resolve().then(function () { return require('./index-CULwez6o.cjs'); });
13665
+ const { runAcp, resolveAcpAgentConfig } = await Promise.resolve().then(function () { return require('./index-Syfrd3oP.cjs'); });
13545
13666
  let startedBy = void 0;
13546
13667
  let verbose = false;
13547
13668
  const acpArgs = [];
@@ -13581,7 +13702,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
13581
13702
  return;
13582
13703
  } else if (subcommand === "openclaw") {
13583
13704
  try {
13584
- const { runOpenClaw } = await Promise.resolve().then(function () { return require('./runOpenClaw-BlZkYWEQ.cjs'); });
13705
+ const { runOpenClaw } = await Promise.resolve().then(function () { return require('./runOpenClaw-DJYiIMrs.cjs'); });
13585
13706
  let startedBy = void 0;
13586
13707
  let verbose = false;
13587
13708
  let gatewayUrl;
@@ -13632,7 +13753,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
13632
13753
  return;
13633
13754
  } else if (subcommand === "mcp" && args.length === 1) {
13634
13755
  try {
13635
- const { handleMcpCommand } = await Promise.resolve().then(function () { return require('./mcp-X7yyQ2d_.cjs'); });
13756
+ const { handleMcpCommand } = await Promise.resolve().then(function () { return require('./mcp-DGHMyTt-.cjs'); });
13636
13757
  await handleMcpCommand();
13637
13758
  } catch (error) {
13638
13759
  process.stderr.write(`[very-happy mcp] Fatal: ${error instanceof Error ? error.message : String(error)}
@@ -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 } 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 getLocalHappyAgentCredentialPath, L as readLocalHappyAgentCredentials, N as decryptWithDataKey, O as decryptLegacy, P as extractCompleteLines, Q as decideBackfill, S as parseTerminalHookPayload, T as decideMirrorBinding, U as persistSession, V as MIRROR_BACKFILL_LINES_DEFAULT, W as mirrorLineKey, X as mirrorLocalId, Y as detectResumeSupport, Z as detectCLIAvailability, _ as acquireDaemonLock, $ as summarizeSpawnSessionForLog, a0 as deletePersistedSessions, a1 as decrypt, a2 as writeDaemonState, A as ApiClient, a3 as fetchCliUpdateState, a4 as resolveCliUpdateCheckInterval, a5 as DEFAULT_CLI_UPDATE_CHECK_INTERVAL_MS, a6 as releaseDaemonLock, a7 as isValidSessionId, a8 as listVhTerminals, a9 as isValidTerminalId, aa as readVhTerminal, ab as sendToVhTerminal, h as connectionState, ac as startOfflineReconnection, ad as clearCredentials, ae as clearMachineId, k as ensurePrivateDirectorySync, w as writePrivateFileSync, af as SandboxConfigSchema, b as createEnvelope, ag as CodexAppServerClient, ah as getLatestDaemonLog } from './types-Bv1nc9M1.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 getLocalHappyAgentCredentialPath, L as readLocalHappyAgentCredentials, N as decryptWithDataKey, O as decryptLegacy, P as extractCompleteLines, Q as decideBackfill, S as parseTerminalHookPayload, T as decideMirrorBinding, U as persistSession, V as MIRROR_BACKFILL_LINES_DEFAULT, W as mirrorLineKey, X as mirrorLocalId, Y as detectResumeSupport, Z as detectCLIAvailability, _ as acquireDaemonLock, $ as summarizeSpawnSessionForLog, a0 as deletePersistedSessions, a1 as decrypt, a2 as writeDaemonState, A as ApiClient, a3 as fetchCliUpdateState, a4 as resolveCliUpdateCheckInterval, a5 as DEFAULT_CLI_UPDATE_CHECK_INTERVAL_MS, a6 as releaseDaemonLock, a7 as isValidSessionId, a8 as listVhTerminals, a9 as isValidTerminalId, aa as readVhTerminal, ab as sendToVhTerminal, h as connectionState, ac as startOfflineReconnection, ad as clearCredentials, ae as clearMachineId, k as ensurePrivateDirectorySync, w as writePrivateFileSync, af as SandboxConfigSchema, b as createEnvelope, ag as CodexAppServerClient, ah as getLatestDaemonLog } from './types-CkUHjxKz.mjs';
5
5
  import spawn$1, { spawn } from 'cross-spawn';
6
6
  import path, { join, resolve, basename, isAbsolute, normalize, sep, dirname } from 'node:path';
7
7
  import { createInterface } from 'node:readline';
@@ -264,6 +264,8 @@ class Session {
264
264
  hadAssistantOutputThisTurn = false;
265
265
  /** Last assistant text snippet seen this turn, used as the reply_done body. */
266
266
  lastAssistantSnippet;
267
+ /** Live remote-query input sink. Absent in local mode and between SDK queries. */
268
+ steerHandler = null;
267
269
  /** Callbacks to be notified when session ID is found/changed */
268
270
  sessionFoundCallbacks = [];
269
271
  /** Keep alive interval reference for cleanup */
@@ -304,8 +306,22 @@ class Session {
304
306
  cleanup = () => {
305
307
  clearInterval(this.keepAliveInterval);
306
308
  this.sessionFoundCallbacks = [];
309
+ this.steerHandler = null;
307
310
  logger.debug("[Session] Cleaned up resources");
308
311
  };
312
+ /** Register the current remote query's Steer sink; null removes it. */
313
+ setSteerHandler = (handler) => {
314
+ this.steerHandler = handler;
315
+ };
316
+ /**
317
+ * Attempt same-turn delivery. A stale Web "working" snapshot must never
318
+ * lose a message: once the turn is no longer thinking, return false and
319
+ * let runClaude fall back to the ordinary next-turn queue.
320
+ */
321
+ trySteer = async (input) => {
322
+ if (!this.thinking || !this.steerHandler) return false;
323
+ return this.steerHandler(input);
324
+ };
309
325
  onThinkingChange = (thinking) => {
310
326
  if (thinking && !this.thinking) {
311
327
  this.hadAssistantOutputThisTurn = false;
@@ -1894,6 +1910,7 @@ async function claudeRemote(opts) {
1894
1910
  messages.push({
1895
1911
  type: "user",
1896
1912
  parent_tool_use_id: null,
1913
+ origin: { kind: "human" },
1897
1914
  message: {
1898
1915
  role: "user",
1899
1916
  content: initial.message
@@ -1908,6 +1925,16 @@ async function claudeRemote(opts) {
1908
1925
  setPermissionMode: (mode2) => response.setPermissionMode(mode2),
1909
1926
  interrupt: async () => {
1910
1927
  await response.interrupt();
1928
+ },
1929
+ steer: (message, nextMode) => {
1930
+ mode = nextMode;
1931
+ messages.push({
1932
+ type: "user",
1933
+ parent_tool_use_id: null,
1934
+ priority: "now",
1935
+ origin: { kind: "human" },
1936
+ message: { role: "user", content: message }
1937
+ });
1911
1938
  }
1912
1939
  });
1913
1940
  }
@@ -1960,7 +1987,13 @@ async function claudeRemote(opts) {
1960
1987
  messages.end();
1961
1988
  } else {
1962
1989
  mode = next.mode;
1963
- messages.push({ type: "user", parent_tool_use_id: null, message: { role: "user", content: next.message } });
1990
+ updateThinking(true);
1991
+ messages.push({
1992
+ type: "user",
1993
+ parent_tool_use_id: null,
1994
+ origin: { kind: "human" },
1995
+ message: { role: "user", content: next.message }
1996
+ });
1964
1997
  }
1965
1998
  }).catch(() => {
1966
1999
  messages.end();
@@ -2057,16 +2090,7 @@ class PermissionHandler {
2057
2090
  });
2058
2091
  if (response.approved) {
2059
2092
  const newMode = response.mode && ["default", "acceptEdits", "bypassPermissions"].includes(response.mode) ? response.mode : "default";
2060
- logger.debug(`Plan approved - switching to ${newMode} mode and allowing ExitPlanMode`);
2061
- try {
2062
- if (!this.setPermissionModeCallback) throw new Error("permission mode updater unavailable");
2063
- await this.setPermissionModeCallback(newMode);
2064
- } catch (err) {
2065
- const reason = `Failed to switch permission mode: ${err instanceof Error ? err.message : String(err)}`;
2066
- logger.debug(reason);
2067
- pending.resolve({ behavior: "deny", message: reason });
2068
- return { ...response, approved: false, reason };
2069
- }
2093
+ logger.debug(`Plan approved - allowing ExitPlanMode with ${newMode} as the local follow-up mode`);
2070
2094
  this.permissionMode = newMode;
2071
2095
  pending.resolve({ behavior: "allow", updatedInput: pending.input || {} });
2072
2096
  } else {
@@ -2526,6 +2550,50 @@ function formatClaudeMessageForInk(message, messageBuffer, onAssistantResult) {
2526
2550
  }
2527
2551
  }
2528
2552
 
2553
+ const INTERRUPT_SENTINEL = /^\[Request interrupted by user(?: for tool use)?\]$/i;
2554
+ const EDE_DIAGNOSTIC_PREFIX = "[ede_diagnostic]";
2555
+ const SDK_ERROR_PREFIX = "Claude Code returned an error result:";
2556
+ function textBlocks(content) {
2557
+ if (!Array.isArray(content) || content.length === 0) return null;
2558
+ const texts = [];
2559
+ for (const block of content) {
2560
+ if (!block || typeof block !== "object" || block.type !== "text") {
2561
+ return null;
2562
+ }
2563
+ const text = block.text;
2564
+ if (typeof text !== "string") return null;
2565
+ texts.push(text.trim());
2566
+ }
2567
+ return texts;
2568
+ }
2569
+ function isClaudeInterruptSentinelContent(content) {
2570
+ if (typeof content === "string") {
2571
+ return INTERRUPT_SENTINEL.test(content.trim());
2572
+ }
2573
+ const texts = textBlocks(content);
2574
+ return texts !== null && texts.length > 0 && texts.every((text) => INTERRUPT_SENTINEL.test(text));
2575
+ }
2576
+ function resultErrors(value) {
2577
+ if (!value || typeof value !== "object") return [];
2578
+ const errors = value.errors;
2579
+ if (!Array.isArray(errors) || errors.length === 0 || errors.some((error) => typeof error !== "string")) {
2580
+ return [];
2581
+ }
2582
+ return errors.map((error) => error.trim()).filter(Boolean);
2583
+ }
2584
+ function isClaudeEdeOnlyResult(value) {
2585
+ const errors = resultErrors(value);
2586
+ return errors.length > 0 && errors.every((error) => error.startsWith(EDE_DIAGNOSTIC_PREFIX));
2587
+ }
2588
+ function isClaudeEdeOnlySdkError(error) {
2589
+ if (!(error instanceof Error)) return false;
2590
+ const message = error.message.trim();
2591
+ if (!message.startsWith(SDK_ERROR_PREFIX)) return false;
2592
+ const payload = message.slice(SDK_ERROR_PREFIX.length).trim();
2593
+ const entries = payload.split(/[;\n]+/).map((entry) => entry.trim()).filter(Boolean);
2594
+ return entries.length > 0 && entries.every((entry) => entry.startsWith(EDE_DIAGNOSTIC_PREFIX));
2595
+ }
2596
+
2529
2597
  function getGitBranch(cwd) {
2530
2598
  try {
2531
2599
  const branch = execSync("git rev-parse --abbrev-ref HEAD", {
@@ -2544,6 +2612,7 @@ class SDKToLogConverter {
2544
2612
  context;
2545
2613
  responses;
2546
2614
  sidechainLastUUID = /* @__PURE__ */ new Map();
2615
+ sawInterruptSentinel = false;
2547
2616
  constructor(context, responses) {
2548
2617
  this.context = {
2549
2618
  ...context,
@@ -2566,6 +2635,10 @@ class SDKToLogConverter {
2566
2635
  this.lastUuid = null;
2567
2636
  this.context.parentUuid = null;
2568
2637
  }
2638
+ /** Drop per-query markers that must never leak into the next SDK query. */
2639
+ resetTransientState() {
2640
+ this.sawInterruptSentinel = false;
2641
+ }
2569
2642
  /**
2570
2643
  * Convert SDK message to log format
2571
2644
  */
@@ -2595,6 +2668,10 @@ class SDKToLogConverter {
2595
2668
  switch (sdkMessage.type) {
2596
2669
  case "user": {
2597
2670
  const userMsg = sdkMessage;
2671
+ if (isClaudeInterruptSentinelContent(userMsg.message.content)) {
2672
+ this.sawInterruptSentinel = true;
2673
+ return null;
2674
+ }
2598
2675
  const meta = userMsg.isSynthetic === true || userMsg.isMeta === true;
2599
2676
  logMessage = {
2600
2677
  ...baseFields,
@@ -2647,6 +2724,8 @@ class SDKToLogConverter {
2647
2724
  }
2648
2725
  case "result": {
2649
2726
  const resultMsg = sdkMessage;
2727
+ const interrupted = this.sawInterruptSentinel || isClaudeEdeOnlyResult(resultMsg);
2728
+ this.sawInterruptSentinel = false;
2650
2729
  logMessage = {
2651
2730
  ...baseFields,
2652
2731
  type: "result",
@@ -2658,7 +2737,8 @@ class SDKToLogConverter {
2658
2737
  num_turns: resultMsg.num_turns,
2659
2738
  usage: resultMsg.usage,
2660
2739
  ..."errors" in resultMsg ? { errors: resultMsg.errors } : {},
2661
- ..."terminal_reason" in resultMsg && resultMsg.terminal_reason ? { terminal_reason: resultMsg.terminal_reason } : {}
2740
+ ..."terminal_reason" in resultMsg && resultMsg.terminal_reason ? { terminal_reason: resultMsg.terminal_reason } : {},
2741
+ ...interrupted ? { interrupted: true } : {}
2662
2742
  };
2663
2743
  break;
2664
2744
  }
@@ -3174,6 +3254,10 @@ async function claudeRemoteLauncher(session) {
3174
3254
  let ongoingToolCalls = /* @__PURE__ */ new Map();
3175
3255
  let notifiedQuestionToolCalls = /* @__PURE__ */ new Set();
3176
3256
  function onMessage(message) {
3257
+ if (message.type === "user" && isClaudeInterruptSentinelContent(message.message.content)) {
3258
+ sdkToLogConverter.convert(message);
3259
+ return;
3260
+ }
3177
3261
  formatClaudeMessageForInk(message, messageBuffer);
3178
3262
  if (message.type === "assistant") {
3179
3263
  let umessage = message;
@@ -3372,6 +3456,21 @@ async function claudeRemoteLauncher(session) {
3372
3456
  },
3373
3457
  onQueryReady: (q) => {
3374
3458
  turnSteering.setInterrupt(q.interrupt);
3459
+ session.setSteerHandler(async (input) => {
3460
+ const expectedHash = session.queue.modeHasher(input.mode);
3461
+ if (!modeHash || expectedHash !== modeHash) return false;
3462
+ let message = input.message;
3463
+ if (input.attachments?.length) {
3464
+ const staged = await stageClaudeAttachments(input.attachments, {
3465
+ happyHomeDir: configuration.happyHomeDir,
3466
+ sessionId: session.client.sessionId
3467
+ });
3468
+ message = appendStagedAttachmentsToPrompt(input.message, staged);
3469
+ }
3470
+ if (!session.thinking || modeHash !== expectedHash) return false;
3471
+ q.steer(message, input.mode);
3472
+ return true;
3473
+ });
3375
3474
  permissionHandler.setPermissionModeUpdater(async (mode2) => {
3376
3475
  await q.setPermissionMode(mode2);
3377
3476
  });
@@ -3424,6 +3523,10 @@ async function claudeRemoteLauncher(session) {
3424
3523
  } catch (e) {
3425
3524
  logger.debug("[remote]: launch error", e);
3426
3525
  if (!exitReason) {
3526
+ if (isClaudeEdeOnlySdkError(e)) {
3527
+ session.client.closeClaudeSessionTurn("cancelled");
3528
+ continue;
3529
+ }
3427
3530
  session.client.closeClaudeSessionTurn("failed");
3428
3531
  session.client.sendSessionEvent({ type: "message", message: "Process exited unexpectedly" });
3429
3532
  session.onSessionError(e instanceof Error ? e.message : "Process exited unexpectedly");
@@ -3431,6 +3534,8 @@ async function claudeRemoteLauncher(session) {
3431
3534
  }
3432
3535
  } finally {
3433
3536
  turnSteering.reset();
3537
+ session.setSteerHandler(null);
3538
+ sdkToLogConverter.resetTransientState();
3434
3539
  logger.debug("[remote]: launch finally");
3435
3540
  for (let [toolCallId, { parentToolCallId }] of ongoingToolCalls) {
3436
3541
  const converted = sdkToLogConverter.generateInterruptedToolResult(toolCallId, parentToolCallId);
@@ -9004,6 +9109,7 @@ async function runClaude(credentials, options = {}) {
9004
9109
  // a brand-new session cannot pick a PDF until after sending once.
9005
9110
  attachmentKinds: [...CLAUDE_ATTACHMENT_KINDS],
9006
9111
  queueCancellation: true,
9112
+ capabilities: ["claude-steer-v1"],
9007
9113
  sandbox: sandboxConfig?.enabled ? sandboxConfig : null,
9008
9114
  dangerouslySkipPermissions,
9009
9115
  ...forkedFromSessionId ? { parentSessionId: forkedFromSessionId } : {},
@@ -9457,6 +9563,21 @@ async function runClaude(credentials, options = {}) {
9457
9563
  disallowedTools: messageDisallowedTools,
9458
9564
  effort: messageEffort
9459
9565
  };
9566
+ if (message.meta?.delivery === "steer" && currentRunMode === "remote") {
9567
+ const accepted = await currentSession?.trySteer({
9568
+ message: message.content.text,
9569
+ mode: enhancedMode,
9570
+ attachments: attachmentsForThisMessage
9571
+ }) === true;
9572
+ if (accepted) {
9573
+ logger.debug("User message steered into current turn:", {
9574
+ ...contentLogMetadata(message.content.text),
9575
+ attachmentCount: attachmentsForThisMessage?.length ?? 0
9576
+ });
9577
+ return;
9578
+ }
9579
+ logger.debug("[start] Steer arrived without a compatible live turn; falling back to queue");
9580
+ }
9460
9581
  messageQueue.push(message.content.text, enhancedMode, attachmentsForThisMessage, message.localKey);
9461
9582
  logger.debug("User message pushed to queue:", {
9462
9583
  ...contentLogMetadata(message.content.text),
@@ -13289,7 +13410,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
13289
13410
  process.exit(0);
13290
13411
  } else if (subcommand === "install-terminal-hooks") {
13291
13412
  try {
13292
- const { installTerminalHooks, parseTerminalHooksArgs, TERMINAL_HOOKS_HELP } = await import('./installTerminalHooks-C-8Vuwlu.mjs');
13413
+ const { installTerminalHooks, parseTerminalHooksArgs, TERMINAL_HOOKS_HELP } = await import('./installTerminalHooks-BMTBsCfi.mjs');
13293
13414
  const command = parseTerminalHooksArgs(args.slice(1));
13294
13415
  if (command.action === "help") {
13295
13416
  console.log(TERMINAL_HOOKS_HELP);
@@ -13306,7 +13427,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
13306
13427
  }
13307
13428
  } else if (subcommand === "spawn") {
13308
13429
  try {
13309
- const { handleSpawnCommand } = await import('./spawn-hjPuTkvH.mjs');
13430
+ const { handleSpawnCommand } = await import('./spawn-DPz_3Q6B.mjs');
13310
13431
  await handleSpawnCommand(args.slice(1));
13311
13432
  } catch (error) {
13312
13433
  console.error(chalk.red("Error:"), error instanceof Error ? error.message : "Unknown error");
@@ -13318,7 +13439,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
13318
13439
  return;
13319
13440
  } else if (subcommand === "send") {
13320
13441
  try {
13321
- const { handleSendCommand } = await import('./send-C6-E03t-.mjs');
13442
+ const { handleSendCommand } = await import('./send-AIDeVBON.mjs');
13322
13443
  await handleSendCommand(args.slice(1));
13323
13444
  } catch (error) {
13324
13445
  console.error(chalk.red("Error:"), error instanceof Error ? error.message : "Unknown error");
@@ -13424,9 +13545,9 @@ Conversation history is preserved on the server, but in-flight tool calls are in
13424
13545
  if (geminiSubcommand === "project" && args[2] === "set" && args[3]) {
13425
13546
  const projectId = args[3];
13426
13547
  try {
13427
- const { saveGoogleCloudProjectToConfig } = await import('./config-CQjk8rce.mjs');
13428
- const { readCredentialsForConfiguredRelay: readCredentialsForConfiguredRelay2 } = await import('./types-Bv1nc9M1.mjs').then(function (n) { return n.ai; });
13429
- const { ApiClient: ApiClient2 } = await import('./types-Bv1nc9M1.mjs').then(function (n) { return n.aj; });
13548
+ const { saveGoogleCloudProjectToConfig } = await import('./config-DDsvmCxL.mjs');
13549
+ const { readCredentialsForConfiguredRelay: readCredentialsForConfiguredRelay2 } = await import('./types-CkUHjxKz.mjs').then(function (n) { return n.ai; });
13550
+ const { ApiClient: ApiClient2 } = await import('./types-CkUHjxKz.mjs').then(function (n) { return n.aj; });
13430
13551
  let userEmail = void 0;
13431
13552
  try {
13432
13553
  const credentials = await readCredentialsForConfiguredRelay2();
@@ -13457,7 +13578,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
13457
13578
  }
13458
13579
  if (geminiSubcommand === "project" && args[2] === "get") {
13459
13580
  try {
13460
- const { readGeminiLocalConfig } = await import('./config-CQjk8rce.mjs');
13581
+ const { readGeminiLocalConfig } = await import('./config-DDsvmCxL.mjs');
13461
13582
  const config = readGeminiLocalConfig();
13462
13583
  if (config.googleCloudProject) {
13463
13584
  console.log(`Current Google Cloud Project: ${config.googleCloudProject}`);
@@ -13497,7 +13618,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
13497
13618
  process.exit(0);
13498
13619
  }
13499
13620
  try {
13500
- const { runGemini } = await import('./runGemini-Nig1hb70.mjs');
13621
+ const { runGemini } = await import('./runGemini-CUpp6u-S.mjs');
13501
13622
  let startedBy = void 0;
13502
13623
  for (let i = 1; i < args.length; i++) {
13503
13624
  if (args[i] === "--started-by") {
@@ -13519,7 +13640,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
13519
13640
  return;
13520
13641
  } else if (subcommand === "acp") {
13521
13642
  try {
13522
- const { runAcp, resolveAcpAgentConfig } = await import('./index-Cc2VYKqa.mjs');
13643
+ const { runAcp, resolveAcpAgentConfig } = await import('./index-CCQ2mqkA.mjs');
13523
13644
  let startedBy = void 0;
13524
13645
  let verbose = false;
13525
13646
  const acpArgs = [];
@@ -13559,7 +13680,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
13559
13680
  return;
13560
13681
  } else if (subcommand === "openclaw") {
13561
13682
  try {
13562
- const { runOpenClaw } = await import('./runOpenClaw-DllszOSy.mjs');
13683
+ const { runOpenClaw } = await import('./runOpenClaw-BHR7emaO.mjs');
13563
13684
  let startedBy = void 0;
13564
13685
  let verbose = false;
13565
13686
  let gatewayUrl;
@@ -13610,7 +13731,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
13610
13731
  return;
13611
13732
  } else if (subcommand === "mcp" && args.length === 1) {
13612
13733
  try {
13613
- const { handleMcpCommand } = await import('./mcp-BZba259A.mjs');
13734
+ const { handleMcpCommand } = await import('./mcp-C2bERsV2.mjs');
13614
13735
  await handleMcpCommand();
13615
13736
  } catch (error) {
13616
13737
  process.stderr.write(`[very-happy mcp] Fatal: ${error instanceof Error ? error.message : String(error)}
@@ -1,11 +1,11 @@
1
1
  'use strict';
2
2
 
3
- var AcpBackend = require('./AcpBackend-DxoxNKOM.cjs');
4
- var persistence = require('./types-Dudpkl_i.cjs');
5
- var AcpSessionManager = require('./AcpSessionManager-_bG1kjZz.cjs');
3
+ var AcpBackend = require('./AcpBackend-B1l_WyZy.cjs');
4
+ var persistence = require('./types-DJGEti9c.cjs');
5
+ var AcpSessionManager = require('./AcpSessionManager-dVX0uTo8.cjs');
6
6
  var node_crypto = require('node:crypto');
7
7
  var path = require('node:path');
8
- var index = require('./index-B8UoTir2.cjs');
8
+ var index = require('./index-DUcWAKZ0.cjs');
9
9
  require('node:child_process');
10
10
  require('@agentclientprotocol/sdk');
11
11
  require('axios');
package/dist/index.cjs CHANGED
@@ -1,8 +1,8 @@
1
1
  'use strict';
2
2
 
3
3
  require('chalk');
4
- require('./index-B8UoTir2.cjs');
5
- require('./types-Dudpkl_i.cjs');
4
+ require('./index-DUcWAKZ0.cjs');
5
+ require('./types-DJGEti9c.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-Cnb_eI7Q.mjs';
3
- import './types-Bv1nc9M1.mjs';
2
+ import './index-DVKieWPR.mjs';
3
+ import './types-CkUHjxKz.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-Bv1nc9M1.mjs';
7
- import { t as tmuxSupportsSessionEnv } from './index-Cnb_eI7Q.mjs';
6
+ import { p as projectPath } from './types-CkUHjxKz.mjs';
7
+ import { t as tmuxSupportsSessionEnv } from './index-DVKieWPR.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-Dudpkl_i.cjs');
9
- var index = require('./index-B8UoTir2.cjs');
8
+ var persistence = require('./types-DJGEti9c.cjs');
9
+ var index = require('./index-DUcWAKZ0.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-Dudpkl_i.cjs');
3
+ var persistence = require('./types-DJGEti9c.cjs');
4
4
  require('axios');
5
5
  require('chalk');
6
6
  require('node:util');
package/dist/lib.d.cts CHANGED
@@ -347,6 +347,10 @@ declare const UserMessageSchema: z$1.ZodObject<{
347
347
  appendSystemPrompt: z$1.ZodOptional<z$1.ZodNullable<z$1.ZodString>>;
348
348
  allowedTools: z$1.ZodOptional<z$1.ZodNullable<z$1.ZodArray<z$1.ZodString>>>;
349
349
  disallowedTools: z$1.ZodOptional<z$1.ZodNullable<z$1.ZodArray<z$1.ZodString>>>;
350
+ delivery: z$1.ZodOptional<z$1.ZodEnum<{
351
+ queue: "queue";
352
+ steer: "steer";
353
+ }>>;
350
354
  }, z$1.core.$strip>>;
351
355
  }, z$1.core.$strip>;
352
356
  type UserMessage = z$1.infer<typeof UserMessageSchema>;
@@ -431,6 +435,8 @@ type Metadata = {
431
435
  attachmentKinds?: string[];
432
436
  /** Pending user messages can be canceled by stable transport id. */
433
437
  queueCancellation?: boolean;
438
+ /** Explicit feature negotiation; old CLIs omit this field. */
439
+ capabilities?: string[];
434
440
  homeDir: string;
435
441
  happyHomeDir: string;
436
442
  happyLibDir: string;
package/dist/lib.d.mts CHANGED
@@ -347,6 +347,10 @@ declare const UserMessageSchema: z$1.ZodObject<{
347
347
  appendSystemPrompt: z$1.ZodOptional<z$1.ZodNullable<z$1.ZodString>>;
348
348
  allowedTools: z$1.ZodOptional<z$1.ZodNullable<z$1.ZodArray<z$1.ZodString>>>;
349
349
  disallowedTools: z$1.ZodOptional<z$1.ZodNullable<z$1.ZodArray<z$1.ZodString>>>;
350
+ delivery: z$1.ZodOptional<z$1.ZodEnum<{
351
+ queue: "queue";
352
+ steer: "steer";
353
+ }>>;
350
354
  }, z$1.core.$strip>>;
351
355
  }, z$1.core.$strip>;
352
356
  type UserMessage = z$1.infer<typeof UserMessageSchema>;
@@ -431,6 +435,8 @@ type Metadata = {
431
435
  attachmentKinds?: string[];
432
436
  /** Pending user messages can be canceled by stable transport id. */
433
437
  queueCancellation?: boolean;
438
+ /** Explicit feature negotiation; old CLIs omit this field. */
439
+ capabilities?: string[];
434
440
  homeDir: string;
435
441
  happyHomeDir: string;
436
442
  happyLibDir: string;
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-Bv1nc9M1.mjs';
1
+ export { A as ApiClient, a as ApiSessionClient, R as RawJSONLinesSchema, c as configuration, l as logger } from './types-CkUHjxKz.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-Cnb_eI7Q.mjs';
4
+ import { p as pushClipboardViaDaemon } from './index-DVKieWPR.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-Bv1nc9M1.mjs';
6
+ import { l as logger } from './types-CkUHjxKz.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-B8UoTir2.cjs');
6
+ var index = require('./index-DUcWAKZ0.cjs');
7
7
  var limits = require('./limits-KdWKmwtH.cjs');
8
- var persistence = require('./types-Dudpkl_i.cjs');
8
+ var persistence = require('./types-DJGEti9c.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-Bv1nc9M1.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-Cnb_eI7Q.mjs';
7
- import { A as AcpBackend } from './AcpBackend-BgOEcqMG.mjs';
8
- import { readGeminiLocalConfig, determineGeminiModel, getGeminiModelSource, getInitialGeminiModel, saveGeminiModelToConfig } from './config-CQjk8rce.mjs';
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-CkUHjxKz.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-DVKieWPR.mjs';
7
+ import { A as AcpBackend } from './AcpBackend-CDclNgxu.mjs';
8
+ import { readGeminiLocalConfig, determineGeminiModel, getGeminiModelSource, getInitialGeminiModel, saveGeminiModelToConfig } from './config-DDsvmCxL.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-Dudpkl_i.cjs');
8
- var index = require('./index-B8UoTir2.cjs');
9
- var AcpBackend = require('./AcpBackend-DxoxNKOM.cjs');
10
- var config = require('./config-Dv2kzos6.cjs');
7
+ var persistence = require('./types-DJGEti9c.cjs');
8
+ var index = require('./index-DUcWAKZ0.cjs');
9
+ var AcpBackend = require('./AcpBackend-B1l_WyZy.cjs');
10
+ var config = require('./config-Ce5hbWlg.cjs');
11
11
  require('axios');
12
12
  require('chalk');
13
13
  require('node:util');
@@ -3,9 +3,9 @@ import { execFileSync } from 'node:child_process';
3
3
  import os from 'node:os';
4
4
  import { existsSync, readFileSync } from 'node:fs';
5
5
  import { join } from 'node:path';
6
- import { k as ensurePrivateDirectorySync, m as hardenPrivateFileSync, w as writePrivateFileSync, e as errorLogMetadata, d as contentLogMetadata, h as connectionState, A as ApiClient, i as readSettings, j as encodeBase64, l as logger, c as configuration } from './types-Bv1nc9M1.mjs';
7
- import { A as AcpSessionManager } from './AcpSessionManager-Ba9ON7eK.mjs';
8
- import { i as initialMachineMetadata, d as createSessionMetadata, e as setupOfflineReconnection, n as notifyDaemonSessionStarted, M as MessageQueue2, r as registerKillSessionHandler } from './index-Cnb_eI7Q.mjs';
6
+ import { k as ensurePrivateDirectorySync, m as hardenPrivateFileSync, w as writePrivateFileSync, e as errorLogMetadata, d as contentLogMetadata, h as connectionState, A as ApiClient, i as readSettings, j as encodeBase64, l as logger, c as configuration } from './types-CkUHjxKz.mjs';
7
+ import { A as AcpSessionManager } from './AcpSessionManager-PCdfo4gz.mjs';
8
+ import { i as initialMachineMetadata, d as createSessionMetadata, e as setupOfflineReconnection, n as notifyDaemonSessionStarted, M as MessageQueue2, r as registerKillSessionHandler } from './index-DVKieWPR.mjs';
9
9
  import WebSocket from 'ws';
10
10
  import * as ed from '@noble/ed25519';
11
11
  import { sha512 } from '@noble/hashes/sha2.js';
@@ -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-Dudpkl_i.cjs');
9
- var AcpSessionManager = require('./AcpSessionManager-_bG1kjZz.cjs');
10
- var index = require('./index-B8UoTir2.cjs');
8
+ var persistence = require('./types-DJGEti9c.cjs');
9
+ var AcpSessionManager = require('./AcpSessionManager-dVX0uTo8.cjs');
10
+ var index = require('./index-DUcWAKZ0.cjs');
11
11
  var WebSocket = require('ws');
12
12
  var ed = require('@noble/ed25519');
13
13
  var sha2_js = require('@noble/hashes/sha2.js');
@@ -1,8 +1,8 @@
1
1
  import chalk from 'chalk';
2
2
  import { readFileSync } from 'node:fs';
3
3
  import { resolve } from 'node:path';
4
- import { r as readPersistedSessions, c as configuration } from './types-Bv1nc9M1.mjs';
5
- import { b as sendUserMessage, a as sessionWebUrl } from './index-Cnb_eI7Q.mjs';
4
+ import { r as readPersistedSessions, c as configuration } from './types-CkUHjxKz.mjs';
5
+ import { b as sendUserMessage, a as sessionWebUrl } from './index-DVKieWPR.mjs';
6
6
  import 'axios';
7
7
  import 'node:util';
8
8
  import 'node:os';
@@ -3,8 +3,8 @@
3
3
  var chalk = require('chalk');
4
4
  var node_fs = require('node:fs');
5
5
  var path = require('node:path');
6
- var persistence = require('./types-Dudpkl_i.cjs');
7
- var index = require('./index-B8UoTir2.cjs');
6
+ var persistence = require('./types-DJGEti9c.cjs');
7
+ var index = require('./index-DUcWAKZ0.cjs');
8
8
  require('axios');
9
9
  require('node:util');
10
10
  require('node:os');
@@ -1,8 +1,8 @@
1
1
  import chalk from 'chalk';
2
2
  import { readFileSync, statSync } from 'node:fs';
3
3
  import { resolve } from 'node:path';
4
- import { c as checkIfDaemonRunningAndCleanupStaleState, s as spawnDaemonSession, a as sessionWebUrl, w as waitForSessionKey, b as sendUserMessage } from './index-Cnb_eI7Q.mjs';
5
- import { l as logger } from './types-Bv1nc9M1.mjs';
4
+ import { c as checkIfDaemonRunningAndCleanupStaleState, s as spawnDaemonSession, a as sessionWebUrl, w as waitForSessionKey, b as sendUserMessage } from './index-DVKieWPR.mjs';
5
+ import { l as logger } from './types-CkUHjxKz.mjs';
6
6
  import 'node:os';
7
7
  import 'node:crypto';
8
8
  import 'cross-spawn';
@@ -3,8 +3,8 @@
3
3
  var chalk = require('chalk');
4
4
  var node_fs = require('node:fs');
5
5
  var path = require('node:path');
6
- var index = require('./index-B8UoTir2.cjs');
7
- var persistence = require('./types-Dudpkl_i.cjs');
6
+ var index = require('./index-DUcWAKZ0.cjs');
7
+ var persistence = require('./types-DJGEti9c.cjs');
8
8
  require('node:os');
9
9
  require('node:crypto');
10
10
  require('cross-spawn');
@@ -29,7 +29,7 @@ import { SandboxManager } from '@anthropic-ai/sandbox-runtime';
29
29
  import { Expo } from 'expo-server-sdk';
30
30
 
31
31
  var name = "very-happy-cli";
32
- var version = "0.2.84";
32
+ var version = "0.2.85";
33
33
  var description = "Remote multi-agent workspace CLI with deep Claude integration, native terminal streaming, and self-hosting.";
34
34
  var author = "Kirill Dubovitskiy";
35
35
  var contributors = [
@@ -142,12 +142,12 @@ var dependencies = {
142
142
  zod: "^4.0.0"
143
143
  };
144
144
  var optionalDependencies = {
145
- "very-happy-tools-arm64-darwin": "0.2.84",
146
- "very-happy-tools-x64-darwin": "0.2.84",
147
- "very-happy-tools-arm64-linux": "0.2.84",
148
- "very-happy-tools-x64-linux": "0.2.84",
149
- "very-happy-tools-arm64-win32": "0.2.84",
150
- "very-happy-tools-x64-win32": "0.2.84"
145
+ "very-happy-tools-arm64-darwin": "0.2.85",
146
+ "very-happy-tools-x64-darwin": "0.2.85",
147
+ "very-happy-tools-arm64-linux": "0.2.85",
148
+ "very-happy-tools-x64-linux": "0.2.85",
149
+ "very-happy-tools-arm64-win32": "0.2.85",
150
+ "very-happy-tools-x64-win32": "0.2.85"
151
151
  };
152
152
  var devDependencies = {
153
153
  "@slopus/happy-wire": "workspace:*",
@@ -755,6 +755,8 @@ const MessageMetaSchema$1 = z.object({
755
755
  appendSystemPrompt: z.string().nullable().optional(),
756
756
  allowedTools: z.array(z.string()).nullable().optional(),
757
757
  disallowedTools: z.array(z.string()).nullable().optional(),
758
+ /** Omitted/queue waits for the current turn; steer targets the live turn. */
759
+ delivery: z.enum(["queue", "steer"]).optional(),
758
760
  displayText: z.string().optional()
759
761
  });
760
762
  const UserMessageSchema$1 = z.object({
@@ -1028,8 +1030,10 @@ const MessageMetaSchema = z$1.object({
1028
1030
  // Append to system prompt for this message (null = reset)
1029
1031
  allowedTools: z$1.array(z$1.string()).nullable().optional(),
1030
1032
  // Allowed tools for this message (null = reset)
1031
- disallowedTools: z$1.array(z$1.string()).nullable().optional()
1033
+ disallowedTools: z$1.array(z$1.string()).nullable().optional(),
1032
1034
  // Disallowed tools for this message (null = reset)
1035
+ /** Omitted/queue waits for the current turn; steer targets the live turn. */
1036
+ delivery: z$1.enum(["queue", "steer"]).optional()
1033
1037
  });
1034
1038
  z$1.object({
1035
1039
  session: z$1.object({
@@ -2645,7 +2649,7 @@ function mapClaudeLogMessageToSessionEnvelopesInternal(message, state) {
2645
2649
  }
2646
2650
  if (message.type === "result") {
2647
2651
  const raw = message;
2648
- const status = raw.is_error === true ? "failed" : "completed";
2652
+ const status = raw.interrupted === true ? "cancelled" : raw.is_error === true ? "failed" : "completed";
2649
2653
  const error = status === "failed" ? raw.errors?.filter((item) => typeof item === "string" && item.trim()).join("\n") || state.pendingAssistantError || raw.subtype || "Claude turn failed" : void 0;
2650
2654
  if (status === "failed" && !state.currentTurnId) {
2651
2655
  ensureTurn(state, envelopes);
@@ -51,7 +51,7 @@ var z__namespace = /*#__PURE__*/_interopNamespaceDefault(z);
51
51
  var pty__namespace = /*#__PURE__*/_interopNamespaceDefault(pty);
52
52
 
53
53
  var name = "very-happy-cli";
54
- var version = "0.2.84";
54
+ var version = "0.2.85";
55
55
  var description = "Remote multi-agent workspace CLI with deep Claude integration, native terminal streaming, and self-hosting.";
56
56
  var author = "Kirill Dubovitskiy";
57
57
  var contributors = [
@@ -164,12 +164,12 @@ var dependencies = {
164
164
  zod: "^4.0.0"
165
165
  };
166
166
  var optionalDependencies = {
167
- "very-happy-tools-arm64-darwin": "0.2.84",
168
- "very-happy-tools-x64-darwin": "0.2.84",
169
- "very-happy-tools-arm64-linux": "0.2.84",
170
- "very-happy-tools-x64-linux": "0.2.84",
171
- "very-happy-tools-arm64-win32": "0.2.84",
172
- "very-happy-tools-x64-win32": "0.2.84"
167
+ "very-happy-tools-arm64-darwin": "0.2.85",
168
+ "very-happy-tools-x64-darwin": "0.2.85",
169
+ "very-happy-tools-arm64-linux": "0.2.85",
170
+ "very-happy-tools-x64-linux": "0.2.85",
171
+ "very-happy-tools-arm64-win32": "0.2.85",
172
+ "very-happy-tools-x64-win32": "0.2.85"
173
173
  };
174
174
  var devDependencies = {
175
175
  "@slopus/happy-wire": "workspace:*",
@@ -777,6 +777,8 @@ const MessageMetaSchema$1 = z__namespace.object({
777
777
  appendSystemPrompt: z__namespace.string().nullable().optional(),
778
778
  allowedTools: z__namespace.array(z__namespace.string()).nullable().optional(),
779
779
  disallowedTools: z__namespace.array(z__namespace.string()).nullable().optional(),
780
+ /** Omitted/queue waits for the current turn; steer targets the live turn. */
781
+ delivery: z__namespace.enum(["queue", "steer"]).optional(),
780
782
  displayText: z__namespace.string().optional()
781
783
  });
782
784
  const UserMessageSchema$1 = z__namespace.object({
@@ -1050,8 +1052,10 @@ const MessageMetaSchema = z.z.object({
1050
1052
  // Append to system prompt for this message (null = reset)
1051
1053
  allowedTools: z.z.array(z.z.string()).nullable().optional(),
1052
1054
  // Allowed tools for this message (null = reset)
1053
- disallowedTools: z.z.array(z.z.string()).nullable().optional()
1055
+ disallowedTools: z.z.array(z.z.string()).nullable().optional(),
1054
1056
  // Disallowed tools for this message (null = reset)
1057
+ /** Omitted/queue waits for the current turn; steer targets the live turn. */
1058
+ delivery: z.z.enum(["queue", "steer"]).optional()
1055
1059
  });
1056
1060
  z.z.object({
1057
1061
  session: z.z.object({
@@ -1480,7 +1484,7 @@ class RpcHandlerManager {
1480
1484
  }
1481
1485
  }
1482
1486
 
1483
- const __dirname$1 = path$1.dirname(url.fileURLToPath((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('types-Dudpkl_i.cjs', document.baseURI).href))));
1487
+ const __dirname$1 = path$1.dirname(url.fileURLToPath((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('types-DJGEti9c.cjs', document.baseURI).href))));
1484
1488
  function projectPath() {
1485
1489
  const path = path$1.resolve(__dirname$1, "..");
1486
1490
  return path;
@@ -2667,7 +2671,7 @@ function mapClaudeLogMessageToSessionEnvelopesInternal(message, state) {
2667
2671
  }
2668
2672
  if (message.type === "result") {
2669
2673
  const raw = message;
2670
- const status = raw.is_error === true ? "failed" : "completed";
2674
+ const status = raw.interrupted === true ? "cancelled" : raw.is_error === true ? "failed" : "completed";
2671
2675
  const error = status === "failed" ? raw.errors?.filter((item) => typeof item === "string" && item.trim()).join("\n") || state.pendingAssistantError || raw.subtype || "Claude turn failed" : void 0;
2672
2676
  if (status === "failed" && !state.currentTurnId) {
2673
2677
  ensureTurn(state, envelopes);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "very-happy-cli",
3
- "version": "0.2.84",
3
+ "version": "0.2.85",
4
4
  "description": "Remote multi-agent workspace CLI with deep Claude integration, native terminal streaming, and self-hosting.",
5
5
  "author": "Kirill Dubovitskiy",
6
6
  "contributors": [
@@ -113,12 +113,12 @@
113
113
  "zod": "^4.0.0"
114
114
  },
115
115
  "optionalDependencies": {
116
- "very-happy-tools-arm64-darwin": "0.2.84",
117
- "very-happy-tools-x64-darwin": "0.2.84",
118
- "very-happy-tools-arm64-linux": "0.2.84",
119
- "very-happy-tools-x64-linux": "0.2.84",
120
- "very-happy-tools-arm64-win32": "0.2.84",
121
- "very-happy-tools-x64-win32": "0.2.84"
116
+ "very-happy-tools-arm64-darwin": "0.2.85",
117
+ "very-happy-tools-x64-darwin": "0.2.85",
118
+ "very-happy-tools-arm64-linux": "0.2.85",
119
+ "very-happy-tools-x64-linux": "0.2.85",
120
+ "very-happy-tools-arm64-win32": "0.2.85",
121
+ "very-happy-tools-x64-win32": "0.2.85"
122
122
  },
123
123
  "devDependencies": {
124
124
  "@slopus/happy-wire": "workspace:*",