@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.
- package/dist/{index-pL_ungbb.cjs → index-CfnMIBxL.cjs} +104 -24
- package/dist/{index-BfZGZNIf.mjs → index-jDGb6HV8.mjs} +106 -26
- package/dist/index.cjs +2 -2
- package/dist/index.mjs +2 -2
- package/dist/lib.cjs +1 -1
- package/dist/lib.mjs +1 -1
- package/dist/{list-BFBIw5l1.cjs → list-CkMjnW2p.cjs} +1 -1
- package/dist/{list-MUmi4ZF2.mjs → list-CnFDoVXs.mjs} +1 -1
- package/dist/{prompt-C8uOM9BM.mjs → prompt-BbGwX_Nf.mjs} +1 -1
- package/dist/{prompt-TC7YWFCb.cjs → prompt-DoInQDd4.cjs} +1 -1
- package/dist/{runCodex-DWxgaq32.cjs → runCodex-Ch_mWn45.cjs} +2 -2
- package/dist/{runCodex-CAH8Q5j0.mjs → runCodex-DRSD6qZo.mjs} +2 -2
- package/dist/{types-rIsjYnBh.cjs → types-Bop9J_T5.cjs} +3 -3
- package/dist/{types-D5Yw1ZVE.mjs → types-DyS63_MQ.mjs} +2 -2
- package/package.json +1 -1
|
@@ -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-
|
|
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
|
|
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
|
-
|
|
667
|
-
|
|
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(
|
|
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
|
|
744
|
+
async function readSessionLogIncremental(projectDir, sessionId, fromOffset, failedLineHashes) {
|
|
739
745
|
const expectedSessionFile = node_path.join(projectDir, `${sessionId}.jsonl`);
|
|
740
|
-
|
|
741
|
-
let file;
|
|
746
|
+
let fileSize;
|
|
742
747
|
try {
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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 {
|
|
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
|
|
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
|
-
|
|
644
|
-
|
|
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(
|
|
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
|
|
721
|
+
async function readSessionLogIncremental(projectDir, sessionId, fromOffset, failedLineHashes) {
|
|
716
722
|
const expectedSessionFile = join(projectDir, `${sessionId}.jsonl`);
|
|
717
|
-
|
|
718
|
-
let file;
|
|
723
|
+
let fileSize;
|
|
719
724
|
try {
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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-
|
|
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-
|
|
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-
|
|
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
package/dist/index.mjs
CHANGED
package/dist/lib.cjs
CHANGED
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-
|
|
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,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-
|
|
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-
|
|
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';
|
|
@@ -2,14 +2,14 @@
|
|
|
2
2
|
|
|
3
3
|
var ink = require('ink');
|
|
4
4
|
var React = require('react');
|
|
5
|
-
var types = require('./types-
|
|
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-
|
|
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-
|
|
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-
|
|
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.
|
|
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
|
-
|
|
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-
|
|
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.
|
|
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
|
-
|
|
632
|
+
return;
|
|
633
633
|
}
|
|
634
634
|
const truncateStrings = (obj) => {
|
|
635
635
|
if (typeof obj === "string") {
|