@zhigang1992/happy-cli 0.13.7 → 0.13.8

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.
@@ -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 types = require('./types-rIsjYnBh.cjs');
6
+ var types = require('./types-Bop9J_T5.cjs');
7
7
  var node_child_process = require('node:child_process');
8
8
  var node_path = require('node:path');
9
9
  var node_readline = require('node:readline');
@@ -648,8 +648,11 @@ async function createSessionScanner(opts) {
648
648
  let currentSessionId = null;
649
649
  let watchers = /* @__PURE__ */ new Map();
650
650
  let processedMessageKeys = /* @__PURE__ */ new Set();
651
+ let sessionOffsets = /* @__PURE__ */ new Map();
652
+ let failedLineHashes = /* @__PURE__ */ new Set();
651
653
  if (opts.sessionId) {
652
- let messages = await readSessionLog(projectDir, opts.sessionId);
654
+ let { messages, newOffset } = await readSessionLogIncremental(projectDir, opts.sessionId, 0, failedLineHashes);
655
+ sessionOffsets.set(opts.sessionId, newOffset);
653
656
  for (let m of messages) {
654
657
  processedMessageKeys.add(messageKey(m));
655
658
  }
@@ -663,13 +666,16 @@ async function createSessionScanner(opts) {
663
666
  sessions.push(currentSessionId);
664
667
  }
665
668
  for (let session of sessions) {
666
- for (let file of await readSessionLog(projectDir, session)) {
667
- let key = messageKey(file);
669
+ let offset = sessionOffsets.get(session) ?? 0;
670
+ let { messages, newOffset } = await readSessionLogIncremental(projectDir, session, offset, failedLineHashes);
671
+ sessionOffsets.set(session, newOffset);
672
+ for (let msg of messages) {
673
+ let key = messageKey(msg);
668
674
  if (processedMessageKeys.has(key)) {
669
675
  continue;
670
676
  }
671
677
  processedMessageKeys.add(key);
672
- opts.onMessage(file);
678
+ opts.onMessage(msg);
673
679
  }
674
680
  }
675
681
  for (let p of sessions) {
@@ -735,36 +741,60 @@ function messageKey(message) {
735
741
  throw Error();
736
742
  }
737
743
  }
738
- async function readSessionLog(projectDir, sessionId) {
744
+ async function readSessionLogIncremental(projectDir, sessionId, fromOffset, failedLineHashes) {
739
745
  const expectedSessionFile = node_path.join(projectDir, `${sessionId}.jsonl`);
740
- types.logger.debug(`[SESSION_SCANNER] Reading session file: ${expectedSessionFile}`);
741
- let file;
746
+ let fileSize;
742
747
  try {
743
- file = await promises.readFile(expectedSessionFile, "utf-8");
744
- } catch (error) {
745
- types.logger.debug(`[SESSION_SCANNER] Session file not found: ${expectedSessionFile}`);
746
- return [];
748
+ const fileStat = await promises.stat(expectedSessionFile);
749
+ fileSize = fileStat.size;
750
+ } catch {
751
+ return { messages: [], newOffset: fromOffset };
752
+ }
753
+ if (fileSize <= fromOffset) {
754
+ return { messages: [], newOffset: fromOffset };
755
+ }
756
+ let newContent;
757
+ try {
758
+ const fh = await promises.open(expectedSessionFile, "r");
759
+ try {
760
+ const buf = Buffer.alloc(fileSize - fromOffset);
761
+ await fh.read(buf, 0, buf.length, fromOffset);
762
+ newContent = buf.toString("utf-8");
763
+ } finally {
764
+ await fh.close();
765
+ }
766
+ } catch {
767
+ return { messages: [], newOffset: fromOffset };
747
768
  }
748
- let lines = file.split("\n");
749
769
  let messages = [];
770
+ let lines = newContent.split("\n");
750
771
  for (let l of lines) {
772
+ let trimmed = l.trim();
773
+ if (trimmed === "") {
774
+ continue;
775
+ }
751
776
  try {
752
- if (l.trim() === "") {
753
- continue;
754
- }
755
- let message = JSON.parse(l);
777
+ let message = JSON.parse(trimmed);
756
778
  let parsed = types.RawJSONLinesSchema.safeParse(message);
757
779
  if (!parsed.success) {
758
- types.logger.debugLargeJson(`[SESSION_SCANNER] Failed to parse message`, message);
780
+ let lineHash = trimmed.slice(0, 200) + ":" + trimmed.length;
781
+ if (!failedLineHashes.has(lineHash)) {
782
+ failedLineHashes.add(lineHash);
783
+ types.logger.debugLargeJson(`[SESSION_SCANNER] Failed to parse message`, message);
784
+ }
759
785
  continue;
760
786
  }
761
787
  messages.push(parsed.data);
762
788
  } catch (e) {
763
- types.logger.debug(`[SESSION_SCANNER] Error processing message: ${e}`);
789
+ let lineHash = trimmed.slice(0, 200) + ":" + trimmed.length;
790
+ if (!failedLineHashes.has(lineHash)) {
791
+ failedLineHashes.add(lineHash);
792
+ types.logger.debug(`[SESSION_SCANNER] Error processing message: ${e}`);
793
+ }
764
794
  continue;
765
795
  }
766
796
  }
767
- return messages;
797
+ return { messages, newOffset: fileSize };
768
798
  }
769
799
 
770
800
  async function claudeLocalLauncher(session) {
@@ -1184,7 +1214,7 @@ class AbortError extends Error {
1184
1214
  }
1185
1215
  }
1186
1216
 
1187
- 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-pL_ungbb.cjs', document.baseURI).href)));
1217
+ 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-CfnMIBxL.cjs', document.baseURI).href)));
1188
1218
  const __dirname$1 = node_path.join(__filename$1, "..");
1189
1219
  function getGlobalClaudeVersion() {
1190
1220
  try {
@@ -3136,6 +3166,38 @@ async function claudeRemoteLauncher(session) {
3136
3166
  cwd: session.path,
3137
3167
  version: process.env.npm_package_version
3138
3168
  }, permissionHandler.getResponses());
3169
+ const sentMessageUuids = /* @__PURE__ */ new Set();
3170
+ function getMessageDedupeKey(msg) {
3171
+ if (msg.type === "summary") {
3172
+ return `summary:${msg.leafUuid}:${msg.summary}`;
3173
+ }
3174
+ if (msg.type === "system") {
3175
+ return `system:${msg.uuid}`;
3176
+ }
3177
+ try {
3178
+ const content = JSON.stringify(msg.message?.content ?? "");
3179
+ const contentKey = content.slice(0, 100) + ":" + content.length;
3180
+ return `${msg.type}:${contentKey}`;
3181
+ } catch {
3182
+ return msg.uuid ?? null;
3183
+ }
3184
+ }
3185
+ const sessionScanner = await createSessionScanner({
3186
+ sessionId: session.sessionId,
3187
+ workingDirectory: session.path,
3188
+ onMessage: (logMessage) => {
3189
+ const dedupeKey = getMessageDedupeKey(logMessage);
3190
+ if (dedupeKey && sentMessageUuids.has(dedupeKey)) {
3191
+ types.logger.debug(`[remote]: Scanner skipping (already sent): ${logMessage.type}`);
3192
+ return;
3193
+ }
3194
+ if (dedupeKey) {
3195
+ sentMessageUuids.add(dedupeKey);
3196
+ }
3197
+ types.logger.debug(`[remote]: Scanner forwarding message: ${logMessage.type}`);
3198
+ messageQueue.enqueue(logMessage);
3199
+ }
3200
+ });
3139
3201
  let ongoingToolCalls = /* @__PURE__ */ new Map();
3140
3202
  function onMessage(message) {
3141
3203
  formatClaudeMessageForInk(message, messageBuffer);
@@ -3164,6 +3226,10 @@ async function claudeRemoteLauncher(session) {
3164
3226
  }
3165
3227
  const logMessage = sdkToLogConverter.convert(message);
3166
3228
  if (logMessage) {
3229
+ const dedupeKey = getMessageDedupeKey(logMessage);
3230
+ if (dedupeKey) {
3231
+ sentMessageUuids.add(dedupeKey);
3232
+ }
3167
3233
  if (logMessage.type === "user" && logMessage.message?.content) {
3168
3234
  const content = Array.isArray(logMessage.message.content) ? logMessage.message.content : [];
3169
3235
  for (let i = 0; i < content.length; i++) {
@@ -3190,6 +3256,14 @@ async function claudeRemoteLauncher(session) {
3190
3256
  }
3191
3257
  }
3192
3258
  }
3259
+ if (logMessage.type === "user") {
3260
+ const content = logMessage.message?.content;
3261
+ const hasToolResult = Array.isArray(content) && content.some((c) => c.type === "tool_result");
3262
+ if (!hasToolResult) {
3263
+ types.logger.debug("[remote]: Skipping user text message (scanner will handle)");
3264
+ return;
3265
+ }
3266
+ }
3193
3267
  if (logMessage.type === "assistant" && message.type === "assistant") {
3194
3268
  const assistantMsg = message;
3195
3269
  const toolCallIds = [];
@@ -3220,6 +3294,10 @@ async function claudeRemoteLauncher(session) {
3220
3294
  if (c.type === "tool_use" && c.name === "Task" && c.input && typeof c.input.prompt === "string") {
3221
3295
  const logMessage2 = sdkToLogConverter.convertSidechainUserMessage(c.id, c.input.prompt);
3222
3296
  if (logMessage2) {
3297
+ const dedupeKey2 = getMessageDedupeKey(logMessage2);
3298
+ if (dedupeKey2) {
3299
+ sentMessageUuids.add(dedupeKey2);
3300
+ }
3223
3301
  messageQueue.enqueue(logMessage2);
3224
3302
  }
3225
3303
  }
@@ -3299,6 +3377,7 @@ async function claudeRemoteLauncher(session) {
3299
3377
  onSessionFound: (sessionId) => {
3300
3378
  sdkToLogConverter.updateSessionId(sessionId);
3301
3379
  session.onSessionFound(sessionId);
3380
+ sessionScanner.onNewSession(sessionId);
3302
3381
  },
3303
3382
  onThinkingChange: session.onThinkingChange,
3304
3383
  claudeEnvVars: session.claudeEnvVars,
@@ -3394,6 +3473,7 @@ async function claudeRemoteLauncher(session) {
3394
3473
  }
3395
3474
  }
3396
3475
  } finally {
3476
+ await sessionScanner.cleanup();
3397
3477
  permissionHandler.reset();
3398
3478
  process.stdin.off("data", abort);
3399
3479
  if (process.stdin.isTTY) {
@@ -7048,7 +7128,7 @@ async function handleConnectVendor(vendor, displayName) {
7048
7128
  return;
7049
7129
  } else if (subcommand === "codex") {
7050
7130
  try {
7051
- const { runCodex } = await Promise.resolve().then(function () { return require('./runCodex-DWxgaq32.cjs'); });
7131
+ const { runCodex } = await Promise.resolve().then(function () { return require('./runCodex-Ch_mWn45.cjs'); });
7052
7132
  let startedBy = void 0;
7053
7133
  for (let i = 1; i < args.length; i++) {
7054
7134
  if (args[i] === "--started-by") {
@@ -7093,7 +7173,7 @@ async function handleConnectVendor(vendor, displayName) {
7093
7173
  } else if (subcommand === "list") {
7094
7174
  try {
7095
7175
  const { credentials } = await authAndSetupMachineIfNeeded();
7096
- const { listSessions } = await Promise.resolve().then(function () { return require('./list-BFBIw5l1.cjs'); });
7176
+ const { listSessions } = await Promise.resolve().then(function () { return require('./list-CkMjnW2p.cjs'); });
7097
7177
  let sessionId;
7098
7178
  let titleFilter;
7099
7179
  let recentMsgs;
@@ -7195,7 +7275,7 @@ Examples:
7195
7275
  process.exit(1);
7196
7276
  }
7197
7277
  const { credentials } = await authAndSetupMachineIfNeeded();
7198
- const { promptSession } = await Promise.resolve().then(function () { return require('./prompt-TC7YWFCb.cjs'); });
7278
+ const { promptSession } = await Promise.resolve().then(function () { return require('./prompt-DoInQDd4.cjs'); });
7199
7279
  await promptSession(credentials, sessionId, promptText, timeoutMinutes ?? void 0);
7200
7280
  } catch (error) {
7201
7281
  console.error(chalk.red("Error:"), error instanceof Error ? error.message : "Unknown error");
@@ -1,7 +1,7 @@
1
1
  import chalk from 'chalk';
2
2
  import os$1, { homedir } from 'node:os';
3
3
  import { randomUUID, randomBytes, createHmac } from 'node:crypto';
4
- import { l as logger, p as projectPath, j as backoff, k as delay, R as RawJSONLinesSchema, m as AsyncLock, c as configuration, n as readDaemonState, o as clearDaemonState, i as packageJson, r as readSettings, q as readCredentials, g as encodeBase64, u as updateSettings, s as encodeBase64Url, d as decodeBase64, w as writeCredentialsLegacy, t as writeCredentialsDataKey, v as acquireDaemonLock, x as writeDaemonState, A as ApiClient, y as releaseDaemonLock, z as authChallenge, B as clearCredentials, C as clearMachineId, D as getLatestDaemonLog } from './types-D5Yw1ZVE.mjs';
4
+ import { l as logger, p as projectPath, j as backoff, k as delay, R as RawJSONLinesSchema, m as AsyncLock, c as configuration, n as readDaemonState, o as clearDaemonState, i as packageJson, r as readSettings, q as readCredentials, g as encodeBase64, u as updateSettings, s as encodeBase64Url, d as decodeBase64, w as writeCredentialsLegacy, t as writeCredentialsDataKey, v as acquireDaemonLock, x as writeDaemonState, A as ApiClient, y as releaseDaemonLock, z as authChallenge, B as clearCredentials, C as clearMachineId, D as getLatestDaemonLog } from './types-DyS63_MQ.mjs';
5
5
  import { spawn, execSync, exec as exec$1, execFileSync } from 'node:child_process';
6
6
  import { resolve, join, extname, basename as basename$1 } from 'node:path';
7
7
  import { createInterface } from 'node:readline';
@@ -10,7 +10,7 @@ import { exec, spawn as spawn$1, execSync as execSync$1 } from 'child_process';
10
10
  import { promisify } from 'util';
11
11
  import { existsSync as existsSync$1, readFileSync as readFileSync$1, writeFileSync as writeFileSync$1, chmodSync, unlinkSync as unlinkSync$1 } from 'fs';
12
12
  import { join as join$1, dirname, basename } from 'path';
13
- import { readFile } from 'node:fs/promises';
13
+ import { stat, open } from 'node:fs/promises';
14
14
  import fs, { watch, access } from 'fs/promises';
15
15
  import { useStdout, useInput, Box, Text, render } from 'ink';
16
16
  import React, { useState, useRef, useEffect, useCallback } from 'react';
@@ -28,7 +28,7 @@ import psList from 'ps-list';
28
28
  import spawn$2 from 'cross-spawn';
29
29
  import * as tmp from 'tmp';
30
30
  import qrcode from 'qrcode-terminal';
31
- import open from 'open';
31
+ import open$1 from 'open';
32
32
  import fastify from 'fastify';
33
33
  import { z } from 'zod';
34
34
  import { validatorCompiler, serializerCompiler } from 'fastify-type-provider-zod';
@@ -625,8 +625,11 @@ async function createSessionScanner(opts) {
625
625
  let currentSessionId = null;
626
626
  let watchers = /* @__PURE__ */ new Map();
627
627
  let processedMessageKeys = /* @__PURE__ */ new Set();
628
+ let sessionOffsets = /* @__PURE__ */ new Map();
629
+ let failedLineHashes = /* @__PURE__ */ new Set();
628
630
  if (opts.sessionId) {
629
- let messages = await readSessionLog(projectDir, opts.sessionId);
631
+ let { messages, newOffset } = await readSessionLogIncremental(projectDir, opts.sessionId, 0, failedLineHashes);
632
+ sessionOffsets.set(opts.sessionId, newOffset);
630
633
  for (let m of messages) {
631
634
  processedMessageKeys.add(messageKey(m));
632
635
  }
@@ -640,13 +643,16 @@ async function createSessionScanner(opts) {
640
643
  sessions.push(currentSessionId);
641
644
  }
642
645
  for (let session of sessions) {
643
- for (let file of await readSessionLog(projectDir, session)) {
644
- let key = messageKey(file);
646
+ let offset = sessionOffsets.get(session) ?? 0;
647
+ let { messages, newOffset } = await readSessionLogIncremental(projectDir, session, offset, failedLineHashes);
648
+ sessionOffsets.set(session, newOffset);
649
+ for (let msg of messages) {
650
+ let key = messageKey(msg);
645
651
  if (processedMessageKeys.has(key)) {
646
652
  continue;
647
653
  }
648
654
  processedMessageKeys.add(key);
649
- opts.onMessage(file);
655
+ opts.onMessage(msg);
650
656
  }
651
657
  }
652
658
  for (let p of sessions) {
@@ -712,36 +718,60 @@ function messageKey(message) {
712
718
  throw Error();
713
719
  }
714
720
  }
715
- async function readSessionLog(projectDir, sessionId) {
721
+ async function readSessionLogIncremental(projectDir, sessionId, fromOffset, failedLineHashes) {
716
722
  const expectedSessionFile = join(projectDir, `${sessionId}.jsonl`);
717
- logger.debug(`[SESSION_SCANNER] Reading session file: ${expectedSessionFile}`);
718
- let file;
723
+ let fileSize;
719
724
  try {
720
- file = await readFile(expectedSessionFile, "utf-8");
721
- } catch (error) {
722
- logger.debug(`[SESSION_SCANNER] Session file not found: ${expectedSessionFile}`);
723
- return [];
725
+ const fileStat = await stat(expectedSessionFile);
726
+ fileSize = fileStat.size;
727
+ } catch {
728
+ return { messages: [], newOffset: fromOffset };
729
+ }
730
+ if (fileSize <= fromOffset) {
731
+ return { messages: [], newOffset: fromOffset };
732
+ }
733
+ let newContent;
734
+ try {
735
+ const fh = await open(expectedSessionFile, "r");
736
+ try {
737
+ const buf = Buffer.alloc(fileSize - fromOffset);
738
+ await fh.read(buf, 0, buf.length, fromOffset);
739
+ newContent = buf.toString("utf-8");
740
+ } finally {
741
+ await fh.close();
742
+ }
743
+ } catch {
744
+ return { messages: [], newOffset: fromOffset };
724
745
  }
725
- let lines = file.split("\n");
726
746
  let messages = [];
747
+ let lines = newContent.split("\n");
727
748
  for (let l of lines) {
749
+ let trimmed = l.trim();
750
+ if (trimmed === "") {
751
+ continue;
752
+ }
728
753
  try {
729
- if (l.trim() === "") {
730
- continue;
731
- }
732
- let message = JSON.parse(l);
754
+ let message = JSON.parse(trimmed);
733
755
  let parsed = RawJSONLinesSchema.safeParse(message);
734
756
  if (!parsed.success) {
735
- logger.debugLargeJson(`[SESSION_SCANNER] Failed to parse message`, message);
757
+ let lineHash = trimmed.slice(0, 200) + ":" + trimmed.length;
758
+ if (!failedLineHashes.has(lineHash)) {
759
+ failedLineHashes.add(lineHash);
760
+ logger.debugLargeJson(`[SESSION_SCANNER] Failed to parse message`, message);
761
+ }
736
762
  continue;
737
763
  }
738
764
  messages.push(parsed.data);
739
765
  } catch (e) {
740
- logger.debug(`[SESSION_SCANNER] Error processing message: ${e}`);
766
+ let lineHash = trimmed.slice(0, 200) + ":" + trimmed.length;
767
+ if (!failedLineHashes.has(lineHash)) {
768
+ failedLineHashes.add(lineHash);
769
+ logger.debug(`[SESSION_SCANNER] Error processing message: ${e}`);
770
+ }
741
771
  continue;
742
772
  }
743
773
  }
744
- return messages;
774
+ return { messages, newOffset: fileSize };
745
775
  }
746
776
 
747
777
  async function claudeLocalLauncher(session) {
@@ -3113,6 +3143,38 @@ async function claudeRemoteLauncher(session) {
3113
3143
  cwd: session.path,
3114
3144
  version: process.env.npm_package_version
3115
3145
  }, permissionHandler.getResponses());
3146
+ const sentMessageUuids = /* @__PURE__ */ new Set();
3147
+ function getMessageDedupeKey(msg) {
3148
+ if (msg.type === "summary") {
3149
+ return `summary:${msg.leafUuid}:${msg.summary}`;
3150
+ }
3151
+ if (msg.type === "system") {
3152
+ return `system:${msg.uuid}`;
3153
+ }
3154
+ try {
3155
+ const content = JSON.stringify(msg.message?.content ?? "");
3156
+ const contentKey = content.slice(0, 100) + ":" + content.length;
3157
+ return `${msg.type}:${contentKey}`;
3158
+ } catch {
3159
+ return msg.uuid ?? null;
3160
+ }
3161
+ }
3162
+ const sessionScanner = await createSessionScanner({
3163
+ sessionId: session.sessionId,
3164
+ workingDirectory: session.path,
3165
+ onMessage: (logMessage) => {
3166
+ const dedupeKey = getMessageDedupeKey(logMessage);
3167
+ if (dedupeKey && sentMessageUuids.has(dedupeKey)) {
3168
+ logger.debug(`[remote]: Scanner skipping (already sent): ${logMessage.type}`);
3169
+ return;
3170
+ }
3171
+ if (dedupeKey) {
3172
+ sentMessageUuids.add(dedupeKey);
3173
+ }
3174
+ logger.debug(`[remote]: Scanner forwarding message: ${logMessage.type}`);
3175
+ messageQueue.enqueue(logMessage);
3176
+ }
3177
+ });
3116
3178
  let ongoingToolCalls = /* @__PURE__ */ new Map();
3117
3179
  function onMessage(message) {
3118
3180
  formatClaudeMessageForInk(message, messageBuffer);
@@ -3141,6 +3203,10 @@ async function claudeRemoteLauncher(session) {
3141
3203
  }
3142
3204
  const logMessage = sdkToLogConverter.convert(message);
3143
3205
  if (logMessage) {
3206
+ const dedupeKey = getMessageDedupeKey(logMessage);
3207
+ if (dedupeKey) {
3208
+ sentMessageUuids.add(dedupeKey);
3209
+ }
3144
3210
  if (logMessage.type === "user" && logMessage.message?.content) {
3145
3211
  const content = Array.isArray(logMessage.message.content) ? logMessage.message.content : [];
3146
3212
  for (let i = 0; i < content.length; i++) {
@@ -3167,6 +3233,14 @@ async function claudeRemoteLauncher(session) {
3167
3233
  }
3168
3234
  }
3169
3235
  }
3236
+ if (logMessage.type === "user") {
3237
+ const content = logMessage.message?.content;
3238
+ const hasToolResult = Array.isArray(content) && content.some((c) => c.type === "tool_result");
3239
+ if (!hasToolResult) {
3240
+ logger.debug("[remote]: Skipping user text message (scanner will handle)");
3241
+ return;
3242
+ }
3243
+ }
3170
3244
  if (logMessage.type === "assistant" && message.type === "assistant") {
3171
3245
  const assistantMsg = message;
3172
3246
  const toolCallIds = [];
@@ -3197,6 +3271,10 @@ async function claudeRemoteLauncher(session) {
3197
3271
  if (c.type === "tool_use" && c.name === "Task" && c.input && typeof c.input.prompt === "string") {
3198
3272
  const logMessage2 = sdkToLogConverter.convertSidechainUserMessage(c.id, c.input.prompt);
3199
3273
  if (logMessage2) {
3274
+ const dedupeKey2 = getMessageDedupeKey(logMessage2);
3275
+ if (dedupeKey2) {
3276
+ sentMessageUuids.add(dedupeKey2);
3277
+ }
3200
3278
  messageQueue.enqueue(logMessage2);
3201
3279
  }
3202
3280
  }
@@ -3276,6 +3354,7 @@ async function claudeRemoteLauncher(session) {
3276
3354
  onSessionFound: (sessionId) => {
3277
3355
  sdkToLogConverter.updateSessionId(sessionId);
3278
3356
  session.onSessionFound(sessionId);
3357
+ sessionScanner.onNewSession(sessionId);
3279
3358
  },
3280
3359
  onThinkingChange: session.onThinkingChange,
3281
3360
  claudeEnvVars: session.claudeEnvVars,
@@ -3371,6 +3450,7 @@ async function claudeRemoteLauncher(session) {
3371
3450
  }
3372
3451
  }
3373
3452
  } finally {
3453
+ await sessionScanner.cleanup();
3374
3454
  permissionHandler.reset();
3375
3455
  process.stdin.off("data", abort);
3376
3456
  if (process.stdin.isTTY) {
@@ -4536,7 +4616,7 @@ async function openBrowser(url) {
4536
4616
  return false;
4537
4617
  }
4538
4618
  logger.debug(`[browser] Attempting to open URL: ${url}`);
4539
- await open(url);
4619
+ await open$1(url);
4540
4620
  logger.debug("[browser] Browser opened successfully");
4541
4621
  return true;
4542
4622
  } catch (error) {
@@ -7025,7 +7105,7 @@ async function handleConnectVendor(vendor, displayName) {
7025
7105
  return;
7026
7106
  } else if (subcommand === "codex") {
7027
7107
  try {
7028
- const { runCodex } = await import('./runCodex-CAH8Q5j0.mjs');
7108
+ const { runCodex } = await import('./runCodex-DRSD6qZo.mjs');
7029
7109
  let startedBy = void 0;
7030
7110
  for (let i = 1; i < args.length; i++) {
7031
7111
  if (args[i] === "--started-by") {
@@ -7070,7 +7150,7 @@ async function handleConnectVendor(vendor, displayName) {
7070
7150
  } else if (subcommand === "list") {
7071
7151
  try {
7072
7152
  const { credentials } = await authAndSetupMachineIfNeeded();
7073
- const { listSessions } = await import('./list-MUmi4ZF2.mjs');
7153
+ const { listSessions } = await import('./list-CnFDoVXs.mjs');
7074
7154
  let sessionId;
7075
7155
  let titleFilter;
7076
7156
  let recentMsgs;
@@ -7172,7 +7252,7 @@ Examples:
7172
7252
  process.exit(1);
7173
7253
  }
7174
7254
  const { credentials } = await authAndSetupMachineIfNeeded();
7175
- const { promptSession } = await import('./prompt-C8uOM9BM.mjs');
7255
+ const { promptSession } = await import('./prompt-BbGwX_Nf.mjs');
7176
7256
  await promptSession(credentials, sessionId, promptText, timeoutMinutes ?? void 0);
7177
7257
  } catch (error) {
7178
7258
  console.error(chalk.red("Error:"), error instanceof Error ? error.message : "Unknown error");
package/dist/index.cjs CHANGED
@@ -1,8 +1,8 @@
1
1
  'use strict';
2
2
 
3
3
  require('chalk');
4
- require('./index-pL_ungbb.cjs');
5
- require('./types-rIsjYnBh.cjs');
4
+ require('./index-CfnMIBxL.cjs');
5
+ require('./types-Bop9J_T5.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-BfZGZNIf.mjs';
3
- import './types-D5Yw1ZVE.mjs';
2
+ import './index-jDGb6HV8.mjs';
3
+ import './types-DyS63_MQ.mjs';
4
4
  import 'zod';
5
5
  import 'node:child_process';
6
6
  import 'node:os';
package/dist/lib.cjs CHANGED
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- var types = require('./types-rIsjYnBh.cjs');
3
+ var types = require('./types-Bop9J_T5.cjs');
4
4
  require('axios');
5
5
  require('chalk');
6
6
  require('fs');
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-D5Yw1ZVE.mjs';
1
+ export { A as ApiClient, a as ApiSessionClient, R as RawJSONLinesSchema, c as configuration, l as logger } from './types-DyS63_MQ.mjs';
2
2
  import 'axios';
3
3
  import 'chalk';
4
4
  import 'fs';
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- var types = require('./types-rIsjYnBh.cjs');
3
+ var types = require('./types-Bop9J_T5.cjs');
4
4
  var axios = require('axios');
5
5
  var fs = require('fs');
6
6
  var path = require('path');
@@ -1,4 +1,4 @@
1
- import { c as configuration, l as logger, d as decodeBase64, b as decrypt, f as formatTimeAgo, e as libsodiumDecryptFromPublicKey } from './types-D5Yw1ZVE.mjs';
1
+ import { c as configuration, l as logger, d as decodeBase64, b as decrypt, f as formatTimeAgo, e as libsodiumDecryptFromPublicKey } from './types-DyS63_MQ.mjs';
2
2
  import axios from 'axios';
3
3
  import { existsSync, readdirSync, statSync, readFileSync } from 'fs';
4
4
  import { join } from 'path';
@@ -1,4 +1,4 @@
1
- import { c as configuration, b as decrypt, d as decodeBase64, l as logger, g as encodeBase64, h as encrypt } from './types-D5Yw1ZVE.mjs';
1
+ import { c as configuration, b as decrypt, d as decodeBase64, l as logger, g as encodeBase64, h as encrypt } from './types-DyS63_MQ.mjs';
2
2
  import axios from 'axios';
3
3
  import { io } from 'socket.io-client';
4
4
  import 'chalk';
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- var types = require('./types-rIsjYnBh.cjs');
3
+ var types = require('./types-Bop9J_T5.cjs');
4
4
  var axios = require('axios');
5
5
  var socket_ioClient = require('socket.io-client');
6
6
  require('chalk');
@@ -2,14 +2,14 @@
2
2
 
3
3
  var ink = require('ink');
4
4
  var React = require('react');
5
- var types = require('./types-rIsjYnBh.cjs');
5
+ var types = require('./types-Bop9J_T5.cjs');
6
6
  var index_js = require('@modelcontextprotocol/sdk/client/index.js');
7
7
  var stdio_js = require('@modelcontextprotocol/sdk/client/stdio.js');
8
8
  var z = require('zod');
9
9
  var types_js = require('@modelcontextprotocol/sdk/types.js');
10
10
  var child_process = require('child_process');
11
11
  var node_crypto = require('node:crypto');
12
- var index = require('./index-pL_ungbb.cjs');
12
+ var index = require('./index-CfnMIBxL.cjs');
13
13
  var os = require('node:os');
14
14
  var node_path = require('node:path');
15
15
  var fs = require('node:fs');
@@ -1,13 +1,13 @@
1
1
  import { useStdout, useInput, Box, Text, render } from 'ink';
2
2
  import React, { useState, useRef, useEffect, useCallback } from 'react';
3
- import { l as logger, A as ApiClient, r as readSettings, p as projectPath, c as configuration, i as packageJson } from './types-D5Yw1ZVE.mjs';
3
+ import { l as logger, A as ApiClient, r as readSettings, p as projectPath, c as configuration, i as packageJson } from './types-DyS63_MQ.mjs';
4
4
  import { Client } from '@modelcontextprotocol/sdk/client/index.js';
5
5
  import { StdioClientTransport } from '@modelcontextprotocol/sdk/client/stdio.js';
6
6
  import { z } from 'zod';
7
7
  import { ElicitRequestSchema } from '@modelcontextprotocol/sdk/types.js';
8
8
  import { execSync } from 'child_process';
9
9
  import { randomUUID } from 'node:crypto';
10
- import { i as initialMachineMetadata, n as notifyDaemonSessionStarted, M as MessageQueue2, h as hashObject, r as registerKillSessionHandler, a as MessageBuffer, s as startHappyServer, t as trimIdent, b as stopCaffeinate } from './index-BfZGZNIf.mjs';
10
+ import { i as initialMachineMetadata, n as notifyDaemonSessionStarted, M as MessageQueue2, h as hashObject, r as registerKillSessionHandler, a as MessageBuffer, s as startHappyServer, t as trimIdent, b as stopCaffeinate } from './index-jDGb6HV8.mjs';
11
11
  import os from 'node:os';
12
12
  import { resolve, join } from 'node:path';
13
13
  import fs from 'node:fs';
@@ -41,7 +41,7 @@ function _interopNamespaceDefault(e) {
41
41
  var z__namespace = /*#__PURE__*/_interopNamespaceDefault(z);
42
42
 
43
43
  var name = "@zhigang1992/happy-cli";
44
- var version = "0.13.7";
44
+ var version = "0.13.8";
45
45
  var description = "Mobile and Web client for Claude Code and Codex";
46
46
  var author = "Kirill Dubovitskiy";
47
47
  var license = "MIT";
@@ -650,7 +650,7 @@ class Logger {
650
650
  }
651
651
  debugLargeJson(message, object, maxStringLength = 100, maxArrayLength = 10) {
652
652
  if (!process.env.DEBUG) {
653
- this.debug(`In production, skipping message inspection`);
653
+ return;
654
654
  }
655
655
  const truncateStrings = (obj) => {
656
656
  if (typeof obj === "string") {
@@ -1150,7 +1150,7 @@ class RpcHandlerManager {
1150
1150
  }
1151
1151
  }
1152
1152
 
1153
- const __dirname$1 = path.dirname(url.fileURLToPath((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('types-rIsjYnBh.cjs', document.baseURI).href))));
1153
+ const __dirname$1 = path.dirname(url.fileURLToPath((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('types-Bop9J_T5.cjs', document.baseURI).href))));
1154
1154
  function projectPath() {
1155
1155
  const path$1 = path.resolve(__dirname$1, "..");
1156
1156
  return path$1;
@@ -20,7 +20,7 @@ import { fileURLToPath } from 'url';
20
20
  import { Expo } from 'expo-server-sdk';
21
21
 
22
22
  var name = "@zhigang1992/happy-cli";
23
- var version = "0.13.7";
23
+ var version = "0.13.8";
24
24
  var description = "Mobile and Web client for Claude Code and Codex";
25
25
  var author = "Kirill Dubovitskiy";
26
26
  var license = "MIT";
@@ -629,7 +629,7 @@ class Logger {
629
629
  }
630
630
  debugLargeJson(message, object, maxStringLength = 100, maxArrayLength = 10) {
631
631
  if (!process.env.DEBUG) {
632
- this.debug(`In production, skipping message inspection`);
632
+ return;
633
633
  }
634
634
  const truncateStrings = (obj) => {
635
635
  if (typeof obj === "string") {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zhigang1992/happy-cli",
3
- "version": "0.13.7",
3
+ "version": "0.13.8",
4
4
  "description": "Mobile and Web client for Claude Code and Codex",
5
5
  "author": "Kirill Dubovitskiy",
6
6
  "license": "MIT",