very-happy-cli 0.2.111 → 0.2.112

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 (35) hide show
  1. package/dist/{AcpBackend-B_olk79F.cjs → AcpBackend-B3x-gQWP.cjs} +1 -1
  2. package/dist/{AcpBackend-CeXVb_s_.mjs → AcpBackend-DDEdYVW2.mjs} +1 -1
  3. package/dist/{AcpSessionManager-vqdqfD1l.mjs → AcpSessionManager-BORAhQ1r.mjs} +1 -1
  4. package/dist/{AcpSessionManager-uXwWO2Tn.cjs → AcpSessionManager-DGPLD-go.cjs} +1 -1
  5. package/dist/{config-vGkcq9nM.mjs → config-B_L5vXXu.mjs} +2 -2
  6. package/dist/{config-BR3tkFL_.cjs → config-KX6e7GEu.cjs} +2 -2
  7. package/dist/{index-CtBP0Qvc.cjs → index-B7-t5Kwz.cjs} +4 -4
  8. package/dist/{index-BOoGJGQc.cjs → index-BnRQP3PL.cjs} +240 -19
  9. package/dist/{index-SjthsMid.cjs → index-CTd0skWH.cjs} +2 -2
  10. package/dist/{index-JAhGeW4_.mjs → index-Cu5FdgTq.mjs} +5 -5
  11. package/dist/{index-Bn-xsguz.mjs → index-inkhalP5.mjs} +236 -15
  12. package/dist/{index-C-RLk8-e.mjs → index-lQzCAx9I.mjs} +2 -2
  13. package/dist/index.cjs +2 -2
  14. package/dist/index.mjs +2 -2
  15. package/dist/{installTerminalHooks-FbKaK149.cjs → installTerminalHooks-BVk-r0yD.cjs} +2 -2
  16. package/dist/{installTerminalHooks-ADNcNdnB.mjs → installTerminalHooks-CQiW7Jn9.mjs} +2 -2
  17. package/dist/lib.cjs +1 -1
  18. package/dist/lib.d.cts +44 -0
  19. package/dist/lib.d.mts +44 -0
  20. package/dist/lib.mjs +1 -1
  21. package/dist/{mcp-DPp-bYNE.cjs → mcp-D0DIU8Q2.cjs} +2 -2
  22. package/dist/{mcp-DHPm_gvL.mjs → mcp-DD-0VkiA.mjs} +2 -2
  23. package/dist/{runGemini-CWWyjQMz.mjs → runGemini-DHyBDo5P.mjs} +4 -4
  24. package/dist/{runGemini-D5ySpYIZ.cjs → runGemini-Dq1d8Ccb.cjs} +4 -4
  25. package/dist/{runOpenClaw-Bwrb1LXP.cjs → runOpenClaw-BHXnUF_m.cjs} +3 -3
  26. package/dist/{runOpenClaw-Bv4rUTyJ.mjs → runOpenClaw-DX-tgQ2V.mjs} +3 -3
  27. package/dist/{send-BlkxFZu4.mjs → send-0TYDXiGx.mjs} +2 -2
  28. package/dist/{send-DBfSNILO.cjs → send-By6zEUWo.cjs} +2 -2
  29. package/dist/{sessions-CVuEsdRl.cjs → sessions-DTBRcBRk.cjs} +2 -2
  30. package/dist/{sessions-1fW8soBM.mjs → sessions-TM8VaCMY.mjs} +2 -2
  31. package/dist/{spawn-D_ZexrY9.cjs → spawn-CweTEYze.cjs} +2 -2
  32. package/dist/{spawn-BorKN3W2.mjs → spawn-D0oTo5BT.mjs} +2 -2
  33. package/dist/{types-k_ipDb0c.mjs → types-C5ewhu1Q.mjs} +96 -11
  34. package/dist/{types-BG_5QKX5.cjs → types-R11tMGyX.cjs} +97 -11
  35. package/package.json +7 -7
@@ -1,7 +1,7 @@
1
1
  import{createRequire as _pkgrollCR}from"node:module";const require=_pkgrollCR(import.meta.url);import chalk from 'chalk';
2
2
  import os, { homedir, userInfo } from 'node:os';
3
3
  import { randomUUID, randomBytes, createHash as createHash$1, timingSafeEqual } from 'node:crypto';
4
- import { o as readDaemonState, l as logger, c as configuration, q as clearDaemonState, s as getProjectPath, p as projectPath, t as initializeSandbox, u as wrapCommand, d as contentLogMetadata, I as InvalidateSync, R as RawJSONLinesSchema, g as delay, v as AsyncLock, x as ensurePrivateDirectory, M as MAX_CHAT_ATTACHMENT_SOURCE_BYTES, y as hardenPrivateFile, f as packageJson, j as readSettings, z as readCredentials, B as credentialRelayProblem, C as deriveLocalCliUpdateSummary, k as encodeBase64, D as updateSettings, E as encodeBase64Url, F as decodeBase64, G as writeCredentialsLegacy, H as writeCredentialsDataKey, J as readCredentialsForConfiguredRelay, K as encrypt, r as readPersistedSessions, L as isClaudeSessionId, N as getLocalHappyAgentCredentialPath, O as readLocalHappyAgentCredentials, P as decryptWithDataKey, Q as decryptLegacy, S as extractCompleteLines, T as decideBackfill, U as parseTerminalHookPayload, V as tmuxArgs, W as scrubTmuxClientEnv, X as decideMirrorBinding, Y as MIRROR_BACKFILL_LINES_DEFAULT, Z as persistSession, _ as mirrorLineKey, $ as mirrorLocalId, w as writePrivateFileSync, a0 as detectResumeSupport, a1 as detectCLIAvailability, a2 as acquireDaemonLock, a3 as summarizeSpawnSessionForLog, a4 as deletePersistedSessions, a5 as shellescape, a6 as decrypt, a7 as writeDaemonState, A as ApiClient, a8 as writeSettings, a9 as fetchCliUpdateState, aa as resolveCliUpdateCheckInterval, ab as DEFAULT_CLI_UPDATE_CHECK_INTERVAL_MS, ac as releaseDaemonLock, i as isValidSessionId, ad as listVhTerminals, ae as isValidTerminalId, af as readVhTerminal, ag as sendToVhTerminal, ah as TITLE_PROMPT_PREFIX, ai as BOARD_ANALYZER_PROMPT_PREFIX, h as connectionState, aj as startOfflineReconnection, ak as clearCredentials, al as clearMachineId, m as ensurePrivateDirectorySync, am as SandboxConfigSchema, b as createEnvelope, an as CodexAppServerClient, ao as getLatestDaemonLog } from './types-k_ipDb0c.mjs';
4
+ import { o as readDaemonState, l as logger, c as configuration, q as clearDaemonState, s as getProjectPath, p as projectPath, t as initializeSandbox, u as wrapCommand, d as contentLogMetadata, I as InvalidateSync, R as RawJSONLinesSchema, g as delay, v as AsyncLock, S as STREAM_DELTA_MAX_CHARS, x as ensurePrivateDirectory, M as MAX_CHAT_ATTACHMENT_SOURCE_BYTES, y as hardenPrivateFile, f as packageJson, j as readSettings, z as readCredentials, B as credentialRelayProblem, C as deriveLocalCliUpdateSummary, k as encodeBase64, D as updateSettings, E as encodeBase64Url, F as decodeBase64, G as writeCredentialsLegacy, H as writeCredentialsDataKey, J as readCredentialsForConfiguredRelay, K as encrypt, r as readPersistedSessions, L as isClaudeSessionId, N as getLocalHappyAgentCredentialPath, O as readLocalHappyAgentCredentials, P as decryptWithDataKey, Q as decryptLegacy, T as extractCompleteLines, U as decideBackfill, V as parseTerminalHookPayload, W as tmuxArgs, X as scrubTmuxClientEnv, Y as decideMirrorBinding, Z as MIRROR_BACKFILL_LINES_DEFAULT, _ as persistSession, $ as mirrorLineKey, a0 as mirrorLocalId, w as writePrivateFileSync, a1 as detectResumeSupport, a2 as detectCLIAvailability, a3 as acquireDaemonLock, a4 as summarizeSpawnSessionForLog, a5 as deletePersistedSessions, a6 as shellescape, a7 as decrypt, a8 as writeDaemonState, A as ApiClient, a9 as writeSettings, aa as fetchCliUpdateState, ab as resolveCliUpdateCheckInterval, ac as DEFAULT_CLI_UPDATE_CHECK_INTERVAL_MS, ad as releaseDaemonLock, i as isValidSessionId, ae as listVhTerminals, af as isValidTerminalId, ag as readVhTerminal, ah as sendToVhTerminal, ai as TITLE_PROMPT_PREFIX, aj as BOARD_ANALYZER_PROMPT_PREFIX, h as connectionState, ak as startOfflineReconnection, al as clearCredentials, am as clearMachineId, m as ensurePrivateDirectorySync, an as SandboxConfigSchema, b as createEnvelope, ao as CodexAppServerClient, ap as getLatestDaemonLog } from './types-C5ewhu1Q.mjs';
5
5
  import spawn$1, { spawn } from 'cross-spawn';
6
6
  import path, { join, resolve, basename, delimiter, isAbsolute, normalize, sep, dirname } from 'node:path';
7
7
  import { createInterface } from 'node:readline';
@@ -2003,7 +2003,14 @@ async function claudeRemote(opts) {
2003
2003
  onUserDialog: opts.onUserDialog,
2004
2004
  supportedDialogKinds: opts.onUserDialog ? ["refusal_fallback_prompt"] : void 0,
2005
2005
  abort: opts.signal,
2006
- settingsPath: opts.hookSettingsPath
2006
+ settingsPath: opts.hookSettingsPath,
2007
+ // B-309: token-level partials. Without this the SDK emits nothing
2008
+ // between "turn started" and "entire assistant message", which is
2009
+ // exactly why the web used to show a spinner where the terminal shows
2010
+ // the model thinking out loud. The partials do NOT enter the
2011
+ // transcript; they are split off below and relayed on a side channel.
2012
+ // Only pay for them when someone is listening.
2013
+ includePartialMessages: opts.onStreamFrame ? true : void 0
2007
2014
  };
2008
2015
  let thinking = false;
2009
2016
  const updateThinking = (newThinking) => {
@@ -2053,10 +2060,26 @@ async function claudeRemote(opts) {
2053
2060
  try {
2054
2061
  logger.debug(`[claudeRemote] Starting to iterate over response`);
2055
2062
  for await (const message of response) {
2063
+ if (message.type === "stream_event") {
2064
+ if (opts.onStreamFrame && !message.parent_tool_use_id) {
2065
+ opts.onStreamFrame({ type: "stream_event", event: message.event });
2066
+ }
2067
+ continue;
2068
+ }
2056
2069
  logger.debug(`[claudeRemote] Message ${message.type}`, contentLogMetadata(message));
2057
2070
  if (message.type === "assistant" && message.error) {
2058
2071
  lastAssistantError = message.error;
2059
2072
  }
2073
+ if (opts.onStreamFrame && message.type === "system") {
2074
+ const subtype = message.subtype;
2075
+ if (subtype === "thinking_tokens") {
2076
+ const tokens = message;
2077
+ opts.onStreamFrame({ type: "system", subtype: "thinking_tokens", estimated_tokens: tokens.estimated_tokens });
2078
+ } else if (subtype === "status") {
2079
+ const status = message;
2080
+ opts.onStreamFrame({ type: "system", subtype: "status", status: status.status });
2081
+ }
2082
+ }
2060
2083
  const outboundMessage = isCompactCommand && message.type === "assistant" ? { ...message, isCompactSummary: true } : message;
2061
2084
  opts.onMessage(outboundMessage);
2062
2085
  if (message.type === "system" && message.subtype === "init") {
@@ -3256,6 +3279,197 @@ class OutgoingMessageQueue {
3256
3279
  }
3257
3280
  }
3258
3281
 
3282
+ const STREAM_FLUSH_MS = 80;
3283
+ const PROGRESS_FLUSH_MS = 250;
3284
+ const STREAM_FLUSH_MAX_BYTES = 16 * 1024;
3285
+ class StreamRelay {
3286
+ send;
3287
+ setTimer;
3288
+ clearTimer;
3289
+ now;
3290
+ /** The block currently accumulating deltas. At most one is open at a time
3291
+ * in practice; a switch flushes the previous one first, so out-of-order
3292
+ * SDK frames degrade to "slightly chunkier", never to interleaved text. */
3293
+ pending = null;
3294
+ flushHandle = null;
3295
+ progress = {};
3296
+ progressDirty = false;
3297
+ progressHandle = null;
3298
+ /** Message id of the block currently open, so `content_block_delta` (which
3299
+ * carries only an index) can be attributed. Reset per assistant message. */
3300
+ currentMid = null;
3301
+ openBlocks = /* @__PURE__ */ new Set();
3302
+ /** True while nothing has been ingested since the last sweep. Both the SDK
3303
+ * `result` frame and the launcher's `finally` call endTurn (the second is
3304
+ * the safety net for turns that die before producing a result), so
3305
+ * without this a normal turn would emit two sweeps. */
3306
+ idleSinceTurnEnd = true;
3307
+ constructor(options) {
3308
+ this.send = options.send;
3309
+ this.setTimer = options.setTimer ?? ((fn, ms) => setTimeout(fn, ms));
3310
+ this.clearTimer = options.clearTimer ?? ((handle) => clearTimeout(handle));
3311
+ this.now = options.now ?? (() => Date.now());
3312
+ }
3313
+ /** Feed one SDK frame. Unknown shapes are ignored, never thrown on: this
3314
+ * channel must not be able to take a turn down. */
3315
+ ingest(message) {
3316
+ this.idleSinceTurnEnd = false;
3317
+ try {
3318
+ if (message.type === "stream_event") {
3319
+ this.ingestStreamEvent(message.event);
3320
+ return;
3321
+ }
3322
+ if (message.type === "system" && message.subtype === "thinking_tokens") {
3323
+ if (typeof message.estimated_tokens === "number") {
3324
+ this.setProgress({ thinkingTokens: message.estimated_tokens });
3325
+ }
3326
+ return;
3327
+ }
3328
+ if (message.type === "system" && message.subtype === "status") {
3329
+ const status = message.status === "requesting" || message.status === "compacting" ? message.status : void 0;
3330
+ this.progress.status = status;
3331
+ this.progressDirty = true;
3332
+ this.scheduleProgress();
3333
+ return;
3334
+ }
3335
+ } catch {
3336
+ }
3337
+ }
3338
+ /** The turn produced its result. Flushes everything and tells the web to
3339
+ * sweep drafts that no persisted message ever claimed. */
3340
+ endTurn() {
3341
+ if (this.idleSinceTurnEnd) {
3342
+ this.clearTimers();
3343
+ return;
3344
+ }
3345
+ this.idleSinceTurnEnd = true;
3346
+ this.flushPending();
3347
+ this.closeOpenBlocks();
3348
+ this.flushProgress();
3349
+ this.progress = {};
3350
+ this.currentMid = null;
3351
+ this.send({ t: "turn-end" });
3352
+ }
3353
+ /** Release timers without emitting anything (session teardown). */
3354
+ dispose() {
3355
+ this.clearTimers();
3356
+ this.pending = null;
3357
+ this.openBlocks.clear();
3358
+ }
3359
+ clearTimers() {
3360
+ if (this.flushHandle !== null) this.clearTimer(this.flushHandle);
3361
+ if (this.progressHandle !== null) this.clearTimer(this.progressHandle);
3362
+ this.flushHandle = null;
3363
+ this.progressHandle = null;
3364
+ }
3365
+ ingestStreamEvent(event) {
3366
+ const e = event;
3367
+ if (!e || typeof e.type !== "string") return;
3368
+ if (e.type === "message_start") {
3369
+ const mid = e.message?.id;
3370
+ this.flushPending();
3371
+ this.closeOpenBlocks();
3372
+ this.currentMid = typeof mid === "string" && mid.length > 0 ? mid : null;
3373
+ return;
3374
+ }
3375
+ if (e.type === "content_block_start") {
3376
+ const kind = e.content_block?.type === "thinking" ? "thinking" : e.content_block?.type === "text" ? "text" : null;
3377
+ if (!kind || !this.currentMid || typeof e.index !== "number") return;
3378
+ this.flushPending();
3379
+ this.openBlocks.add(e.index);
3380
+ this.send({ t: "block-start", mid: this.currentMid, idx: e.index, kind });
3381
+ return;
3382
+ }
3383
+ if (e.type === "content_block_delta") {
3384
+ const delta = e.delta;
3385
+ const text = delta?.type === "text_delta" ? delta.text : delta?.type === "thinking_delta" ? delta.thinking : null;
3386
+ if (typeof text !== "string" || text.length === 0) return;
3387
+ if (!this.currentMid || typeof e.index !== "number") return;
3388
+ if (!this.openBlocks.has(e.index)) return;
3389
+ this.appendDelta(this.currentMid, e.index, text);
3390
+ return;
3391
+ }
3392
+ if (e.type === "content_block_stop") {
3393
+ if (!this.currentMid || typeof e.index !== "number") return;
3394
+ if (!this.openBlocks.has(e.index)) return;
3395
+ this.flushPending();
3396
+ this.openBlocks.delete(e.index);
3397
+ this.send({ t: "block-end", mid: this.currentMid, idx: e.index });
3398
+ return;
3399
+ }
3400
+ if (e.type === "message_delta") {
3401
+ const outputTokens = e.usage?.output_tokens;
3402
+ if (typeof outputTokens === "number") {
3403
+ this.setProgress({ outputTokens });
3404
+ }
3405
+ return;
3406
+ }
3407
+ }
3408
+ appendDelta(mid, idx, text) {
3409
+ if (this.pending && (this.pending.mid !== mid || this.pending.idx !== idx)) {
3410
+ this.flushPending();
3411
+ }
3412
+ if (!this.pending) {
3413
+ this.pending = { mid, idx, text: "", bytes: 0 };
3414
+ }
3415
+ this.pending.text += text;
3416
+ this.pending.bytes += Buffer.byteLength(text, "utf8");
3417
+ if (this.pending.bytes >= STREAM_FLUSH_MAX_BYTES || this.pending.text.length >= STREAM_DELTA_MAX_CHARS) {
3418
+ this.flushPending();
3419
+ return;
3420
+ }
3421
+ if (this.flushHandle === null) {
3422
+ this.flushHandle = this.setTimer(() => {
3423
+ this.flushHandle = null;
3424
+ this.flushPending();
3425
+ }, STREAM_FLUSH_MS);
3426
+ }
3427
+ }
3428
+ flushPending() {
3429
+ if (this.flushHandle !== null) {
3430
+ this.clearTimer(this.flushHandle);
3431
+ this.flushHandle = null;
3432
+ }
3433
+ const pending = this.pending;
3434
+ this.pending = null;
3435
+ if (!pending || pending.text.length === 0) return;
3436
+ this.send({ t: "block-delta", mid: pending.mid, idx: pending.idx, text: pending.text });
3437
+ }
3438
+ /** Close blocks the SDK never stopped (interrupt, error, message switch) so
3439
+ * the web's draft does not keep a blinking cursor forever. */
3440
+ closeOpenBlocks() {
3441
+ if (!this.currentMid || this.openBlocks.size === 0) {
3442
+ this.openBlocks.clear();
3443
+ return;
3444
+ }
3445
+ for (const idx of [...this.openBlocks].sort((a, b) => a - b)) {
3446
+ this.send({ t: "block-end", mid: this.currentMid, idx });
3447
+ }
3448
+ this.openBlocks.clear();
3449
+ }
3450
+ setProgress(patch) {
3451
+ this.progress = { ...this.progress, ...patch };
3452
+ this.progressDirty = true;
3453
+ this.scheduleProgress();
3454
+ }
3455
+ scheduleProgress() {
3456
+ if (this.progressHandle !== null) return;
3457
+ this.progressHandle = this.setTimer(() => {
3458
+ this.progressHandle = null;
3459
+ this.flushProgress();
3460
+ }, PROGRESS_FLUSH_MS);
3461
+ }
3462
+ flushProgress() {
3463
+ if (this.progressHandle !== null) {
3464
+ this.clearTimer(this.progressHandle);
3465
+ this.progressHandle = null;
3466
+ }
3467
+ if (!this.progressDirty) return;
3468
+ this.progressDirty = false;
3469
+ this.send({ t: "progress", ...this.progress });
3470
+ }
3471
+ }
3472
+
3259
3473
  function getAskUserQuestionToolCallIds(message) {
3260
3474
  if (message.type !== "assistant") {
3261
3475
  return [];
@@ -3636,6 +3850,10 @@ async function claudeRemoteLauncher(session, onPermissionModeChange, onEffective
3636
3850
  return nextMode;
3637
3851
  };
3638
3852
  permissionHandler.reset("Previous CLI process exited before responding");
3853
+ const streamingEnabled = process.env.HAPPY_SESSION_STREAM_DISABLED !== "1";
3854
+ const streamRelay = new StreamRelay({
3855
+ send: (frame) => session.client.sendStreamFrame(frame)
3856
+ });
3639
3857
  const messageQueue = new OutgoingMessageQueue(
3640
3858
  (logMessage) => session.client.sendClaudeSessionMessage(logMessage)
3641
3859
  );
@@ -3894,6 +4112,7 @@ async function claudeRemoteLauncher(session, onPermissionModeChange, onEffective
3894
4112
  };
3895
4113
  },
3896
4114
  onThinkingChange: session.onThinkingChange,
4115
+ onStreamFrame: streamingEnabled ? (frame) => streamRelay.ingest(frame) : void 0,
3897
4116
  claudeEnvVars: session.claudeEnvVars,
3898
4117
  claudeArgs: session.claudeArgs,
3899
4118
  onMessage,
@@ -3973,6 +4192,8 @@ async function claudeRemoteLauncher(session, onPermissionModeChange, onEffective
3973
4192
  await messageQueue.flush();
3974
4193
  messageQueue.destroy();
3975
4194
  logger.debug("[remote]: message queue flushed");
4195
+ streamRelay.endTurn();
4196
+ streamRelay.dispose();
3976
4197
  abortController = null;
3977
4198
  abortFuture?.resolve(void 0);
3978
4199
  abortFuture = null;
@@ -10375,7 +10596,7 @@ function registerSideQuestionHandler(rpc, deps) {
10375
10596
  const retainMs = deps.retainMs ?? SIDE_QUESTION_RETAIN_MS;
10376
10597
  const maxRunMs = deps.maxRunMs ?? SIDE_QUESTION_MAX_RUN_MS;
10377
10598
  const run = deps.run ?? (async (input) => {
10378
- const { query } = await import('./index-C-RLk8-e.mjs');
10599
+ const { query } = await import('./index-lQzCAx9I.mjs');
10379
10600
  return runSideQuestion(query, input);
10380
10601
  });
10381
10602
  const slots = /* @__PURE__ */ new Map();
@@ -15305,7 +15526,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
15305
15526
  process.exit(0);
15306
15527
  } else if (subcommand === "install-terminal-hooks") {
15307
15528
  try {
15308
- const { installTerminalHooks, parseTerminalHooksArgs, TERMINAL_HOOKS_HELP } = await import('./installTerminalHooks-ADNcNdnB.mjs');
15529
+ const { installTerminalHooks, parseTerminalHooksArgs, TERMINAL_HOOKS_HELP } = await import('./installTerminalHooks-CQiW7Jn9.mjs');
15309
15530
  const command = parseTerminalHooksArgs(args.slice(1));
15310
15531
  if (command.action === "help") {
15311
15532
  console.log(TERMINAL_HOOKS_HELP);
@@ -15322,7 +15543,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
15322
15543
  }
15323
15544
  } else if (subcommand === "spawn") {
15324
15545
  try {
15325
- const { handleSpawnCommand } = await import('./spawn-BorKN3W2.mjs');
15546
+ const { handleSpawnCommand } = await import('./spawn-D0oTo5BT.mjs');
15326
15547
  await handleSpawnCommand(args.slice(1));
15327
15548
  } catch (error) {
15328
15549
  console.error(chalk.red("Error:"), error instanceof Error ? error.message : "Unknown error");
@@ -15334,7 +15555,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
15334
15555
  return;
15335
15556
  } else if (subcommand === "sessions") {
15336
15557
  try {
15337
- const { handleSessionsCommand } = await import('./sessions-1fW8soBM.mjs');
15558
+ const { handleSessionsCommand } = await import('./sessions-TM8VaCMY.mjs');
15338
15559
  await handleSessionsCommand(args.slice(1));
15339
15560
  } catch (error) {
15340
15561
  console.error(chalk.red("Error:"), error instanceof Error ? error.message : "Unknown error");
@@ -15346,7 +15567,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
15346
15567
  return;
15347
15568
  } else if (subcommand === "send") {
15348
15569
  try {
15349
- const { handleSendCommand } = await import('./send-BlkxFZu4.mjs');
15570
+ const { handleSendCommand } = await import('./send-0TYDXiGx.mjs');
15350
15571
  await handleSendCommand(args.slice(1));
15351
15572
  } catch (error) {
15352
15573
  console.error(chalk.red("Error:"), error instanceof Error ? error.message : "Unknown error");
@@ -15452,9 +15673,9 @@ Conversation history is preserved on the server, but in-flight tool calls are in
15452
15673
  if (geminiSubcommand === "project" && args[2] === "set" && args[3]) {
15453
15674
  const projectId = args[3];
15454
15675
  try {
15455
- const { saveGoogleCloudProjectToConfig } = await import('./config-vGkcq9nM.mjs');
15456
- const { readCredentialsForConfiguredRelay: readCredentialsForConfiguredRelay2 } = await import('./types-k_ipDb0c.mjs').then(function (n) { return n.ap; });
15457
- const { ApiClient: ApiClient2 } = await import('./types-k_ipDb0c.mjs').then(function (n) { return n.aq; });
15676
+ const { saveGoogleCloudProjectToConfig } = await import('./config-B_L5vXXu.mjs');
15677
+ const { readCredentialsForConfiguredRelay: readCredentialsForConfiguredRelay2 } = await import('./types-C5ewhu1Q.mjs').then(function (n) { return n.aq; });
15678
+ const { ApiClient: ApiClient2 } = await import('./types-C5ewhu1Q.mjs').then(function (n) { return n.ar; });
15458
15679
  let userEmail = void 0;
15459
15680
  try {
15460
15681
  const credentials = await readCredentialsForConfiguredRelay2();
@@ -15485,7 +15706,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
15485
15706
  }
15486
15707
  if (geminiSubcommand === "project" && args[2] === "get") {
15487
15708
  try {
15488
- const { readGeminiLocalConfig } = await import('./config-vGkcq9nM.mjs');
15709
+ const { readGeminiLocalConfig } = await import('./config-B_L5vXXu.mjs');
15489
15710
  const config = readGeminiLocalConfig();
15490
15711
  if (config.googleCloudProject) {
15491
15712
  console.log(`Current Google Cloud Project: ${config.googleCloudProject}`);
@@ -15525,7 +15746,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
15525
15746
  process.exit(0);
15526
15747
  }
15527
15748
  try {
15528
- const { runGemini } = await import('./runGemini-CWWyjQMz.mjs');
15749
+ const { runGemini } = await import('./runGemini-DHyBDo5P.mjs');
15529
15750
  let startedBy = void 0;
15530
15751
  for (let i = 1; i < args.length; i++) {
15531
15752
  if (args[i] === "--started-by") {
@@ -15547,7 +15768,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
15547
15768
  return;
15548
15769
  } else if (subcommand === "acp") {
15549
15770
  try {
15550
- const { runAcp, resolveAcpAgentConfig } = await import('./index-JAhGeW4_.mjs');
15771
+ const { runAcp, resolveAcpAgentConfig } = await import('./index-Cu5FdgTq.mjs');
15551
15772
  let startedBy = void 0;
15552
15773
  let verbose = false;
15553
15774
  const acpArgs = [];
@@ -15587,7 +15808,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
15587
15808
  return;
15588
15809
  } else if (subcommand === "openclaw") {
15589
15810
  try {
15590
- const { runOpenClaw } = await import('./runOpenClaw-Bv4rUTyJ.mjs');
15811
+ const { runOpenClaw } = await import('./runOpenClaw-DX-tgQ2V.mjs');
15591
15812
  let startedBy = void 0;
15592
15813
  let verbose = false;
15593
15814
  let gatewayUrl;
@@ -15638,7 +15859,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
15638
15859
  return;
15639
15860
  } else if (subcommand === "mcp" && args.length === 1) {
15640
15861
  try {
15641
- const { handleMcpCommand } = await import('./mcp-DHPm_gvL.mjs');
15862
+ const { handleMcpCommand } = await import('./mcp-DD-0VkiA.mjs');
15642
15863
  await handleMcpCommand();
15643
15864
  } catch (error) {
15644
15865
  process.stderr.write(`[very-happy mcp] Fatal: ${error instanceof Error ? error.message : String(error)}
@@ -1,9 +1,9 @@
1
- import { q as query } from './index-Bn-xsguz.mjs';
1
+ import { q as query } from './index-inkhalP5.mjs';
2
2
  export { AbortError } from '@anthropic-ai/claude-agent-sdk';
3
3
  import 'chalk';
4
4
  import 'node:os';
5
5
  import 'node:crypto';
6
- import './types-k_ipDb0c.mjs';
6
+ import './types-C5ewhu1Q.mjs';
7
7
  import 'axios';
8
8
  import 'node:util';
9
9
  import 'node:fs';
package/dist/index.cjs CHANGED
@@ -1,8 +1,8 @@
1
1
  'use strict';
2
2
 
3
3
  require('chalk');
4
- require('./index-BOoGJGQc.cjs');
5
- require('./types-BG_5QKX5.cjs');
4
+ require('./index-BnRQP3PL.cjs');
5
+ require('./types-R11tMGyX.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-Bn-xsguz.mjs';
3
- import './types-k_ipDb0c.mjs';
2
+ import './index-inkhalP5.mjs';
3
+ import './types-C5ewhu1Q.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-BG_5QKX5.cjs');
9
- var index = require('./index-BOoGJGQc.cjs');
8
+ var persistence = require('./types-R11tMGyX.cjs');
9
+ var index = require('./index-BnRQP3PL.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-k_ipDb0c.mjs';
7
- import { t as tmuxSupportsSessionEnv } from './index-Bn-xsguz.mjs';
6
+ import { p as projectPath } from './types-C5ewhu1Q.mjs';
7
+ import { t as tmuxSupportsSessionEnv } from './index-inkhalP5.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-BG_5QKX5.cjs');
3
+ var persistence = require('./types-R11tMGyX.cjs');
4
4
  require('axios');
5
5
  require('chalk');
6
6
  require('node:util');
package/dist/lib.d.cts CHANGED
@@ -44,6 +44,7 @@ declare const sessionEnvelopeSchema: z.ZodObject<{
44
44
  subagent: z.ZodOptional<z.ZodString>;
45
45
  claudeUuid: z.ZodOptional<z.ZodString>;
46
46
  codexItemId: z.ZodOptional<z.ZodString>;
47
+ streamKey: z.ZodOptional<z.ZodString>;
47
48
  usage: z.ZodOptional<z.ZodObject<{
48
49
  input_tokens: z.ZodNumber;
49
50
  output_tokens: z.ZodNumber;
@@ -139,6 +140,35 @@ declare const sessionEnvelopeSchema: z.ZodObject<{
139
140
  }, z.core.$strip>], "t">;
140
141
  }, z.core.$strip>;
141
142
  type SessionEnvelope = z.infer<typeof sessionEnvelopeSchema>;
143
+ declare const sessionStreamFrameSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
144
+ t: z.ZodLiteral<"block-start">;
145
+ mid: z.ZodString;
146
+ idx: z.ZodNumber;
147
+ kind: z.ZodEnum<{
148
+ text: "text";
149
+ thinking: "thinking";
150
+ }>;
151
+ }, z.core.$strip>, z.ZodObject<{
152
+ t: z.ZodLiteral<"block-delta">;
153
+ mid: z.ZodString;
154
+ idx: z.ZodNumber;
155
+ text: z.ZodString;
156
+ }, z.core.$strip>, z.ZodObject<{
157
+ t: z.ZodLiteral<"block-end">;
158
+ mid: z.ZodString;
159
+ idx: z.ZodNumber;
160
+ }, z.core.$strip>, z.ZodObject<{
161
+ t: z.ZodLiteral<"progress">;
162
+ thinkingTokens: z.ZodOptional<z.ZodNumber>;
163
+ outputTokens: z.ZodOptional<z.ZodNumber>;
164
+ status: z.ZodOptional<z.ZodEnum<{
165
+ requesting: "requesting";
166
+ compacting: "compacting";
167
+ }>>;
168
+ }, z.core.$strip>, z.ZodObject<{
169
+ t: z.ZodLiteral<"turn-end">;
170
+ }, z.core.$strip>], "t">;
171
+ type SessionStreamFrame = z.infer<typeof sessionStreamFrameSchema>;
142
172
 
143
173
  /**
144
174
  * Simplified schema that only validates fields actually used in the codebase
@@ -901,6 +931,20 @@ declare class ApiSessionClient extends EventEmitter {
901
931
  * Send a ping message to keep the connection alive
902
932
  */
903
933
  keepAlive(thinking: boolean, mode: 'local' | 'remote'): void;
934
+ /**
935
+ * B-309: push one live stream frame (thinking/text delta or progress) to
936
+ * this account's web clients.
937
+ *
938
+ * Encrypted with the SESSION key and relayed without being stored —
939
+ * clipboard-push's shape, for clipboard-push's reasons: the relay must not
940
+ * be able to read thinking text, and the session id is stamped by the
941
+ * server from the authenticated connection rather than trusted from here.
942
+ *
943
+ * `volatile` on purpose. A draft that misses the wire while disconnected
944
+ * is worth nothing — the persisted message is still coming, and replaying
945
+ * stale deltas after a reconnect would paint text that has already landed.
946
+ */
947
+ sendStreamFrame(frame: SessionStreamFrame): void;
904
948
  /**
905
949
  * Send session death message
906
950
  */
package/dist/lib.d.mts CHANGED
@@ -44,6 +44,7 @@ declare const sessionEnvelopeSchema: z.ZodObject<{
44
44
  subagent: z.ZodOptional<z.ZodString>;
45
45
  claudeUuid: z.ZodOptional<z.ZodString>;
46
46
  codexItemId: z.ZodOptional<z.ZodString>;
47
+ streamKey: z.ZodOptional<z.ZodString>;
47
48
  usage: z.ZodOptional<z.ZodObject<{
48
49
  input_tokens: z.ZodNumber;
49
50
  output_tokens: z.ZodNumber;
@@ -139,6 +140,35 @@ declare const sessionEnvelopeSchema: z.ZodObject<{
139
140
  }, z.core.$strip>], "t">;
140
141
  }, z.core.$strip>;
141
142
  type SessionEnvelope = z.infer<typeof sessionEnvelopeSchema>;
143
+ declare const sessionStreamFrameSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
144
+ t: z.ZodLiteral<"block-start">;
145
+ mid: z.ZodString;
146
+ idx: z.ZodNumber;
147
+ kind: z.ZodEnum<{
148
+ text: "text";
149
+ thinking: "thinking";
150
+ }>;
151
+ }, z.core.$strip>, z.ZodObject<{
152
+ t: z.ZodLiteral<"block-delta">;
153
+ mid: z.ZodString;
154
+ idx: z.ZodNumber;
155
+ text: z.ZodString;
156
+ }, z.core.$strip>, z.ZodObject<{
157
+ t: z.ZodLiteral<"block-end">;
158
+ mid: z.ZodString;
159
+ idx: z.ZodNumber;
160
+ }, z.core.$strip>, z.ZodObject<{
161
+ t: z.ZodLiteral<"progress">;
162
+ thinkingTokens: z.ZodOptional<z.ZodNumber>;
163
+ outputTokens: z.ZodOptional<z.ZodNumber>;
164
+ status: z.ZodOptional<z.ZodEnum<{
165
+ requesting: "requesting";
166
+ compacting: "compacting";
167
+ }>>;
168
+ }, z.core.$strip>, z.ZodObject<{
169
+ t: z.ZodLiteral<"turn-end">;
170
+ }, z.core.$strip>], "t">;
171
+ type SessionStreamFrame = z.infer<typeof sessionStreamFrameSchema>;
142
172
 
143
173
  /**
144
174
  * Simplified schema that only validates fields actually used in the codebase
@@ -901,6 +931,20 @@ declare class ApiSessionClient extends EventEmitter {
901
931
  * Send a ping message to keep the connection alive
902
932
  */
903
933
  keepAlive(thinking: boolean, mode: 'local' | 'remote'): void;
934
+ /**
935
+ * B-309: push one live stream frame (thinking/text delta or progress) to
936
+ * this account's web clients.
937
+ *
938
+ * Encrypted with the SESSION key and relayed without being stored —
939
+ * clipboard-push's shape, for clipboard-push's reasons: the relay must not
940
+ * be able to read thinking text, and the session id is stamped by the
941
+ * server from the authenticated connection rather than trusted from here.
942
+ *
943
+ * `volatile` on purpose. A draft that misses the wire while disconnected
944
+ * is worth nothing — the persisted message is still coming, and replaying
945
+ * stale deltas after a reconnect would paint text that has already landed.
946
+ */
947
+ sendStreamFrame(frame: SessionStreamFrame): void;
904
948
  /**
905
949
  * Send session death message
906
950
  */
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-k_ipDb0c.mjs';
1
+ export { A as ApiClient, a as ApiSessionClient, R as RawJSONLinesSchema, c as configuration, l as logger } from './types-C5ewhu1Q.mjs';
2
2
  import 'axios';
3
3
  import 'chalk';
4
4
  import 'node:util';
@@ -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-BOoGJGQc.cjs');
6
+ var index = require('./index-BnRQP3PL.cjs');
7
7
  var limits = require('./limits-KdWKmwtH.cjs');
8
- var persistence = require('./types-BG_5QKX5.cjs');
8
+ var persistence = require('./types-R11tMGyX.cjs');
9
9
  require('chalk');
10
10
  require('node:os');
11
11
  require('node:crypto');
@@ -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-Bn-xsguz.mjs';
4
+ import { p as pushClipboardViaDaemon } from './index-inkhalP5.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-k_ipDb0c.mjs';
6
+ import { l as logger } from './types-C5ewhu1Q.mjs';
7
7
  import 'chalk';
8
8
  import 'node:os';
9
9
  import '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, j as readSettings, e as errorLogMetadata, k as encodeBase64, p as projectPath, d as contentLogMetadata } from './types-k_ipDb0c.mjs';
6
- import { x as GEMINI_API_KEY_ENV, y as GOOGLE_API_KEY_ENV, G as GEMINI_MODEL_ENV, B as BasePermissionHandler, z as BaseReasoningProcessor, h as initialMachineMetadata, j as createSessionMetadata, k as setupOfflineReconnection, n as notifyDaemonSessionStarted, m as MessageQueue2, o as hashObject, C as MessageBuffer, E as CHANGE_TITLE_INSTRUCTION, v as registerKillSessionHandler, u as startHappyServer } from './index-Bn-xsguz.mjs';
7
- import { A as AcpBackend } from './AcpBackend-CeXVb_s_.mjs';
8
- import { readGeminiLocalConfig, determineGeminiModel, getGeminiModelSource, getInitialGeminiModel, saveGeminiModelToConfig } from './config-vGkcq9nM.mjs';
5
+ import { l as logger, h as connectionState, A as ApiClient, j as readSettings, e as errorLogMetadata, k as encodeBase64, p as projectPath, d as contentLogMetadata } from './types-C5ewhu1Q.mjs';
6
+ import { x as GEMINI_API_KEY_ENV, y as GOOGLE_API_KEY_ENV, G as GEMINI_MODEL_ENV, B as BasePermissionHandler, z as BaseReasoningProcessor, h as initialMachineMetadata, j as createSessionMetadata, k as setupOfflineReconnection, n as notifyDaemonSessionStarted, m as MessageQueue2, o as hashObject, C as MessageBuffer, E as CHANGE_TITLE_INSTRUCTION, v as registerKillSessionHandler, u as startHappyServer } from './index-inkhalP5.mjs';
7
+ import { A as AcpBackend } from './AcpBackend-DDEdYVW2.mjs';
8
+ import { readGeminiLocalConfig, determineGeminiModel, getGeminiModelSource, getInitialGeminiModel, saveGeminiModelToConfig } from './config-B_L5vXXu.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-BG_5QKX5.cjs');
8
- var index = require('./index-BOoGJGQc.cjs');
9
- var AcpBackend = require('./AcpBackend-B_olk79F.cjs');
10
- var config = require('./config-BR3tkFL_.cjs');
7
+ var persistence = require('./types-R11tMGyX.cjs');
8
+ var index = require('./index-BnRQP3PL.cjs');
9
+ var AcpBackend = require('./AcpBackend-B3x-gQWP.cjs');
10
+ var config = require('./config-KX6e7GEu.cjs');
11
11
  require('axios');
12
12
  require('chalk');
13
13
  require('node:util');
@@ -5,9 +5,9 @@ var node_child_process = require('node:child_process');
5
5
  var os = require('node:os');
6
6
  var node_fs = require('node:fs');
7
7
  var path = require('node:path');
8
- var persistence = require('./types-BG_5QKX5.cjs');
9
- var AcpSessionManager = require('./AcpSessionManager-uXwWO2Tn.cjs');
10
- var index = require('./index-BOoGJGQc.cjs');
8
+ var persistence = require('./types-R11tMGyX.cjs');
9
+ var AcpSessionManager = require('./AcpSessionManager-DGPLD-go.cjs');
10
+ var index = require('./index-BnRQP3PL.cjs');
11
11
  var WebSocket = require('ws');
12
12
  var ed = require('@noble/ed25519');
13
13
  var sha2_js = require('@noble/hashes/sha2.js');