very-happy-cli 0.2.80 → 0.2.82

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-DBJGqMwR.mjs → AcpBackend-DMLCBDru.mjs} +1 -1
  2. package/dist/{AcpBackend-_662AILI.cjs → AcpBackend-DjHJfd8y.cjs} +1 -1
  3. package/dist/{AcpSessionManager-ENIrbDWT.cjs → AcpSessionManager-Bd-LtS2E.cjs} +1 -1
  4. package/dist/{AcpSessionManager-DcWebwii.mjs → AcpSessionManager-xyImjcMI.mjs} +1 -1
  5. package/dist/{config-Dn4CC1I_.cjs → config-BjgfmsPT.cjs} +2 -2
  6. package/dist/{config-DHUFJkEr.mjs → config-DRjtWNd0.mjs} +2 -2
  7. package/dist/{index-D9OFwx0T.mjs → index-1ZE940yd.mjs} +5 -5
  8. package/dist/{index-CdmSlaUU.cjs → index-BTtTqsj4.cjs} +133 -51
  9. package/dist/{index-C9JZ3wyP.cjs → index-CR24hlKJ.cjs} +4 -4
  10. package/dist/{index-DoLyKWEW.mjs → index-DZ7tAffg.mjs} +130 -48
  11. package/dist/index.cjs +2 -2
  12. package/dist/index.mjs +2 -2
  13. package/dist/{installTerminalHooks-RgJOM2ds.cjs → installTerminalHooks-DSfE4ui6.cjs} +2 -2
  14. package/dist/{installTerminalHooks-D48YflmS.mjs → installTerminalHooks-Do3vnipG.mjs} +2 -2
  15. package/dist/lib.cjs +1 -1
  16. package/dist/lib.d.cts +4 -0
  17. package/dist/lib.d.mts +4 -0
  18. package/dist/lib.mjs +1 -1
  19. package/dist/{mcp-DnO0vHep.mjs → mcp-2Ee6mSAP.mjs} +2 -2
  20. package/dist/{mcp-CIJ6lM8-.cjs → mcp-CJHJEBto.cjs} +2 -2
  21. package/dist/{runGemini-Cnvz6a6J.mjs → runGemini-DQKPf1RX.mjs} +4 -4
  22. package/dist/{runGemini-CDko3vdP.cjs → runGemini-Dj7g2-B_.cjs} +4 -4
  23. package/dist/{runOpenClaw-Cpxdqf9Z.mjs → runOpenClaw-BNfz77EE.mjs} +3 -3
  24. package/dist/{runOpenClaw-Dk_FfroQ.cjs → runOpenClaw-BWAVwl3x.cjs} +3 -3
  25. package/dist/{send-DJWwqdS_.mjs → send-CIm5kZBx.mjs} +2 -2
  26. package/dist/{send-BavRmzTl.cjs → send-Cm28ijOj.cjs} +2 -2
  27. package/dist/{spawn-Bqrneceh.cjs → spawn-BPgkpGXX.cjs} +2 -2
  28. package/dist/{spawn-DWf78N7k.mjs → spawn-Dd8qj3l4.mjs} +2 -2
  29. package/dist/{types-DL98ZceN.cjs → types-B7qS_-8e.cjs} +24 -10
  30. package/dist/{types-B2DG32ua.mjs → types-C4duxyB7.mjs} +23 -9
  31. package/package.json +7 -7
@@ -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-B2DG32ua.mjs';
4
+ import { l as logger, d as contentLogMetadata, e as errorLogMetadata, f as packageJson, g as delay } from './types-C4duxyB7.mjs';
5
5
 
6
6
  const DEFAULT_TIMEOUTS = {
7
7
  /** Default initialization timeout: 60 seconds */
@@ -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-DL98ZceN.cjs');
6
+ var persistence = require('./types-B7qS_-8e.cjs');
7
7
 
8
8
  const DEFAULT_TIMEOUTS = {
9
9
  /** Default initialization timeout: 60 seconds */
@@ -1,7 +1,7 @@
1
1
  'use strict';
2
2
 
3
3
  var cuid2 = require('@paralleldrive/cuid2');
4
- var persistence = require('./types-DL98ZceN.cjs');
4
+ var persistence = require('./types-B7qS_-8e.cjs');
5
5
 
6
6
  function turnOptions(turnId, time) {
7
7
  return turnId ? { turn: turnId, time } : { time };
@@ -1,5 +1,5 @@
1
1
  import { createId } from '@paralleldrive/cuid2';
2
- import { b as createEnvelope } from './types-B2DG32ua.mjs';
2
+ import { b as createEnvelope } from './types-C4duxyB7.mjs';
3
3
 
4
4
  function turnOptions(turnId, time) {
5
5
  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-DL98ZceN.cjs');
8
- var index = require('./index-CdmSlaUU.cjs');
7
+ var persistence = require('./types-B7qS_-8e.cjs');
8
+ var index = require('./index-BTtTqsj4.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-B2DG32ua.mjs';
6
- import { D as DEFAULT_GEMINI_MODEL, G as GEMINI_MODEL_ENV } from './index-DoLyKWEW.mjs';
5
+ import { l as logger } from './types-C4duxyB7.mjs';
6
+ import { D as DEFAULT_GEMINI_MODEL, G as GEMINI_MODEL_ENV } from './index-DZ7tAffg.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-DBJGqMwR.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-DBJGqMwR.mjs';
3
- import { h as connectionState, A as ApiClient, i as readSettings, j as encodeBase64, l as logger, p as projectPath } from './types-B2DG32ua.mjs';
4
- import { A as AcpSessionManager } from './AcpSessionManager-DcWebwii.mjs';
1
+ import { D as DefaultTransport, A as AcpBackend } from './AcpBackend-DMLCBDru.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-DMLCBDru.mjs';
3
+ import { h as connectionState, A as ApiClient, i as readSettings, j as encodeBase64, l as logger, p as projectPath } from './types-C4duxyB7.mjs';
4
+ import { A as AcpSessionManager } from './AcpSessionManager-xyImjcMI.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-DoLyKWEW.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-DZ7tAffg.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-DL98ZceN.cjs');
6
+ var persistence = require('./types-B7qS_-8e.cjs');
7
7
  var spawn = require('cross-spawn');
8
8
  var path = require('node:path');
9
9
  var node_readline = require('node:readline');
@@ -1925,7 +1925,10 @@ async function claudeRemote(opts) {
1925
1925
  });
1926
1926
  if (opts.onQueryReady) {
1927
1927
  opts.onQueryReady({
1928
- setPermissionMode: (mode2) => response.setPermissionMode(mode2)
1928
+ setPermissionMode: (mode2) => response.setPermissionMode(mode2),
1929
+ interrupt: async () => {
1930
+ await response.interrupt();
1931
+ }
1929
1932
  });
1930
1933
  }
1931
1934
  updateThinking(true);
@@ -1943,7 +1946,9 @@ async function claudeRemote(opts) {
1943
1946
  tools: systemInit.tools,
1944
1947
  slashCommands: systemInit.slash_commands,
1945
1948
  mcpServers: systemInit.mcp_servers?.map((s) => ({ name: s.name, status: s.status })),
1946
- skills: systemInit.skills
1949
+ skills: systemInit.skills,
1950
+ model: systemInit.model,
1951
+ modelIsDefault: initial.mode.model == null
1947
1952
  });
1948
1953
  }
1949
1954
  if (systemInit.session_id) {
@@ -2999,6 +3004,91 @@ function applyClaudeResultLifecycle(result, callbacks) {
2999
3004
  callbacks.onCompleted();
3000
3005
  }
3001
3006
 
3007
+ const CLAUDE_ATTACHMENT_KINDS = [
3008
+ "image/jpeg",
3009
+ "image/png",
3010
+ "image/gif",
3011
+ "image/webp",
3012
+ "application/pdf"
3013
+ ];
3014
+ function detectClaudeImageMime(bytes) {
3015
+ if (bytes.length >= 4 && bytes[0] === 137 && bytes[1] === 80 && bytes[2] === 78 && bytes[3] === 71) {
3016
+ return "image/png";
3017
+ }
3018
+ if (bytes.length >= 3 && bytes[0] === 255 && bytes[1] === 216 && bytes[2] === 255) {
3019
+ return "image/jpeg";
3020
+ }
3021
+ if (bytes.length >= 4 && bytes[0] === 71 && bytes[1] === 73 && bytes[2] === 70 && bytes[3] === 56) {
3022
+ return "image/gif";
3023
+ }
3024
+ if (bytes.length >= 12 && bytes[0] === 82 && bytes[1] === 73 && bytes[2] === 70 && bytes[3] === 70 && bytes[8] === 87 && bytes[9] === 69 && bytes[10] === 66 && bytes[11] === 80) {
3025
+ return "image/webp";
3026
+ }
3027
+ return null;
3028
+ }
3029
+ function isPdf(bytes) {
3030
+ return bytes.length >= 5 && bytes[0] === 37 && bytes[1] === 80 && bytes[2] === 68 && bytes[3] === 70 && bytes[4] === 45;
3031
+ }
3032
+ function attachmentToClaudeContentBlock(bytes) {
3033
+ const data = Buffer.from(bytes).toString("base64");
3034
+ const imageMime = detectClaudeImageMime(bytes);
3035
+ if (imageMime) {
3036
+ return {
3037
+ type: "image",
3038
+ source: { type: "base64", media_type: imageMime, data }
3039
+ };
3040
+ }
3041
+ if (isPdf(bytes)) {
3042
+ return {
3043
+ type: "document",
3044
+ source: { type: "base64", media_type: "application/pdf", data }
3045
+ };
3046
+ }
3047
+ return null;
3048
+ }
3049
+
3050
+ function applyClaudeSdkMetadata(current, update) {
3051
+ return {
3052
+ ...current,
3053
+ tools: update.tools,
3054
+ slashCommands: update.slashCommands,
3055
+ mcpServers: update.mcpServers,
3056
+ skills: update.skills,
3057
+ attachmentKinds: [...CLAUDE_ATTACHMENT_KINDS],
3058
+ ...update.modelIsDefault && update.model ? { defaultModelCode: update.model } : {}
3059
+ };
3060
+ }
3061
+
3062
+ function createTurnSteeringController() {
3063
+ let interrupt = null;
3064
+ let steering = false;
3065
+ return {
3066
+ setInterrupt(next) {
3067
+ interrupt = next;
3068
+ },
3069
+ async steer() {
3070
+ if (!interrupt) return false;
3071
+ steering = true;
3072
+ try {
3073
+ await interrupt();
3074
+ return true;
3075
+ } catch (error) {
3076
+ steering = false;
3077
+ throw error;
3078
+ }
3079
+ },
3080
+ consumeReady() {
3081
+ if (!steering) return false;
3082
+ steering = false;
3083
+ return true;
3084
+ },
3085
+ reset() {
3086
+ interrupt = null;
3087
+ steering = false;
3088
+ }
3089
+ };
3090
+ }
3091
+
3002
3092
  async function claudeRemoteLauncher(session) {
3003
3093
  persistence.logger.debug("[claudeRemoteLauncher] Starting remote launcher");
3004
3094
  const hasTTY = process.stdout.isTTY && process.stdin.isTTY;
@@ -3036,6 +3126,7 @@ async function claudeRemoteLauncher(session) {
3036
3126
  let exitReason = null;
3037
3127
  let abortController = null;
3038
3128
  let abortFuture = null;
3129
+ const turnSteering = createTurnSteeringController();
3039
3130
  async function abort() {
3040
3131
  if (abortController && !abortController.signal.aborted) {
3041
3132
  abortController.abort();
@@ -3055,6 +3146,9 @@ async function claudeRemoteLauncher(session) {
3055
3146
  await abort();
3056
3147
  }
3057
3148
  session.client.rpcHandlerManager.registerHandler("abort", doAbort);
3149
+ session.client.rpcHandlerManager.registerHandler("steer", async () => {
3150
+ await turnSteering.steer();
3151
+ });
3058
3152
  session.client.rpcHandlerManager.registerHandler("switch", doSwitch);
3059
3153
  const permissionHandler = new PermissionHandler(session);
3060
3154
  permissionHandler.reset("Previous CLI process exited before responding");
@@ -3236,23 +3330,23 @@ async function claudeRemoteLauncher(session) {
3236
3330
  const attachments = msg.attachments ?? [];
3237
3331
  if (attachments.length > 0) {
3238
3332
  const contentBlocks = [];
3333
+ let acceptedAttachments = 0;
3239
3334
  for (const att of attachments) {
3240
- const detected = detectClaudeImageMime(att.data);
3241
- if (!detected) {
3335
+ const block = attachmentToClaudeContentBlock(att.data);
3336
+ if (!block) {
3242
3337
  persistence.logger.debug(`[remote] Skipping unsupported attachment (no magic-byte match): ${att.name}, claimed mimeType=${att.mimeType}`);
3243
3338
  continue;
3244
3339
  }
3245
- contentBlocks.push({
3246
- type: "image",
3247
- source: {
3248
- type: "base64",
3249
- media_type: detected,
3250
- data: Buffer.from(att.data).toString("base64")
3251
- }
3252
- });
3340
+ contentBlocks.push(block);
3341
+ acceptedAttachments++;
3253
3342
  }
3254
- contentBlocks.push({ type: "text", text: msg.message });
3255
- persistence.logger.debug(`[remote] Combined ${contentBlocks.length - 1} image(s) with text message`);
3343
+ if (msg.message.trim().length > 0) {
3344
+ contentBlocks.push({ type: "text", text: msg.message });
3345
+ }
3346
+ if (contentBlocks.length === 0) {
3347
+ throw new Error("No supported attachment content was available to send");
3348
+ }
3349
+ persistence.logger.debug(`[remote] Combined ${acceptedAttachments} attachment(s) with${msg.message.trim() ? "" : "out"} text message`);
3256
3350
  return {
3257
3351
  message: contentBlocks,
3258
3352
  mode: msg.mode
@@ -3276,15 +3370,10 @@ async function claudeRemoteLauncher(session) {
3276
3370
  mcpServerCount: metadata.mcpServers?.length ?? 0,
3277
3371
  skillCount: metadata.skills?.length ?? 0
3278
3372
  });
3279
- session.client.updateMetadata((currentMetadata) => ({
3280
- ...currentMetadata,
3281
- tools: metadata.tools,
3282
- slashCommands: metadata.slashCommands,
3283
- mcpServers: metadata.mcpServers,
3284
- skills: metadata.skills
3285
- }));
3373
+ session.client.updateMetadata((currentMetadata) => applyClaudeSdkMetadata(currentMetadata, metadata));
3286
3374
  },
3287
3375
  onQueryReady: (q) => {
3376
+ turnSteering.setInterrupt(q.interrupt);
3288
3377
  permissionHandler.setPermissionModeUpdater(async (mode2) => {
3289
3378
  await q.setPermissionMode(mode2);
3290
3379
  });
@@ -3302,6 +3391,10 @@ async function claudeRemoteLauncher(session) {
3302
3391
  session.clearSessionId();
3303
3392
  },
3304
3393
  onReady: (result) => {
3394
+ if (turnSteering.consumeReady()) {
3395
+ session.client.closeClaudeSessionTurn("cancelled");
3396
+ return;
3397
+ }
3305
3398
  applyClaudeResultLifecycle(result, {
3306
3399
  closeCompleted: () => session.client.closeClaudeSessionTurn("completed"),
3307
3400
  closeFailed: (error) => session.client.closeClaudeSessionTurn("failed", { error }),
@@ -3339,6 +3432,7 @@ async function claudeRemoteLauncher(session) {
3339
3432
  continue;
3340
3433
  }
3341
3434
  } finally {
3435
+ turnSteering.reset();
3342
3436
  persistence.logger.debug("[remote]: launch finally");
3343
3437
  for (let [toolCallId, { parentToolCallId }] of ongoingToolCalls) {
3344
3438
  const converted = sdkToLogConverter.generateInterruptedToolResult(toolCallId, parentToolCallId);
@@ -3384,21 +3478,6 @@ async function claudeRemoteLauncher(session) {
3384
3478
  }
3385
3479
  return exitReason || "exit";
3386
3480
  }
3387
- function detectClaudeImageMime(bytes) {
3388
- if (bytes.length >= 4 && bytes[0] === 137 && bytes[1] === 80 && bytes[2] === 78 && bytes[3] === 71) {
3389
- return "image/png";
3390
- }
3391
- if (bytes.length >= 3 && bytes[0] === 255 && bytes[1] === 216 && bytes[2] === 255) {
3392
- return "image/jpeg";
3393
- }
3394
- if (bytes.length >= 4 && bytes[0] === 71 && bytes[1] === 73 && bytes[2] === 70 && bytes[3] === 56) {
3395
- return "image/gif";
3396
- }
3397
- if (bytes.length >= 12 && bytes[0] === 82 && bytes[1] === 73 && bytes[2] === 70 && bytes[3] === 70 && bytes[8] === 87 && bytes[9] === 69 && bytes[10] === 66 && bytes[11] === 80) {
3398
- return "image/webp";
3399
- }
3400
- return null;
3401
- }
3402
3481
 
3403
3482
  async function loop(opts) {
3404
3483
  const logPath = persistence.logger.logFilePath;
@@ -8453,7 +8532,7 @@ const MAX_TITLE_CHARS = 60;
8453
8532
  const GENERATION_TIMEOUT_MS = 3e4;
8454
8533
  function resolveClaudeBinary() {
8455
8534
  try {
8456
- 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-CdmSlaUU.cjs', document.baseURI).href)));
8535
+ 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-BTtTqsj4.cjs', document.baseURI).href)));
8457
8536
  const utilsPath = path.resolve(path.join(persistence.projectPath(), "scripts", "claude_version_utils.cjs"));
8458
8537
  const { getClaudeCliPath } = require$1(utilsPath);
8459
8538
  const path$1 = getClaudeCliPath();
@@ -8906,6 +8985,9 @@ async function runClaude(credentials, options = {}) {
8906
8985
  lifecycleState: "running",
8907
8986
  lifecycleStateSince: Date.now(),
8908
8987
  flavor: "claude",
8988
+ // Advertise composer support before the first SDK response. Otherwise
8989
+ // a brand-new session cannot pick a PDF until after sending once.
8990
+ attachmentKinds: [...CLAUDE_ATTACHMENT_KINDS],
8909
8991
  sandbox: sandboxConfig?.enabled ? sandboxConfig : null,
8910
8992
  dangerouslySkipPermissions,
8911
8993
  ...forkedFromSessionId ? { parentSessionId: forkedFromSessionId } : {},
@@ -10570,9 +10652,9 @@ function resolveLocalSignupBootstrap(configuredMode, configuredInviteCodes, gene
10570
10652
  };
10571
10653
  }
10572
10654
 
10573
- 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-CdmSlaUU.cjs', document.baseURI).href)));
10655
+ 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-BTtTqsj4.cjs', document.baseURI).href)));
10574
10656
  const __dirname$1 = path.dirname(__filename$1);
10575
- const require_ = node_module.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index-CdmSlaUU.cjs', document.baseURI).href)));
10657
+ const require_ = node_module.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index-BTtTqsj4.cjs', document.baseURI).href)));
10576
10658
  const PRISMA_QUERY_ENGINE_FILES = {
10577
10659
  "arm64-darwin": "libquery_engine-darwin-arm64.dylib.node",
10578
10660
  "x64-darwin": "libquery_engine-darwin.dylib.node",
@@ -13184,7 +13266,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
13184
13266
  process.exit(0);
13185
13267
  } else if (subcommand === "install-terminal-hooks") {
13186
13268
  try {
13187
- const { installTerminalHooks, parseTerminalHooksArgs, TERMINAL_HOOKS_HELP } = await Promise.resolve().then(function () { return require('./installTerminalHooks-RgJOM2ds.cjs'); });
13269
+ const { installTerminalHooks, parseTerminalHooksArgs, TERMINAL_HOOKS_HELP } = await Promise.resolve().then(function () { return require('./installTerminalHooks-DSfE4ui6.cjs'); });
13188
13270
  const command = parseTerminalHooksArgs(args.slice(1));
13189
13271
  if (command.action === "help") {
13190
13272
  console.log(TERMINAL_HOOKS_HELP);
@@ -13201,7 +13283,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
13201
13283
  }
13202
13284
  } else if (subcommand === "spawn") {
13203
13285
  try {
13204
- const { handleSpawnCommand } = await Promise.resolve().then(function () { return require('./spawn-Bqrneceh.cjs'); });
13286
+ const { handleSpawnCommand } = await Promise.resolve().then(function () { return require('./spawn-BPgkpGXX.cjs'); });
13205
13287
  await handleSpawnCommand(args.slice(1));
13206
13288
  } catch (error) {
13207
13289
  console.error(chalk.red("Error:"), error instanceof Error ? error.message : "Unknown error");
@@ -13213,7 +13295,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
13213
13295
  return;
13214
13296
  } else if (subcommand === "send") {
13215
13297
  try {
13216
- const { handleSendCommand } = await Promise.resolve().then(function () { return require('./send-BavRmzTl.cjs'); });
13298
+ const { handleSendCommand } = await Promise.resolve().then(function () { return require('./send-Cm28ijOj.cjs'); });
13217
13299
  await handleSendCommand(args.slice(1));
13218
13300
  } catch (error) {
13219
13301
  console.error(chalk.red("Error:"), error instanceof Error ? error.message : "Unknown error");
@@ -13319,9 +13401,9 @@ Conversation history is preserved on the server, but in-flight tool calls are in
13319
13401
  if (geminiSubcommand === "project" && args[2] === "set" && args[3]) {
13320
13402
  const projectId = args[3];
13321
13403
  try {
13322
- const { saveGoogleCloudProjectToConfig } = await Promise.resolve().then(function () { return require('./config-Dn4CC1I_.cjs'); });
13323
- const { readCredentialsForConfiguredRelay: readCredentialsForConfiguredRelay2 } = await Promise.resolve().then(function () { return require('./types-DL98ZceN.cjs'); }).then(function (n) { return n.persistence; });
13324
- const { ApiClient: ApiClient2 } = await Promise.resolve().then(function () { return require('./types-DL98ZceN.cjs'); }).then(function (n) { return n.api; });
13404
+ const { saveGoogleCloudProjectToConfig } = await Promise.resolve().then(function () { return require('./config-BjgfmsPT.cjs'); });
13405
+ const { readCredentialsForConfiguredRelay: readCredentialsForConfiguredRelay2 } = await Promise.resolve().then(function () { return require('./types-B7qS_-8e.cjs'); }).then(function (n) { return n.persistence; });
13406
+ const { ApiClient: ApiClient2 } = await Promise.resolve().then(function () { return require('./types-B7qS_-8e.cjs'); }).then(function (n) { return n.api; });
13325
13407
  let userEmail = void 0;
13326
13408
  try {
13327
13409
  const credentials = await readCredentialsForConfiguredRelay2();
@@ -13352,7 +13434,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
13352
13434
  }
13353
13435
  if (geminiSubcommand === "project" && args[2] === "get") {
13354
13436
  try {
13355
- const { readGeminiLocalConfig } = await Promise.resolve().then(function () { return require('./config-Dn4CC1I_.cjs'); });
13437
+ const { readGeminiLocalConfig } = await Promise.resolve().then(function () { return require('./config-BjgfmsPT.cjs'); });
13356
13438
  const config = readGeminiLocalConfig();
13357
13439
  if (config.googleCloudProject) {
13358
13440
  console.log(`Current Google Cloud Project: ${config.googleCloudProject}`);
@@ -13392,7 +13474,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
13392
13474
  process.exit(0);
13393
13475
  }
13394
13476
  try {
13395
- const { runGemini } = await Promise.resolve().then(function () { return require('./runGemini-CDko3vdP.cjs'); });
13477
+ const { runGemini } = await Promise.resolve().then(function () { return require('./runGemini-Dj7g2-B_.cjs'); });
13396
13478
  let startedBy = void 0;
13397
13479
  for (let i = 1; i < args.length; i++) {
13398
13480
  if (args[i] === "--started-by") {
@@ -13414,7 +13496,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
13414
13496
  return;
13415
13497
  } else if (subcommand === "acp") {
13416
13498
  try {
13417
- const { runAcp, resolveAcpAgentConfig } = await Promise.resolve().then(function () { return require('./index-C9JZ3wyP.cjs'); });
13499
+ const { runAcp, resolveAcpAgentConfig } = await Promise.resolve().then(function () { return require('./index-CR24hlKJ.cjs'); });
13418
13500
  let startedBy = void 0;
13419
13501
  let verbose = false;
13420
13502
  const acpArgs = [];
@@ -13454,7 +13536,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
13454
13536
  return;
13455
13537
  } else if (subcommand === "openclaw") {
13456
13538
  try {
13457
- const { runOpenClaw } = await Promise.resolve().then(function () { return require('./runOpenClaw-Dk_FfroQ.cjs'); });
13539
+ const { runOpenClaw } = await Promise.resolve().then(function () { return require('./runOpenClaw-BWAVwl3x.cjs'); });
13458
13540
  let startedBy = void 0;
13459
13541
  let verbose = false;
13460
13542
  let gatewayUrl;
@@ -13505,7 +13587,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
13505
13587
  return;
13506
13588
  } else if (subcommand === "mcp" && args.length === 1) {
13507
13589
  try {
13508
- const { handleMcpCommand } = await Promise.resolve().then(function () { return require('./mcp-CIJ6lM8-.cjs'); });
13590
+ const { handleMcpCommand } = await Promise.resolve().then(function () { return require('./mcp-CJHJEBto.cjs'); });
13509
13591
  await handleMcpCommand();
13510
13592
  } catch (error) {
13511
13593
  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-_662AILI.cjs');
4
- var persistence = require('./types-DL98ZceN.cjs');
5
- var AcpSessionManager = require('./AcpSessionManager-ENIrbDWT.cjs');
3
+ var AcpBackend = require('./AcpBackend-DjHJfd8y.cjs');
4
+ var persistence = require('./types-B7qS_-8e.cjs');
5
+ var AcpSessionManager = require('./AcpSessionManager-Bd-LtS2E.cjs');
6
6
  var node_crypto = require('node:crypto');
7
7
  var path = require('node:path');
8
- var index = require('./index-CdmSlaUU.cjs');
8
+ var index = require('./index-BTtTqsj4.cjs');
9
9
  require('node:child_process');
10
10
  require('@agentclientprotocol/sdk');
11
11
  require('axios');
@@ -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, f as packageJson, i as readSettings, v as readCredentials, x as credentialRelayProblem, y as deriveLocalCliUpdateSummary, j as encodeBase64, z as updateSettings, B as encodeBase64Url, C as decodeBase64, D as writeCredentialsLegacy, E as writeCredentialsDataKey, F as readCredentialsForConfiguredRelay, G as encrypt, r as readPersistedSessions, H as getLocalHappyAgentCredentialPath, J as readLocalHappyAgentCredentials, K as decryptWithDataKey, L as decryptLegacy, M as extractCompleteLines, N as decideBackfill, O as parseTerminalHookPayload, P as decideMirrorBinding, Q as persistSession, S as MIRROR_BACKFILL_LINES_DEFAULT, T as mirrorLineKey, U as mirrorLocalId, V as detectResumeSupport, W as detectCLIAvailability, X as acquireDaemonLock, Y as summarizeSpawnSessionForLog, Z as deletePersistedSessions, _ as decrypt, $ as writeDaemonState, A as ApiClient, a0 as fetchCliUpdateState, a1 as resolveCliUpdateCheckInterval, a2 as DEFAULT_CLI_UPDATE_CHECK_INTERVAL_MS, a3 as releaseDaemonLock, a4 as isValidSessionId, a5 as listVhTerminals, a6 as isValidTerminalId, a7 as readVhTerminal, a8 as sendToVhTerminal, h as connectionState, a9 as startOfflineReconnection, aa as clearCredentials, ab as clearMachineId, k as ensurePrivateDirectorySync, w as writePrivateFileSync, ac as SandboxConfigSchema, b as createEnvelope, ad as CodexAppServerClient, ae as getLatestDaemonLog } from './types-B2DG32ua.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, f as packageJson, i as readSettings, v as readCredentials, x as credentialRelayProblem, y as deriveLocalCliUpdateSummary, j as encodeBase64, z as updateSettings, B as encodeBase64Url, C as decodeBase64, D as writeCredentialsLegacy, E as writeCredentialsDataKey, F as readCredentialsForConfiguredRelay, G as encrypt, r as readPersistedSessions, H as getLocalHappyAgentCredentialPath, J as readLocalHappyAgentCredentials, K as decryptWithDataKey, L as decryptLegacy, M as extractCompleteLines, N as decideBackfill, O as parseTerminalHookPayload, P as decideMirrorBinding, Q as persistSession, S as MIRROR_BACKFILL_LINES_DEFAULT, T as mirrorLineKey, U as mirrorLocalId, V as detectResumeSupport, W as detectCLIAvailability, X as acquireDaemonLock, Y as summarizeSpawnSessionForLog, Z as deletePersistedSessions, _ as decrypt, $ as writeDaemonState, A as ApiClient, a0 as fetchCliUpdateState, a1 as resolveCliUpdateCheckInterval, a2 as DEFAULT_CLI_UPDATE_CHECK_INTERVAL_MS, a3 as releaseDaemonLock, a4 as isValidSessionId, a5 as listVhTerminals, a6 as isValidTerminalId, a7 as readVhTerminal, a8 as sendToVhTerminal, h as connectionState, a9 as startOfflineReconnection, aa as clearCredentials, ab as clearMachineId, k as ensurePrivateDirectorySync, w as writePrivateFileSync, ac as SandboxConfigSchema, b as createEnvelope, ad as CodexAppServerClient, ae as getLatestDaemonLog } from './types-C4duxyB7.mjs';
5
5
  import spawn$1, { spawn } from 'cross-spawn';
6
6
  import path, { join, resolve, isAbsolute, normalize, sep, dirname } from 'node:path';
7
7
  import { createInterface } from 'node:readline';
@@ -1903,7 +1903,10 @@ async function claudeRemote(opts) {
1903
1903
  });
1904
1904
  if (opts.onQueryReady) {
1905
1905
  opts.onQueryReady({
1906
- setPermissionMode: (mode2) => response.setPermissionMode(mode2)
1906
+ setPermissionMode: (mode2) => response.setPermissionMode(mode2),
1907
+ interrupt: async () => {
1908
+ await response.interrupt();
1909
+ }
1907
1910
  });
1908
1911
  }
1909
1912
  updateThinking(true);
@@ -1921,7 +1924,9 @@ async function claudeRemote(opts) {
1921
1924
  tools: systemInit.tools,
1922
1925
  slashCommands: systemInit.slash_commands,
1923
1926
  mcpServers: systemInit.mcp_servers?.map((s) => ({ name: s.name, status: s.status })),
1924
- skills: systemInit.skills
1927
+ skills: systemInit.skills,
1928
+ model: systemInit.model,
1929
+ modelIsDefault: initial.mode.model == null
1925
1930
  });
1926
1931
  }
1927
1932
  if (systemInit.session_id) {
@@ -2977,6 +2982,91 @@ function applyClaudeResultLifecycle(result, callbacks) {
2977
2982
  callbacks.onCompleted();
2978
2983
  }
2979
2984
 
2985
+ const CLAUDE_ATTACHMENT_KINDS = [
2986
+ "image/jpeg",
2987
+ "image/png",
2988
+ "image/gif",
2989
+ "image/webp",
2990
+ "application/pdf"
2991
+ ];
2992
+ function detectClaudeImageMime(bytes) {
2993
+ if (bytes.length >= 4 && bytes[0] === 137 && bytes[1] === 80 && bytes[2] === 78 && bytes[3] === 71) {
2994
+ return "image/png";
2995
+ }
2996
+ if (bytes.length >= 3 && bytes[0] === 255 && bytes[1] === 216 && bytes[2] === 255) {
2997
+ return "image/jpeg";
2998
+ }
2999
+ if (bytes.length >= 4 && bytes[0] === 71 && bytes[1] === 73 && bytes[2] === 70 && bytes[3] === 56) {
3000
+ return "image/gif";
3001
+ }
3002
+ if (bytes.length >= 12 && bytes[0] === 82 && bytes[1] === 73 && bytes[2] === 70 && bytes[3] === 70 && bytes[8] === 87 && bytes[9] === 69 && bytes[10] === 66 && bytes[11] === 80) {
3003
+ return "image/webp";
3004
+ }
3005
+ return null;
3006
+ }
3007
+ function isPdf(bytes) {
3008
+ return bytes.length >= 5 && bytes[0] === 37 && bytes[1] === 80 && bytes[2] === 68 && bytes[3] === 70 && bytes[4] === 45;
3009
+ }
3010
+ function attachmentToClaudeContentBlock(bytes) {
3011
+ const data = Buffer.from(bytes).toString("base64");
3012
+ const imageMime = detectClaudeImageMime(bytes);
3013
+ if (imageMime) {
3014
+ return {
3015
+ type: "image",
3016
+ source: { type: "base64", media_type: imageMime, data }
3017
+ };
3018
+ }
3019
+ if (isPdf(bytes)) {
3020
+ return {
3021
+ type: "document",
3022
+ source: { type: "base64", media_type: "application/pdf", data }
3023
+ };
3024
+ }
3025
+ return null;
3026
+ }
3027
+
3028
+ function applyClaudeSdkMetadata(current, update) {
3029
+ return {
3030
+ ...current,
3031
+ tools: update.tools,
3032
+ slashCommands: update.slashCommands,
3033
+ mcpServers: update.mcpServers,
3034
+ skills: update.skills,
3035
+ attachmentKinds: [...CLAUDE_ATTACHMENT_KINDS],
3036
+ ...update.modelIsDefault && update.model ? { defaultModelCode: update.model } : {}
3037
+ };
3038
+ }
3039
+
3040
+ function createTurnSteeringController() {
3041
+ let interrupt = null;
3042
+ let steering = false;
3043
+ return {
3044
+ setInterrupt(next) {
3045
+ interrupt = next;
3046
+ },
3047
+ async steer() {
3048
+ if (!interrupt) return false;
3049
+ steering = true;
3050
+ try {
3051
+ await interrupt();
3052
+ return true;
3053
+ } catch (error) {
3054
+ steering = false;
3055
+ throw error;
3056
+ }
3057
+ },
3058
+ consumeReady() {
3059
+ if (!steering) return false;
3060
+ steering = false;
3061
+ return true;
3062
+ },
3063
+ reset() {
3064
+ interrupt = null;
3065
+ steering = false;
3066
+ }
3067
+ };
3068
+ }
3069
+
2980
3070
  async function claudeRemoteLauncher(session) {
2981
3071
  logger.debug("[claudeRemoteLauncher] Starting remote launcher");
2982
3072
  const hasTTY = process.stdout.isTTY && process.stdin.isTTY;
@@ -3014,6 +3104,7 @@ async function claudeRemoteLauncher(session) {
3014
3104
  let exitReason = null;
3015
3105
  let abortController = null;
3016
3106
  let abortFuture = null;
3107
+ const turnSteering = createTurnSteeringController();
3017
3108
  async function abort() {
3018
3109
  if (abortController && !abortController.signal.aborted) {
3019
3110
  abortController.abort();
@@ -3033,6 +3124,9 @@ async function claudeRemoteLauncher(session) {
3033
3124
  await abort();
3034
3125
  }
3035
3126
  session.client.rpcHandlerManager.registerHandler("abort", doAbort);
3127
+ session.client.rpcHandlerManager.registerHandler("steer", async () => {
3128
+ await turnSteering.steer();
3129
+ });
3036
3130
  session.client.rpcHandlerManager.registerHandler("switch", doSwitch);
3037
3131
  const permissionHandler = new PermissionHandler(session);
3038
3132
  permissionHandler.reset("Previous CLI process exited before responding");
@@ -3214,23 +3308,23 @@ async function claudeRemoteLauncher(session) {
3214
3308
  const attachments = msg.attachments ?? [];
3215
3309
  if (attachments.length > 0) {
3216
3310
  const contentBlocks = [];
3311
+ let acceptedAttachments = 0;
3217
3312
  for (const att of attachments) {
3218
- const detected = detectClaudeImageMime(att.data);
3219
- if (!detected) {
3313
+ const block = attachmentToClaudeContentBlock(att.data);
3314
+ if (!block) {
3220
3315
  logger.debug(`[remote] Skipping unsupported attachment (no magic-byte match): ${att.name}, claimed mimeType=${att.mimeType}`);
3221
3316
  continue;
3222
3317
  }
3223
- contentBlocks.push({
3224
- type: "image",
3225
- source: {
3226
- type: "base64",
3227
- media_type: detected,
3228
- data: Buffer.from(att.data).toString("base64")
3229
- }
3230
- });
3318
+ contentBlocks.push(block);
3319
+ acceptedAttachments++;
3231
3320
  }
3232
- contentBlocks.push({ type: "text", text: msg.message });
3233
- logger.debug(`[remote] Combined ${contentBlocks.length - 1} image(s) with text message`);
3321
+ if (msg.message.trim().length > 0) {
3322
+ contentBlocks.push({ type: "text", text: msg.message });
3323
+ }
3324
+ if (contentBlocks.length === 0) {
3325
+ throw new Error("No supported attachment content was available to send");
3326
+ }
3327
+ logger.debug(`[remote] Combined ${acceptedAttachments} attachment(s) with${msg.message.trim() ? "" : "out"} text message`);
3234
3328
  return {
3235
3329
  message: contentBlocks,
3236
3330
  mode: msg.mode
@@ -3254,15 +3348,10 @@ async function claudeRemoteLauncher(session) {
3254
3348
  mcpServerCount: metadata.mcpServers?.length ?? 0,
3255
3349
  skillCount: metadata.skills?.length ?? 0
3256
3350
  });
3257
- session.client.updateMetadata((currentMetadata) => ({
3258
- ...currentMetadata,
3259
- tools: metadata.tools,
3260
- slashCommands: metadata.slashCommands,
3261
- mcpServers: metadata.mcpServers,
3262
- skills: metadata.skills
3263
- }));
3351
+ session.client.updateMetadata((currentMetadata) => applyClaudeSdkMetadata(currentMetadata, metadata));
3264
3352
  },
3265
3353
  onQueryReady: (q) => {
3354
+ turnSteering.setInterrupt(q.interrupt);
3266
3355
  permissionHandler.setPermissionModeUpdater(async (mode2) => {
3267
3356
  await q.setPermissionMode(mode2);
3268
3357
  });
@@ -3280,6 +3369,10 @@ async function claudeRemoteLauncher(session) {
3280
3369
  session.clearSessionId();
3281
3370
  },
3282
3371
  onReady: (result) => {
3372
+ if (turnSteering.consumeReady()) {
3373
+ session.client.closeClaudeSessionTurn("cancelled");
3374
+ return;
3375
+ }
3283
3376
  applyClaudeResultLifecycle(result, {
3284
3377
  closeCompleted: () => session.client.closeClaudeSessionTurn("completed"),
3285
3378
  closeFailed: (error) => session.client.closeClaudeSessionTurn("failed", { error }),
@@ -3317,6 +3410,7 @@ async function claudeRemoteLauncher(session) {
3317
3410
  continue;
3318
3411
  }
3319
3412
  } finally {
3413
+ turnSteering.reset();
3320
3414
  logger.debug("[remote]: launch finally");
3321
3415
  for (let [toolCallId, { parentToolCallId }] of ongoingToolCalls) {
3322
3416
  const converted = sdkToLogConverter.generateInterruptedToolResult(toolCallId, parentToolCallId);
@@ -3362,21 +3456,6 @@ async function claudeRemoteLauncher(session) {
3362
3456
  }
3363
3457
  return exitReason || "exit";
3364
3458
  }
3365
- function detectClaudeImageMime(bytes) {
3366
- if (bytes.length >= 4 && bytes[0] === 137 && bytes[1] === 80 && bytes[2] === 78 && bytes[3] === 71) {
3367
- return "image/png";
3368
- }
3369
- if (bytes.length >= 3 && bytes[0] === 255 && bytes[1] === 216 && bytes[2] === 255) {
3370
- return "image/jpeg";
3371
- }
3372
- if (bytes.length >= 4 && bytes[0] === 71 && bytes[1] === 73 && bytes[2] === 70 && bytes[3] === 56) {
3373
- return "image/gif";
3374
- }
3375
- if (bytes.length >= 12 && bytes[0] === 82 && bytes[1] === 73 && bytes[2] === 70 && bytes[3] === 70 && bytes[8] === 87 && bytes[9] === 69 && bytes[10] === 66 && bytes[11] === 80) {
3376
- return "image/webp";
3377
- }
3378
- return null;
3379
- }
3380
3459
 
3381
3460
  async function loop(opts) {
3382
3461
  const logPath = logger.logFilePath;
@@ -8884,6 +8963,9 @@ async function runClaude(credentials, options = {}) {
8884
8963
  lifecycleState: "running",
8885
8964
  lifecycleStateSince: Date.now(),
8886
8965
  flavor: "claude",
8966
+ // Advertise composer support before the first SDK response. Otherwise
8967
+ // a brand-new session cannot pick a PDF until after sending once.
8968
+ attachmentKinds: [...CLAUDE_ATTACHMENT_KINDS],
8887
8969
  sandbox: sandboxConfig?.enabled ? sandboxConfig : null,
8888
8970
  dangerouslySkipPermissions,
8889
8971
  ...forkedFromSessionId ? { parentSessionId: forkedFromSessionId } : {},
@@ -13162,7 +13244,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
13162
13244
  process.exit(0);
13163
13245
  } else if (subcommand === "install-terminal-hooks") {
13164
13246
  try {
13165
- const { installTerminalHooks, parseTerminalHooksArgs, TERMINAL_HOOKS_HELP } = await import('./installTerminalHooks-D48YflmS.mjs');
13247
+ const { installTerminalHooks, parseTerminalHooksArgs, TERMINAL_HOOKS_HELP } = await import('./installTerminalHooks-Do3vnipG.mjs');
13166
13248
  const command = parseTerminalHooksArgs(args.slice(1));
13167
13249
  if (command.action === "help") {
13168
13250
  console.log(TERMINAL_HOOKS_HELP);
@@ -13179,7 +13261,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
13179
13261
  }
13180
13262
  } else if (subcommand === "spawn") {
13181
13263
  try {
13182
- const { handleSpawnCommand } = await import('./spawn-DWf78N7k.mjs');
13264
+ const { handleSpawnCommand } = await import('./spawn-Dd8qj3l4.mjs');
13183
13265
  await handleSpawnCommand(args.slice(1));
13184
13266
  } catch (error) {
13185
13267
  console.error(chalk.red("Error:"), error instanceof Error ? error.message : "Unknown error");
@@ -13191,7 +13273,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
13191
13273
  return;
13192
13274
  } else if (subcommand === "send") {
13193
13275
  try {
13194
- const { handleSendCommand } = await import('./send-DJWwqdS_.mjs');
13276
+ const { handleSendCommand } = await import('./send-CIm5kZBx.mjs');
13195
13277
  await handleSendCommand(args.slice(1));
13196
13278
  } catch (error) {
13197
13279
  console.error(chalk.red("Error:"), error instanceof Error ? error.message : "Unknown error");
@@ -13297,9 +13379,9 @@ Conversation history is preserved on the server, but in-flight tool calls are in
13297
13379
  if (geminiSubcommand === "project" && args[2] === "set" && args[3]) {
13298
13380
  const projectId = args[3];
13299
13381
  try {
13300
- const { saveGoogleCloudProjectToConfig } = await import('./config-DHUFJkEr.mjs');
13301
- const { readCredentialsForConfiguredRelay: readCredentialsForConfiguredRelay2 } = await import('./types-B2DG32ua.mjs').then(function (n) { return n.af; });
13302
- const { ApiClient: ApiClient2 } = await import('./types-B2DG32ua.mjs').then(function (n) { return n.ag; });
13382
+ const { saveGoogleCloudProjectToConfig } = await import('./config-DRjtWNd0.mjs');
13383
+ const { readCredentialsForConfiguredRelay: readCredentialsForConfiguredRelay2 } = await import('./types-C4duxyB7.mjs').then(function (n) { return n.af; });
13384
+ const { ApiClient: ApiClient2 } = await import('./types-C4duxyB7.mjs').then(function (n) { return n.ag; });
13303
13385
  let userEmail = void 0;
13304
13386
  try {
13305
13387
  const credentials = await readCredentialsForConfiguredRelay2();
@@ -13330,7 +13412,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
13330
13412
  }
13331
13413
  if (geminiSubcommand === "project" && args[2] === "get") {
13332
13414
  try {
13333
- const { readGeminiLocalConfig } = await import('./config-DHUFJkEr.mjs');
13415
+ const { readGeminiLocalConfig } = await import('./config-DRjtWNd0.mjs');
13334
13416
  const config = readGeminiLocalConfig();
13335
13417
  if (config.googleCloudProject) {
13336
13418
  console.log(`Current Google Cloud Project: ${config.googleCloudProject}`);
@@ -13370,7 +13452,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
13370
13452
  process.exit(0);
13371
13453
  }
13372
13454
  try {
13373
- const { runGemini } = await import('./runGemini-Cnvz6a6J.mjs');
13455
+ const { runGemini } = await import('./runGemini-DQKPf1RX.mjs');
13374
13456
  let startedBy = void 0;
13375
13457
  for (let i = 1; i < args.length; i++) {
13376
13458
  if (args[i] === "--started-by") {
@@ -13392,7 +13474,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
13392
13474
  return;
13393
13475
  } else if (subcommand === "acp") {
13394
13476
  try {
13395
- const { runAcp, resolveAcpAgentConfig } = await import('./index-D9OFwx0T.mjs');
13477
+ const { runAcp, resolveAcpAgentConfig } = await import('./index-1ZE940yd.mjs');
13396
13478
  let startedBy = void 0;
13397
13479
  let verbose = false;
13398
13480
  const acpArgs = [];
@@ -13432,7 +13514,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
13432
13514
  return;
13433
13515
  } else if (subcommand === "openclaw") {
13434
13516
  try {
13435
- const { runOpenClaw } = await import('./runOpenClaw-Cpxdqf9Z.mjs');
13517
+ const { runOpenClaw } = await import('./runOpenClaw-BNfz77EE.mjs');
13436
13518
  let startedBy = void 0;
13437
13519
  let verbose = false;
13438
13520
  let gatewayUrl;
@@ -13483,7 +13565,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
13483
13565
  return;
13484
13566
  } else if (subcommand === "mcp" && args.length === 1) {
13485
13567
  try {
13486
- const { handleMcpCommand } = await import('./mcp-DnO0vHep.mjs');
13568
+ const { handleMcpCommand } = await import('./mcp-2Ee6mSAP.mjs');
13487
13569
  await handleMcpCommand();
13488
13570
  } catch (error) {
13489
13571
  process.stderr.write(`[very-happy mcp] Fatal: ${error instanceof Error ? error.message : String(error)}
package/dist/index.cjs CHANGED
@@ -1,8 +1,8 @@
1
1
  'use strict';
2
2
 
3
3
  require('chalk');
4
- require('./index-CdmSlaUU.cjs');
5
- require('./types-DL98ZceN.cjs');
4
+ require('./index-BTtTqsj4.cjs');
5
+ require('./types-B7qS_-8e.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-DoLyKWEW.mjs';
3
- import './types-B2DG32ua.mjs';
2
+ import './index-DZ7tAffg.mjs';
3
+ import './types-C4duxyB7.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-DL98ZceN.cjs');
9
- var index = require('./index-CdmSlaUU.cjs');
8
+ var persistence = require('./types-B7qS_-8e.cjs');
9
+ var index = require('./index-BTtTqsj4.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-B2DG32ua.mjs';
7
- import { t as tmuxSupportsSessionEnv } from './index-DoLyKWEW.mjs';
6
+ import { p as projectPath } from './types-C4duxyB7.mjs';
7
+ import { t as tmuxSupportsSessionEnv } from './index-DZ7tAffg.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-DL98ZceN.cjs');
3
+ var persistence = require('./types-B7qS_-8e.cjs');
4
4
  require('axios');
5
5
  require('chalk');
6
6
  require('node:util');
package/dist/lib.d.cts CHANGED
@@ -388,6 +388,8 @@ type Metadata = {
388
388
  description?: string | null;
389
389
  }>;
390
390
  currentModelCode?: string;
391
+ /** Resolved SDK model when no per-message model override was supplied. */
392
+ defaultModelCode?: string;
391
393
  operatingModes?: Array<{
392
394
  code: string;
393
395
  value: string;
@@ -425,6 +427,8 @@ type Metadata = {
425
427
  status: string;
426
428
  }>;
427
429
  skills?: string[];
430
+ /** Attachment content blocks this daemon can forward to the active SDK. */
431
+ attachmentKinds?: string[];
428
432
  homeDir: string;
429
433
  happyHomeDir: string;
430
434
  happyLibDir: string;
package/dist/lib.d.mts CHANGED
@@ -388,6 +388,8 @@ type Metadata = {
388
388
  description?: string | null;
389
389
  }>;
390
390
  currentModelCode?: string;
391
+ /** Resolved SDK model when no per-message model override was supplied. */
392
+ defaultModelCode?: string;
391
393
  operatingModes?: Array<{
392
394
  code: string;
393
395
  value: string;
@@ -425,6 +427,8 @@ type Metadata = {
425
427
  status: string;
426
428
  }>;
427
429
  skills?: string[];
430
+ /** Attachment content blocks this daemon can forward to the active SDK. */
431
+ attachmentKinds?: string[];
428
432
  homeDir: string;
429
433
  happyHomeDir: string;
430
434
  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-B2DG32ua.mjs';
1
+ export { A as ApiClient, a as ApiSessionClient, R as RawJSONLinesSchema, c as configuration, l as logger } from './types-C4duxyB7.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-DoLyKWEW.mjs';
4
+ import { p as pushClipboardViaDaemon } from './index-DZ7tAffg.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-B2DG32ua.mjs';
6
+ import { l as logger } from './types-C4duxyB7.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-CdmSlaUU.cjs');
6
+ var index = require('./index-BTtTqsj4.cjs');
7
7
  var limits = require('./limits-KdWKmwtH.cjs');
8
- var persistence = require('./types-DL98ZceN.cjs');
8
+ var persistence = require('./types-B7qS_-8e.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-B2DG32ua.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-DoLyKWEW.mjs';
7
- import { A as AcpBackend } from './AcpBackend-DBJGqMwR.mjs';
8
- import { readGeminiLocalConfig, determineGeminiModel, getGeminiModelSource, getInitialGeminiModel, saveGeminiModelToConfig } from './config-DHUFJkEr.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-C4duxyB7.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-DZ7tAffg.mjs';
7
+ import { A as AcpBackend } from './AcpBackend-DMLCBDru.mjs';
8
+ import { readGeminiLocalConfig, determineGeminiModel, getGeminiModelSource, getInitialGeminiModel, saveGeminiModelToConfig } from './config-DRjtWNd0.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-DL98ZceN.cjs');
8
- var index = require('./index-CdmSlaUU.cjs');
9
- var AcpBackend = require('./AcpBackend-_662AILI.cjs');
10
- var config = require('./config-Dn4CC1I_.cjs');
7
+ var persistence = require('./types-B7qS_-8e.cjs');
8
+ var index = require('./index-BTtTqsj4.cjs');
9
+ var AcpBackend = require('./AcpBackend-DjHJfd8y.cjs');
10
+ var config = require('./config-BjgfmsPT.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-B2DG32ua.mjs';
7
- import { A as AcpSessionManager } from './AcpSessionManager-DcWebwii.mjs';
8
- import { i as initialMachineMetadata, d as createSessionMetadata, e as setupOfflineReconnection, n as notifyDaemonSessionStarted, M as MessageQueue2, r as registerKillSessionHandler } from './index-DoLyKWEW.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-C4duxyB7.mjs';
7
+ import { A as AcpSessionManager } from './AcpSessionManager-xyImjcMI.mjs';
8
+ import { i as initialMachineMetadata, d as createSessionMetadata, e as setupOfflineReconnection, n as notifyDaemonSessionStarted, M as MessageQueue2, r as registerKillSessionHandler } from './index-DZ7tAffg.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-DL98ZceN.cjs');
9
- var AcpSessionManager = require('./AcpSessionManager-ENIrbDWT.cjs');
10
- var index = require('./index-CdmSlaUU.cjs');
8
+ var persistence = require('./types-B7qS_-8e.cjs');
9
+ var AcpSessionManager = require('./AcpSessionManager-Bd-LtS2E.cjs');
10
+ var index = require('./index-BTtTqsj4.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-B2DG32ua.mjs';
5
- import { b as sendUserMessage, a as sessionWebUrl } from './index-DoLyKWEW.mjs';
4
+ import { r as readPersistedSessions, c as configuration } from './types-C4duxyB7.mjs';
5
+ import { b as sendUserMessage, a as sessionWebUrl } from './index-DZ7tAffg.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-DL98ZceN.cjs');
7
- var index = require('./index-CdmSlaUU.cjs');
6
+ var persistence = require('./types-B7qS_-8e.cjs');
7
+ var index = require('./index-BTtTqsj4.cjs');
8
8
  require('axios');
9
9
  require('node:util');
10
10
  require('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 index = require('./index-CdmSlaUU.cjs');
7
- var persistence = require('./types-DL98ZceN.cjs');
6
+ var index = require('./index-BTtTqsj4.cjs');
7
+ var persistence = require('./types-B7qS_-8e.cjs');
8
8
  require('node:os');
9
9
  require('node:crypto');
10
10
  require('cross-spawn');
@@ -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-DoLyKWEW.mjs';
5
- import { l as logger } from './types-B2DG32ua.mjs';
4
+ import { c as checkIfDaemonRunningAndCleanupStaleState, s as spawnDaemonSession, a as sessionWebUrl, w as waitForSessionKey, b as sendUserMessage } from './index-DZ7tAffg.mjs';
5
+ import { l as logger } from './types-C4duxyB7.mjs';
6
6
  import 'node:os';
7
7
  import 'node:crypto';
8
8
  import 'cross-spawn';
@@ -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.80";
54
+ var version = "0.2.82";
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.80",
168
- "very-happy-tools-x64-darwin": "0.2.80",
169
- "very-happy-tools-arm64-linux": "0.2.80",
170
- "very-happy-tools-x64-linux": "0.2.80",
171
- "very-happy-tools-arm64-win32": "0.2.80",
172
- "very-happy-tools-x64-win32": "0.2.80"
167
+ "very-happy-tools-arm64-darwin": "0.2.82",
168
+ "very-happy-tools-x64-darwin": "0.2.82",
169
+ "very-happy-tools-arm64-linux": "0.2.82",
170
+ "very-happy-tools-x64-linux": "0.2.82",
171
+ "very-happy-tools-arm64-win32": "0.2.82",
172
+ "very-happy-tools-x64-win32": "0.2.82"
173
173
  };
174
174
  var devDependencies = {
175
175
  "@slopus/happy-wire": "workspace:*",
@@ -1480,7 +1480,7 @@ class RpcHandlerManager {
1480
1480
  }
1481
1481
  }
1482
1482
 
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-DL98ZceN.cjs', document.baseURI).href))));
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-B7qS_-8e.cjs', document.baseURI).href))));
1484
1484
  function projectPath() {
1485
1485
  const path = path$1.resolve(__dirname$1, "..");
1486
1486
  return path;
@@ -10023,6 +10023,9 @@ function defaultShell() {
10023
10023
  function tmuxNewSessionArgs(session, cols, rows, cwd, envFlags, shell) {
10024
10024
  return ["new-session", "-d", ...envFlags, "-s", session, "-x", String(cols), "-y", String(rows), "-c", cwd, shell];
10025
10025
  }
10026
+ function shouldUseDirectPtyFallback(attachOnly, createdNew, sessionAlive) {
10027
+ return !attachOnly && !createdNew && !sessionAlive;
10028
+ }
10026
10029
  function ptyEnv() {
10027
10030
  const env = {};
10028
10031
  for (const [k, v] of Object.entries(process.env)) {
@@ -10697,7 +10700,7 @@ class WebTerminalManager {
10697
10700
  ] : [];
10698
10701
  const created = node_child_process.spawnSync(
10699
10702
  "tmux",
10700
- ["new-session", "-d", ...envFlags, "-s", name, "-x", "120", "-y", "30", "-c", plan.cwd],
10703
+ tmuxNewSessionArgs(name, 120, 30, plan.cwd, envFlags, defaultShell()),
10701
10704
  { stdio: "ignore", timeout: TMUX_CREATE_TIMEOUT_MS, env }
10702
10705
  );
10703
10706
  const live = created.status === 0 && node_child_process.spawnSync(
@@ -10939,7 +10942,7 @@ class WebTerminalManager {
10939
10942
  ["has-session", "-t", `=${tmuxSession}:`],
10940
10943
  { stdio: "ignore", timeout: TMUX_PROBE_TIMEOUT_MS, env }
10941
10944
  ).status === 0;
10942
- if (!alive) {
10945
+ if (shouldUseDirectPtyFallback(attachOnly, createdNew, alive)) {
10943
10946
  const retry = node_child_process.spawnSync(
10944
10947
  "tmux",
10945
10948
  tmuxNewSessionArgs(tmuxSession, cols, rows, cwd, envFlags, defaultShell()),
@@ -10959,6 +10962,17 @@ class WebTerminalManager {
10959
10962
  }
10960
10963
  }
10961
10964
  }
10965
+ if (!attachOnly && !createdNew) {
10966
+ const alive = node_child_process.spawnSync(
10967
+ "tmux",
10968
+ ["has-session", "-t", `=${tmuxSession}:`],
10969
+ { stdio: "ignore", timeout: TMUX_PROBE_TIMEOUT_MS, env }
10970
+ ).status === 0;
10971
+ if (!alive) {
10972
+ logger.info(`[WEB TERMINAL] tmux session creation unavailable; using direct PTY for ${id}`);
10973
+ tmuxSession = void 0;
10974
+ }
10975
+ }
10962
10976
  } else {
10963
10977
  file = defaultShell();
10964
10978
  args = [];
@@ -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.80";
32
+ var version = "0.2.82";
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.80",
146
- "very-happy-tools-x64-darwin": "0.2.80",
147
- "very-happy-tools-arm64-linux": "0.2.80",
148
- "very-happy-tools-x64-linux": "0.2.80",
149
- "very-happy-tools-arm64-win32": "0.2.80",
150
- "very-happy-tools-x64-win32": "0.2.80"
145
+ "very-happy-tools-arm64-darwin": "0.2.82",
146
+ "very-happy-tools-x64-darwin": "0.2.82",
147
+ "very-happy-tools-arm64-linux": "0.2.82",
148
+ "very-happy-tools-x64-linux": "0.2.82",
149
+ "very-happy-tools-arm64-win32": "0.2.82",
150
+ "very-happy-tools-x64-win32": "0.2.82"
151
151
  };
152
152
  var devDependencies = {
153
153
  "@slopus/happy-wire": "workspace:*",
@@ -10001,6 +10001,9 @@ function defaultShell() {
10001
10001
  function tmuxNewSessionArgs(session, cols, rows, cwd, envFlags, shell) {
10002
10002
  return ["new-session", "-d", ...envFlags, "-s", session, "-x", String(cols), "-y", String(rows), "-c", cwd, shell];
10003
10003
  }
10004
+ function shouldUseDirectPtyFallback(attachOnly, createdNew, sessionAlive) {
10005
+ return !attachOnly && !createdNew && !sessionAlive;
10006
+ }
10004
10007
  function ptyEnv() {
10005
10008
  const env = {};
10006
10009
  for (const [k, v] of Object.entries(process.env)) {
@@ -10675,7 +10678,7 @@ class WebTerminalManager {
10675
10678
  ] : [];
10676
10679
  const created = spawnSync(
10677
10680
  "tmux",
10678
- ["new-session", "-d", ...envFlags, "-s", name, "-x", "120", "-y", "30", "-c", plan.cwd],
10681
+ tmuxNewSessionArgs(name, 120, 30, plan.cwd, envFlags, defaultShell()),
10679
10682
  { stdio: "ignore", timeout: TMUX_CREATE_TIMEOUT_MS, env }
10680
10683
  );
10681
10684
  const live = created.status === 0 && spawnSync(
@@ -10917,7 +10920,7 @@ class WebTerminalManager {
10917
10920
  ["has-session", "-t", `=${tmuxSession}:`],
10918
10921
  { stdio: "ignore", timeout: TMUX_PROBE_TIMEOUT_MS, env }
10919
10922
  ).status === 0;
10920
- if (!alive) {
10923
+ if (shouldUseDirectPtyFallback(attachOnly, createdNew, alive)) {
10921
10924
  const retry = spawnSync(
10922
10925
  "tmux",
10923
10926
  tmuxNewSessionArgs(tmuxSession, cols, rows, cwd, envFlags, defaultShell()),
@@ -10937,6 +10940,17 @@ class WebTerminalManager {
10937
10940
  }
10938
10941
  }
10939
10942
  }
10943
+ if (!attachOnly && !createdNew) {
10944
+ const alive = spawnSync(
10945
+ "tmux",
10946
+ ["has-session", "-t", `=${tmuxSession}:`],
10947
+ { stdio: "ignore", timeout: TMUX_PROBE_TIMEOUT_MS, env }
10948
+ ).status === 0;
10949
+ if (!alive) {
10950
+ logger.info(`[WEB TERMINAL] tmux session creation unavailable; using direct PTY for ${id}`);
10951
+ tmuxSession = void 0;
10952
+ }
10953
+ }
10940
10954
  } else {
10941
10955
  file = defaultShell();
10942
10956
  args = [];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "very-happy-cli",
3
- "version": "0.2.80",
3
+ "version": "0.2.82",
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.80",
117
- "very-happy-tools-x64-darwin": "0.2.80",
118
- "very-happy-tools-arm64-linux": "0.2.80",
119
- "very-happy-tools-x64-linux": "0.2.80",
120
- "very-happy-tools-arm64-win32": "0.2.80",
121
- "very-happy-tools-x64-win32": "0.2.80"
116
+ "very-happy-tools-arm64-darwin": "0.2.82",
117
+ "very-happy-tools-x64-darwin": "0.2.82",
118
+ "very-happy-tools-arm64-linux": "0.2.82",
119
+ "very-happy-tools-x64-linux": "0.2.82",
120
+ "very-happy-tools-arm64-win32": "0.2.82",
121
+ "very-happy-tools-x64-win32": "0.2.82"
122
122
  },
123
123
  "devDependencies": {
124
124
  "@slopus/happy-wire": "workspace:*",