happy-imou-cloud 2.0.1 → 2.0.2
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/{BaseReasoningProcessor-01KqA3Kz.cjs → BaseReasoningProcessor-B6tJ_eL5.cjs} +2 -2
- package/dist/{BaseReasoningProcessor-DQE2l7Xu.mjs → BaseReasoningProcessor-D8VhEbs2.mjs} +2 -2
- package/dist/{api-B8v4tczT.cjs → api-D2Njw9Im.cjs} +56 -3
- package/dist/{api-B5Ui8Fw0.mjs → api-MYhAGPLn.mjs} +56 -3
- package/dist/{command-D8yNlaDo.cjs → command-CVldr51S.cjs} +3 -3
- package/dist/{command-BfIuJmeo.mjs → command-nmK6O-ab.mjs} +3 -3
- package/dist/{index-BByhFIIq.mjs → index-B97L7qLD.mjs} +15 -17
- package/dist/{index-BOqJ9hwi.cjs → index-Bg-YziG2.cjs} +17 -19
- package/dist/index.cjs +3 -3
- package/dist/index.mjs +3 -3
- package/dist/lib.cjs +1 -1
- package/dist/lib.d.cts +6 -0
- package/dist/lib.d.mts +6 -0
- package/dist/lib.mjs +1 -1
- package/dist/{persistence-C33AMdtv.cjs → persistence-D_2GkJAO.cjs} +28 -6
- package/dist/{persistence-CzpZpiL3.mjs → persistence-Dkm7rm8k.mjs} +29 -7
- package/dist/{registerKillSessionHandler-BtSK7IOa.mjs → registerKillSessionHandler-5GbrO0FM.mjs} +2 -2
- package/dist/{registerKillSessionHandler-BkzQulD9.cjs → registerKillSessionHandler-BAXmJQRt.cjs} +2 -2
- package/dist/{runClaude-CNVufgZb.cjs → runClaude-B-GNEkKg.cjs} +228 -44
- package/dist/{runClaude-C_WLfM6c.mjs → runClaude-Cii3R2Fv.mjs} +229 -45
- package/dist/{runCodex-8eWjTPJr.mjs → runCodex-C--ZwAhl.mjs} +5 -5
- package/dist/{runCodex-Dzy8anlX.cjs → runCodex-CPHyGwj9.cjs} +5 -5
- package/dist/{runGemini-nbr0mm-S.mjs → runGemini-CQp7Nuzn.mjs} +5 -5
- package/dist/{runGemini-CgsVKP7m.cjs → runGemini-DaDz1bzQ.cjs} +5 -5
- package/package.json +1 -2
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import os, { homedir } from 'node:os';
|
|
2
2
|
import { randomUUID } from 'node:crypto';
|
|
3
|
-
import { l as logger, d as backoff, f as delay, g as AsyncLock, c as configuration, b as connectionState, A as ApiClient, p as packageJson, i as isAuthenticationRequiredError, s as startOfflineReconnection } from './api-
|
|
4
|
-
import { e as getProjectPath, h as claudeLocal, E as ExitCodeError, j as isBun, k as trimIdent, l as claudeCheckSession, p as projectPath, m as getEnvironmentInfo, i as initialMachineMetadata, b as stopCaffeinate, n as notifyDaemonSessionStarted, o as startCaffeinate } from './index-
|
|
3
|
+
import { l as logger, d as backoff, f as delay, g as AsyncLock, c as configuration, b as connectionState, A as ApiClient, p as packageJson, i as isAuthenticationRequiredError, s as startOfflineReconnection } from './api-MYhAGPLn.mjs';
|
|
4
|
+
import { e as getProjectPath, h as claudeLocal, E as ExitCodeError, j as isBun, k as trimIdent, l as claudeCheckSession, p as projectPath, m as getEnvironmentInfo, i as initialMachineMetadata, b as stopCaffeinate, n as notifyDaemonSessionStarted, o as startCaffeinate } from './index-B97L7qLD.mjs';
|
|
5
5
|
import { F as Future } from './future-xRdLl3vf.mjs';
|
|
6
6
|
import { R as RawJSONLinesSchema } from './types-CiliQpqS.mjs';
|
|
7
|
-
import { join, resolve } from 'node:path';
|
|
7
|
+
import { dirname, basename, join, resolve } from 'node:path';
|
|
8
8
|
import { readFile } from 'node:fs/promises';
|
|
9
|
-
import { watch, access } from 'fs/promises';
|
|
9
|
+
import { stat, watch, access } from 'fs/promises';
|
|
10
10
|
import { useStdout, useInput, Box, Text, render } from 'ink';
|
|
11
|
-
import { a as MessageBuffer, M as MessageQueue2, h as hashObject, r as registerKillSessionHandler } from './registerKillSessionHandler-
|
|
11
|
+
import { a as MessageBuffer, M as MessageQueue2, h as hashObject, r as registerKillSessionHandler } from './registerKillSessionHandler-5GbrO0FM.mjs';
|
|
12
12
|
import React, { useState, useRef, useEffect, useCallback } from 'react';
|
|
13
13
|
import { execSync, spawn } from 'node:child_process';
|
|
14
14
|
import { createInterface } from 'node:readline';
|
|
@@ -21,7 +21,7 @@ import 'tweetnacl';
|
|
|
21
21
|
import 'expo-server-sdk';
|
|
22
22
|
import 'chalk';
|
|
23
23
|
import { isDeepStrictEqual } from 'node:util';
|
|
24
|
-
import { readSettings } from './persistence-
|
|
24
|
+
import { readSettings } from './persistence-Dkm7rm8k.mjs';
|
|
25
25
|
import { createServer } from 'node:http';
|
|
26
26
|
import 'fs';
|
|
27
27
|
import 'zod';
|
|
@@ -59,6 +59,7 @@ class Session {
|
|
|
59
59
|
/** JavaScript runtime to use for spawning Claude Code (default: 'node') */
|
|
60
60
|
jsRuntime;
|
|
61
61
|
sessionId;
|
|
62
|
+
transcriptPath = null;
|
|
62
63
|
mode = "local";
|
|
63
64
|
thinking = false;
|
|
64
65
|
/** Callbacks to be notified when session ID is found/changed */
|
|
@@ -112,15 +113,33 @@ class Session {
|
|
|
112
113
|
* Updates internal state, syncs to API metadata, and notifies
|
|
113
114
|
* all registered callbacks (e.g., SessionScanner) about the change.
|
|
114
115
|
*/
|
|
115
|
-
onSessionFound = (sessionId) => {
|
|
116
|
+
onSessionFound = (sessionId, hookData) => {
|
|
117
|
+
const nextTranscriptPathRaw = hookData?.transcript_path ?? hookData?.transcriptPath;
|
|
118
|
+
const nextTranscriptPath = typeof nextTranscriptPathRaw === "string" ? nextTranscriptPathRaw : null;
|
|
119
|
+
const previousSessionId = this.sessionId;
|
|
120
|
+
const previousTranscriptPath = this.transcriptPath;
|
|
116
121
|
this.sessionId = sessionId;
|
|
122
|
+
if (previousSessionId !== sessionId) {
|
|
123
|
+
this.transcriptPath = nextTranscriptPath;
|
|
124
|
+
} else if (nextTranscriptPath) {
|
|
125
|
+
this.transcriptPath = nextTranscriptPath;
|
|
126
|
+
}
|
|
117
127
|
this.client.updateMetadata((metadata) => ({
|
|
118
128
|
...metadata,
|
|
119
|
-
claudeSessionId: sessionId
|
|
129
|
+
claudeSessionId: sessionId,
|
|
130
|
+
claudeTranscriptPath: this.transcriptPath || void 0
|
|
120
131
|
}));
|
|
121
|
-
logger.debug(`[Session] Claude
|
|
132
|
+
logger.debug(`[Session] Claude session info updated: sessionId=${sessionId}, transcriptPath=${this.transcriptPath ?? "none"}`);
|
|
133
|
+
const didTranscriptPathChange = nextTranscriptPath !== null && nextTranscriptPath !== previousTranscriptPath;
|
|
134
|
+
if (previousSessionId === sessionId && !didTranscriptPathChange) {
|
|
135
|
+
return;
|
|
136
|
+
}
|
|
137
|
+
const info = {
|
|
138
|
+
sessionId,
|
|
139
|
+
transcriptPath: this.transcriptPath
|
|
140
|
+
};
|
|
122
141
|
for (const callback of this.sessionFoundCallbacks) {
|
|
123
|
-
callback(
|
|
142
|
+
callback(info);
|
|
124
143
|
}
|
|
125
144
|
};
|
|
126
145
|
/**
|
|
@@ -143,6 +162,7 @@ class Session {
|
|
|
143
162
|
*/
|
|
144
163
|
clearSessionId = () => {
|
|
145
164
|
this.sessionId = null;
|
|
165
|
+
this.transcriptPath = null;
|
|
146
166
|
logger.debug("[Session] Session ID cleared");
|
|
147
167
|
};
|
|
148
168
|
/**
|
|
@@ -247,9 +267,51 @@ class InvalidateSync {
|
|
|
247
267
|
|
|
248
268
|
function startFileWatcher(file, onFileChange) {
|
|
249
269
|
const abortController = new AbortController();
|
|
270
|
+
const parentDir = dirname(file);
|
|
271
|
+
const targetName = basename(file);
|
|
250
272
|
void (async () => {
|
|
251
273
|
while (true) {
|
|
252
274
|
try {
|
|
275
|
+
try {
|
|
276
|
+
await stat(file);
|
|
277
|
+
} catch (e) {
|
|
278
|
+
if (abortController.signal.aborted) {
|
|
279
|
+
return;
|
|
280
|
+
}
|
|
281
|
+
if (e?.code === "ENOENT") {
|
|
282
|
+
logger.debug(`[FILE_WATCHER] Waiting for file to exist: ${file}`);
|
|
283
|
+
const dirWatcher = watch(parentDir, { persistent: true, signal: abortController.signal });
|
|
284
|
+
try {
|
|
285
|
+
await stat(file);
|
|
286
|
+
} catch (err) {
|
|
287
|
+
if (err?.code !== "ENOENT") {
|
|
288
|
+
throw err;
|
|
289
|
+
}
|
|
290
|
+
for await (const event of dirWatcher) {
|
|
291
|
+
if (abortController.signal.aborted) {
|
|
292
|
+
return;
|
|
293
|
+
}
|
|
294
|
+
const name = typeof event?.filename === "string" ? String(event.filename) : null;
|
|
295
|
+
if (name && name !== targetName) {
|
|
296
|
+
continue;
|
|
297
|
+
}
|
|
298
|
+
try {
|
|
299
|
+
await stat(file);
|
|
300
|
+
logger.debug(`[FILE_WATCHER] File appeared: ${file}`);
|
|
301
|
+
break;
|
|
302
|
+
} catch (nextErr) {
|
|
303
|
+
if (nextErr?.code === "ENOENT") {
|
|
304
|
+
continue;
|
|
305
|
+
}
|
|
306
|
+
throw nextErr;
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
} else {
|
|
311
|
+
throw e;
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
onFileChange(file);
|
|
253
315
|
logger.debug(`[FILE_WATCHER] Starting watcher for ${file}`);
|
|
254
316
|
const watcher = watch(file, { persistent: true, signal: abortController.signal });
|
|
255
317
|
for await (const event of watcher) {
|
|
@@ -279,19 +341,67 @@ const INTERNAL_CLAUDE_EVENT_TYPES = /* @__PURE__ */ new Set([
|
|
|
279
341
|
"queue-operation"
|
|
280
342
|
]);
|
|
281
343
|
async function createSessionScanner(opts) {
|
|
282
|
-
const
|
|
344
|
+
const initialProjectDir = getProjectPath(opts.workingDirectory);
|
|
345
|
+
let projectDirOverride = null;
|
|
346
|
+
const sessionFileOverrides = /* @__PURE__ */ new Map();
|
|
347
|
+
const transcriptMissingWarningMs = opts.transcriptMissingWarningMs ?? 5e3;
|
|
348
|
+
const warnedMissingTranscripts = /* @__PURE__ */ new Set();
|
|
349
|
+
const missingTranscriptTimers = /* @__PURE__ */ new Map();
|
|
350
|
+
function effectiveProjectDir() {
|
|
351
|
+
return projectDirOverride ?? initialProjectDir;
|
|
352
|
+
}
|
|
353
|
+
function getSessionFilePath(sessionId) {
|
|
354
|
+
const override = sessionFileOverrides.get(sessionId);
|
|
355
|
+
return override ?? join(effectiveProjectDir(), `${sessionId}.jsonl`);
|
|
356
|
+
}
|
|
357
|
+
function scheduleTranscriptMissingWarning(sessionId) {
|
|
358
|
+
if (!opts.onTranscriptMissing) {
|
|
359
|
+
return;
|
|
360
|
+
}
|
|
361
|
+
if (!Number.isFinite(transcriptMissingWarningMs) || transcriptMissingWarningMs <= 0) {
|
|
362
|
+
return;
|
|
363
|
+
}
|
|
364
|
+
if (warnedMissingTranscripts.has(sessionId) || missingTranscriptTimers.has(sessionId)) {
|
|
365
|
+
return;
|
|
366
|
+
}
|
|
367
|
+
const timeoutId = setTimeout(async () => {
|
|
368
|
+
missingTranscriptTimers.delete(sessionId);
|
|
369
|
+
if (warnedMissingTranscripts.has(sessionId)) {
|
|
370
|
+
return;
|
|
371
|
+
}
|
|
372
|
+
const filePath = getSessionFilePath(sessionId);
|
|
373
|
+
try {
|
|
374
|
+
await readFile(filePath, "utf-8");
|
|
375
|
+
return;
|
|
376
|
+
} catch {
|
|
377
|
+
}
|
|
378
|
+
warnedMissingTranscripts.add(sessionId);
|
|
379
|
+
try {
|
|
380
|
+
opts.onTranscriptMissing?.({ sessionId, filePath });
|
|
381
|
+
} catch (err) {
|
|
382
|
+
logger.debug("[SESSION_SCANNER] onTranscriptMissing callback threw:", err);
|
|
383
|
+
}
|
|
384
|
+
}, transcriptMissingWarningMs);
|
|
385
|
+
missingTranscriptTimers.set(sessionId, timeoutId);
|
|
386
|
+
}
|
|
283
387
|
let finishedSessions = /* @__PURE__ */ new Set();
|
|
284
388
|
let pendingSessions = /* @__PURE__ */ new Set();
|
|
285
389
|
let currentSessionId = null;
|
|
286
390
|
let watchers = /* @__PURE__ */ new Map();
|
|
287
391
|
let processedMessageKeys = /* @__PURE__ */ new Set();
|
|
392
|
+
if (opts.sessionId && typeof opts.transcriptPath === "string" && opts.transcriptPath.trim()) {
|
|
393
|
+
const transcriptPath = opts.transcriptPath.trim();
|
|
394
|
+
sessionFileOverrides.set(opts.sessionId, transcriptPath);
|
|
395
|
+
projectDirOverride = dirname(transcriptPath);
|
|
396
|
+
}
|
|
288
397
|
if (opts.sessionId) {
|
|
289
|
-
let messages = await readSessionLog(
|
|
398
|
+
let messages = await readSessionLog(getSessionFilePath(opts.sessionId));
|
|
290
399
|
logger.debug(`[SESSION_SCANNER] Marking ${messages.length} existing messages as processed from session ${opts.sessionId}`);
|
|
291
400
|
for (let m of messages) {
|
|
292
401
|
processedMessageKeys.add(messageKey(m));
|
|
293
402
|
}
|
|
294
403
|
currentSessionId = opts.sessionId;
|
|
404
|
+
scheduleTranscriptMissingWarning(opts.sessionId);
|
|
295
405
|
}
|
|
296
406
|
const sync = new InvalidateSync(async () => {
|
|
297
407
|
let sessions = [];
|
|
@@ -307,7 +417,7 @@ async function createSessionScanner(opts) {
|
|
|
307
417
|
}
|
|
308
418
|
}
|
|
309
419
|
for (let session of sessions) {
|
|
310
|
-
const sessionMessages = await readSessionLog(
|
|
420
|
+
const sessionMessages = await readSessionLog(getSessionFilePath(session));
|
|
311
421
|
let skipped = 0;
|
|
312
422
|
let sent = 0;
|
|
313
423
|
for (let file of sessionMessages) {
|
|
@@ -332,11 +442,27 @@ async function createSessionScanner(opts) {
|
|
|
332
442
|
}
|
|
333
443
|
}
|
|
334
444
|
for (let p of sessions) {
|
|
335
|
-
|
|
445
|
+
const desiredPath = getSessionFilePath(p);
|
|
446
|
+
const existing = watchers.get(p);
|
|
447
|
+
if (!existing) {
|
|
336
448
|
logger.debug(`[SESSION_SCANNER] Starting watcher for session: ${p}`);
|
|
337
|
-
watchers.set(p,
|
|
338
|
-
|
|
339
|
-
|
|
449
|
+
watchers.set(p, {
|
|
450
|
+
filePath: desiredPath,
|
|
451
|
+
stop: startFileWatcher(desiredPath, () => {
|
|
452
|
+
sync.invalidate();
|
|
453
|
+
})
|
|
454
|
+
});
|
|
455
|
+
continue;
|
|
456
|
+
}
|
|
457
|
+
if (existing.filePath !== desiredPath) {
|
|
458
|
+
logger.debug(`[SESSION_SCANNER] Restarting watcher for session: ${p} (${existing.filePath} -> ${desiredPath})`);
|
|
459
|
+
existing.stop();
|
|
460
|
+
watchers.set(p, {
|
|
461
|
+
filePath: desiredPath,
|
|
462
|
+
stop: startFileWatcher(desiredPath, () => {
|
|
463
|
+
sync.invalidate();
|
|
464
|
+
})
|
|
465
|
+
});
|
|
340
466
|
}
|
|
341
467
|
}
|
|
342
468
|
});
|
|
@@ -348,23 +474,55 @@ async function createSessionScanner(opts) {
|
|
|
348
474
|
cleanup: async () => {
|
|
349
475
|
clearInterval(intervalId);
|
|
350
476
|
for (let w of watchers.values()) {
|
|
351
|
-
w();
|
|
477
|
+
w.stop();
|
|
352
478
|
}
|
|
353
479
|
watchers.clear();
|
|
480
|
+
for (const timeoutId of missingTranscriptTimers.values()) {
|
|
481
|
+
clearTimeout(timeoutId);
|
|
482
|
+
}
|
|
483
|
+
missingTranscriptTimers.clear();
|
|
354
484
|
await sync.invalidateAndAwait();
|
|
355
485
|
sync.stop();
|
|
356
486
|
},
|
|
357
|
-
onNewSession: (
|
|
487
|
+
onNewSession: (arg) => {
|
|
488
|
+
const sessionId = typeof arg === "string" ? arg : arg.sessionId;
|
|
489
|
+
const transcriptPathRaw = typeof arg === "string" ? null : arg.transcriptPath;
|
|
490
|
+
const transcriptPath = typeof transcriptPathRaw === "string" && transcriptPathRaw.trim() ? transcriptPathRaw.trim() : null;
|
|
491
|
+
let didUpdatePaths = false;
|
|
492
|
+
if (transcriptPath) {
|
|
493
|
+
const previousOverride = sessionFileOverrides.get(sessionId);
|
|
494
|
+
if (previousOverride !== transcriptPath) {
|
|
495
|
+
sessionFileOverrides.set(sessionId, transcriptPath);
|
|
496
|
+
didUpdatePaths = true;
|
|
497
|
+
}
|
|
498
|
+
const nextProjectDir = dirname(transcriptPath);
|
|
499
|
+
if (projectDirOverride !== nextProjectDir) {
|
|
500
|
+
projectDirOverride = nextProjectDir;
|
|
501
|
+
didUpdatePaths = true;
|
|
502
|
+
}
|
|
503
|
+
}
|
|
358
504
|
if (currentSessionId === sessionId) {
|
|
359
|
-
|
|
505
|
+
if (didUpdatePaths) {
|
|
506
|
+
sync.invalidate();
|
|
507
|
+
} else {
|
|
508
|
+
logger.debug(`[SESSION_SCANNER] New session: ${sessionId} is the same as the current session, skipping`);
|
|
509
|
+
}
|
|
360
510
|
return;
|
|
361
511
|
}
|
|
362
512
|
if (finishedSessions.has(sessionId)) {
|
|
363
|
-
|
|
513
|
+
if (didUpdatePaths) {
|
|
514
|
+
sync.invalidate();
|
|
515
|
+
} else {
|
|
516
|
+
logger.debug(`[SESSION_SCANNER] New session: ${sessionId} is already finished, skipping`);
|
|
517
|
+
}
|
|
364
518
|
return;
|
|
365
519
|
}
|
|
366
520
|
if (pendingSessions.has(sessionId)) {
|
|
367
|
-
|
|
521
|
+
if (didUpdatePaths) {
|
|
522
|
+
sync.invalidate();
|
|
523
|
+
} else {
|
|
524
|
+
logger.debug(`[SESSION_SCANNER] New session: ${sessionId} is already pending, skipping`);
|
|
525
|
+
}
|
|
368
526
|
return;
|
|
369
527
|
}
|
|
370
528
|
if (currentSessionId) {
|
|
@@ -372,6 +530,7 @@ async function createSessionScanner(opts) {
|
|
|
372
530
|
}
|
|
373
531
|
logger.debug(`[SESSION_SCANNER] New session: ${sessionId}`);
|
|
374
532
|
currentSessionId = sessionId;
|
|
533
|
+
scheduleTranscriptMissingWarning(sessionId);
|
|
375
534
|
sync.invalidate();
|
|
376
535
|
}
|
|
377
536
|
};
|
|
@@ -389,14 +548,13 @@ function messageKey(message) {
|
|
|
389
548
|
throw Error();
|
|
390
549
|
}
|
|
391
550
|
}
|
|
392
|
-
async function readSessionLog(
|
|
393
|
-
|
|
394
|
-
logger.debug(`[SESSION_SCANNER] Reading session file: ${expectedSessionFile}`);
|
|
551
|
+
async function readSessionLog(sessionFilePath) {
|
|
552
|
+
logger.debug(`[SESSION_SCANNER] Reading session file: ${sessionFilePath}`);
|
|
395
553
|
let file;
|
|
396
554
|
try {
|
|
397
|
-
file = await readFile(
|
|
555
|
+
file = await readFile(sessionFilePath, "utf-8");
|
|
398
556
|
} catch (error) {
|
|
399
|
-
logger.debug(`[SESSION_SCANNER] Session file not found: ${
|
|
557
|
+
logger.debug(`[SESSION_SCANNER] Session file not found: ${sessionFilePath}`);
|
|
400
558
|
return [];
|
|
401
559
|
}
|
|
402
560
|
let lines = file.split("\n");
|
|
@@ -426,15 +584,25 @@ async function readSessionLog(projectDir, sessionId) {
|
|
|
426
584
|
async function claudeLocalLauncher(session) {
|
|
427
585
|
const scanner = await createSessionScanner({
|
|
428
586
|
sessionId: session.sessionId,
|
|
587
|
+
transcriptPath: session.transcriptPath,
|
|
429
588
|
workingDirectory: session.path,
|
|
430
589
|
onMessage: (message) => {
|
|
431
590
|
if (message.type !== "summary") {
|
|
432
591
|
session.client.sendClaudeSessionMessage(message);
|
|
433
592
|
}
|
|
593
|
+
},
|
|
594
|
+
onTranscriptMissing: () => {
|
|
595
|
+
session.client.sendSessionEvent({
|
|
596
|
+
type: "message",
|
|
597
|
+
message: "Claude transcript file not found yet, waiting for it to appear..."
|
|
598
|
+
});
|
|
434
599
|
}
|
|
435
600
|
});
|
|
436
|
-
const scannerSessionCallback = (
|
|
437
|
-
scanner.onNewSession(
|
|
601
|
+
const scannerSessionCallback = (info) => {
|
|
602
|
+
scanner.onNewSession({
|
|
603
|
+
sessionId: info.sessionId,
|
|
604
|
+
transcriptPath: info.transcriptPath
|
|
605
|
+
});
|
|
438
606
|
};
|
|
439
607
|
session.addSessionFoundCallback(scannerSessionCallback);
|
|
440
608
|
let exitReason = null;
|
|
@@ -472,7 +640,6 @@ async function claudeLocalLauncher(session) {
|
|
|
472
640
|
}
|
|
473
641
|
const handleSessionStart = (sessionId) => {
|
|
474
642
|
session.onSessionFound(sessionId);
|
|
475
|
-
scanner.onNewSession(sessionId);
|
|
476
643
|
};
|
|
477
644
|
while (true) {
|
|
478
645
|
if (exitReason) {
|
|
@@ -1421,7 +1588,7 @@ const systemPrompt = (() => {
|
|
|
1421
1588
|
|
|
1422
1589
|
async function claudeRemote(opts) {
|
|
1423
1590
|
let startFrom = opts.sessionId;
|
|
1424
|
-
if (opts.sessionId && !claudeCheckSession(opts.sessionId, opts.path)) {
|
|
1591
|
+
if (opts.sessionId && !claudeCheckSession(opts.sessionId, opts.path, opts.transcriptPath)) {
|
|
1425
1592
|
startFrom = null;
|
|
1426
1593
|
}
|
|
1427
1594
|
if (!startFrom && opts.claudeArgs) {
|
|
@@ -1523,11 +1690,14 @@ async function claudeRemote(opts) {
|
|
|
1523
1690
|
updateThinking(true);
|
|
1524
1691
|
const systemInit = message;
|
|
1525
1692
|
if (systemInit.session_id) {
|
|
1526
|
-
|
|
1527
|
-
|
|
1528
|
-
const found = await awaitFileExist(
|
|
1693
|
+
const transcriptPath = opts.transcriptPath && opts.sessionId === systemInit.session_id ? opts.transcriptPath : join(getProjectPath(opts.path), `${systemInit.session_id}.jsonl`);
|
|
1694
|
+
logger.debug(`[claudeRemote] Waiting for session file to be written to disk: ${transcriptPath}`);
|
|
1695
|
+
const found = await awaitFileExist(transcriptPath);
|
|
1529
1696
|
logger.debug(`[claudeRemote] Session file found: ${systemInit.session_id} ${found}`);
|
|
1530
|
-
opts.onSessionFound(systemInit.session_id
|
|
1697
|
+
opts.onSessionFound(systemInit.session_id, {
|
|
1698
|
+
transcript_path: transcriptPath,
|
|
1699
|
+
transcriptPath
|
|
1700
|
+
});
|
|
1531
1701
|
}
|
|
1532
1702
|
}
|
|
1533
1703
|
if (message.type === "result") {
|
|
@@ -1980,11 +2150,21 @@ function formatClaudeMessageForInk(message, messageBuffer, onAssistantResult) {
|
|
|
1980
2150
|
case "assistant": {
|
|
1981
2151
|
const assistantMsg = message;
|
|
1982
2152
|
if (assistantMsg.message && assistantMsg.message.content) {
|
|
1983
|
-
|
|
2153
|
+
let assistantHeaderShown = false;
|
|
1984
2154
|
for (const block of assistantMsg.message.content) {
|
|
1985
|
-
if (block.type === "
|
|
2155
|
+
if (block.type === "thinking" && typeof block.thinking === "string" && block.thinking.trim()) {
|
|
2156
|
+
messageBuffer.addMessage(`[Thinking] ${block.thinking}`, "status");
|
|
2157
|
+
} else if (block.type === "text") {
|
|
2158
|
+
if (!assistantHeaderShown) {
|
|
2159
|
+
messageBuffer.addMessage("\u{1F916} Assistant:", "assistant");
|
|
2160
|
+
assistantHeaderShown = true;
|
|
2161
|
+
}
|
|
1986
2162
|
messageBuffer.addMessage(block.text || "", "assistant");
|
|
1987
2163
|
} else if (block.type === "tool_use") {
|
|
2164
|
+
if (!assistantHeaderShown) {
|
|
2165
|
+
messageBuffer.addMessage("\u{1F916} Assistant:", "assistant");
|
|
2166
|
+
assistantHeaderShown = true;
|
|
2167
|
+
}
|
|
1988
2168
|
messageBuffer.addMessage(`\u{1F527} Tool: ${block.name}`, "tool");
|
|
1989
2169
|
if (block.input) {
|
|
1990
2170
|
const inputStr = JSON.stringify(block.input, null, 2);
|
|
@@ -2630,6 +2810,7 @@ async function claudeRemoteLauncher(session) {
|
|
|
2630
2810
|
try {
|
|
2631
2811
|
const remoteResult = await claudeRemote({
|
|
2632
2812
|
sessionId: session.sessionId,
|
|
2813
|
+
transcriptPath: session.transcriptPath,
|
|
2633
2814
|
path: session.path,
|
|
2634
2815
|
allowedTools: session.allowedTools ?? [],
|
|
2635
2816
|
mcpServers: session.mcpServers,
|
|
@@ -2663,9 +2844,9 @@ async function claudeRemoteLauncher(session) {
|
|
|
2663
2844
|
}
|
|
2664
2845
|
return null;
|
|
2665
2846
|
},
|
|
2666
|
-
onSessionFound: (sessionId) => {
|
|
2847
|
+
onSessionFound: (sessionId, data) => {
|
|
2667
2848
|
sdkToLogConverter.updateSessionId(sessionId);
|
|
2668
|
-
session.onSessionFound(sessionId);
|
|
2849
|
+
session.onSessionFound(sessionId, data);
|
|
2669
2850
|
},
|
|
2670
2851
|
onThinkingChange: session.onThinkingChange,
|
|
2671
2852
|
claudeEnvVars: session.claudeEnvVars,
|
|
@@ -2854,13 +3035,20 @@ async function startHookServer(options) {
|
|
|
2854
3035
|
}
|
|
2855
3036
|
clearTimeout(timeout);
|
|
2856
3037
|
const body = Buffer.concat(chunks).toString("utf-8");
|
|
2857
|
-
logger.debug("[hookServer] Received session hook:", body);
|
|
2858
3038
|
let data = {};
|
|
2859
3039
|
try {
|
|
2860
3040
|
data = JSON.parse(body);
|
|
2861
3041
|
} catch (parseError) {
|
|
2862
3042
|
logger.debug("[hookServer] Failed to parse hook data as JSON:", parseError);
|
|
2863
3043
|
}
|
|
3044
|
+
logger.debug("[hookServer] Received session hook", {
|
|
3045
|
+
sessionId: data.session_id || data.sessionId || null,
|
|
3046
|
+
transcriptPath: data.transcript_path || data.transcriptPath || null,
|
|
3047
|
+
cwd: data.cwd,
|
|
3048
|
+
hookEventName: data.hook_event_name,
|
|
3049
|
+
source: data.source,
|
|
3050
|
+
bodyLength: body.length
|
|
3051
|
+
});
|
|
2864
3052
|
const sessionId = data.session_id || data.sessionId;
|
|
2865
3053
|
if (sessionId) {
|
|
2866
3054
|
logger.debug(`[hookServer] Session hook received session ID: ${sessionId}`);
|
|
@@ -3062,11 +3250,7 @@ async function runClaude(credentials, options = {}) {
|
|
|
3062
3250
|
onSessionHook: (sessionId, data) => {
|
|
3063
3251
|
logger.debug(`[START] Session hook received: ${sessionId}`, data);
|
|
3064
3252
|
if (currentSession) {
|
|
3065
|
-
|
|
3066
|
-
if (previousSessionId !== sessionId) {
|
|
3067
|
-
logger.debug(`[START] Claude session ID changed: ${previousSessionId} -> ${sessionId}`);
|
|
3068
|
-
currentSession.onSessionFound(sessionId);
|
|
3069
|
-
}
|
|
3253
|
+
currentSession.onSessionFound(sessionId, data);
|
|
3070
3254
|
}
|
|
3071
3255
|
}
|
|
3072
3256
|
});
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { randomUUID } from 'node:crypto';
|
|
2
|
-
import { l as logger, b as connectionState, A as ApiClient, i as isAuthenticationRequiredError } from './api-
|
|
3
|
-
import { readSettings } from './persistence-
|
|
4
|
-
import { f as formatDisplayMessage, v as validateCodexAcpSpawn, d as createCodexBackend, t as truncateDisplayMessage, b as stopCaffeinate, i as initialMachineMetadata, n as notifyDaemonSessionStarted } from './index-
|
|
5
|
-
import { B as BasePermissionHandler, g as getPendingInteractionTimeoutMs, I as INTERACTION_SUPERSEDED_ERROR, b as INTERACTION_TIMED_OUT_ERROR, a as BaseReasoningProcessor, c as createSessionMetadata, s as setupOfflineReconnection } from './BaseReasoningProcessor-
|
|
6
|
-
import { a as MessageBuffer, r as registerKillSessionHandler, M as MessageQueue2, h as hashObject } from './registerKillSessionHandler-
|
|
2
|
+
import { l as logger, b as connectionState, A as ApiClient, i as isAuthenticationRequiredError } from './api-MYhAGPLn.mjs';
|
|
3
|
+
import { readSettings } from './persistence-Dkm7rm8k.mjs';
|
|
4
|
+
import { f as formatDisplayMessage, v as validateCodexAcpSpawn, d as createCodexBackend, t as truncateDisplayMessage, b as stopCaffeinate, i as initialMachineMetadata, n as notifyDaemonSessionStarted } from './index-B97L7qLD.mjs';
|
|
5
|
+
import { B as BasePermissionHandler, g as getPendingInteractionTimeoutMs, I as INTERACTION_SUPERSEDED_ERROR, b as INTERACTION_TIMED_OUT_ERROR, a as BaseReasoningProcessor, c as createSessionMetadata, s as setupOfflineReconnection } from './BaseReasoningProcessor-D8VhEbs2.mjs';
|
|
6
|
+
import { a as MessageBuffer, r as registerKillSessionHandler, M as MessageQueue2, h as hashObject } from './registerKillSessionHandler-5GbrO0FM.mjs';
|
|
7
7
|
import { F as Future } from './future-xRdLl3vf.mjs';
|
|
8
8
|
import { spawn, execFileSync } from 'node:child_process';
|
|
9
9
|
import fs from 'node:fs';
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
var node_crypto = require('node:crypto');
|
|
4
|
-
var api = require('./api-
|
|
5
|
-
var persistence = require('./persistence-
|
|
6
|
-
var index = require('./index-
|
|
7
|
-
var BaseReasoningProcessor = require('./BaseReasoningProcessor-
|
|
8
|
-
var registerKillSessionHandler = require('./registerKillSessionHandler-
|
|
4
|
+
var api = require('./api-D2Njw9Im.cjs');
|
|
5
|
+
var persistence = require('./persistence-D_2GkJAO.cjs');
|
|
6
|
+
var index = require('./index-Bg-YziG2.cjs');
|
|
7
|
+
var BaseReasoningProcessor = require('./BaseReasoningProcessor-B6tJ_eL5.cjs');
|
|
8
|
+
var registerKillSessionHandler = require('./registerKillSessionHandler-BAXmJQRt.cjs');
|
|
9
9
|
var future = require('./future-Dq4Ha1Dn.cjs');
|
|
10
10
|
var node_child_process = require('node:child_process');
|
|
11
11
|
var fs = require('node:fs');
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
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
|
-
import { l as logger, b as connectionState, A as ApiClient, i as isAuthenticationRequiredError } from './api-
|
|
5
|
-
import { readSettings } from './persistence-
|
|
6
|
-
import { B as BasePermissionHandler, a as BaseReasoningProcessor, c as createSessionMetadata, s as setupOfflineReconnection } from './BaseReasoningProcessor-
|
|
7
|
-
import { i as initialMachineMetadata, n as notifyDaemonSessionStarted, g as getInitialGeminiModel, r as readGeminiLocalConfig, G as GEMINI_MODEL_ENV, s as saveGeminiModelToConfig, a as createGeminiBackend, b as stopCaffeinate } from './index-
|
|
8
|
-
import { M as MessageQueue2, h as hashObject, a as MessageBuffer, r as registerKillSessionHandler } from './registerKillSessionHandler-
|
|
4
|
+
import { l as logger, b as connectionState, A as ApiClient, i as isAuthenticationRequiredError } from './api-MYhAGPLn.mjs';
|
|
5
|
+
import { readSettings } from './persistence-Dkm7rm8k.mjs';
|
|
6
|
+
import { B as BasePermissionHandler, a as BaseReasoningProcessor, c as createSessionMetadata, s as setupOfflineReconnection } from './BaseReasoningProcessor-D8VhEbs2.mjs';
|
|
7
|
+
import { i as initialMachineMetadata, n as notifyDaemonSessionStarted, g as getInitialGeminiModel, r as readGeminiLocalConfig, G as GEMINI_MODEL_ENV, s as saveGeminiModelToConfig, a as createGeminiBackend, b as stopCaffeinate } from './index-B97L7qLD.mjs';
|
|
8
|
+
import { M as MessageQueue2, h as hashObject, a as MessageBuffer, r as registerKillSessionHandler } from './registerKillSessionHandler-5GbrO0FM.mjs';
|
|
9
9
|
import 'axios';
|
|
10
10
|
import 'chalk';
|
|
11
11
|
import 'fs';
|
|
@@ -3,11 +3,11 @@
|
|
|
3
3
|
var ink = require('ink');
|
|
4
4
|
var React = require('react');
|
|
5
5
|
var node_crypto = require('node:crypto');
|
|
6
|
-
var api = require('./api-
|
|
7
|
-
var persistence = require('./persistence-
|
|
8
|
-
var BaseReasoningProcessor = require('./BaseReasoningProcessor-
|
|
9
|
-
var index = require('./index-
|
|
10
|
-
var registerKillSessionHandler = require('./registerKillSessionHandler-
|
|
6
|
+
var api = require('./api-D2Njw9Im.cjs');
|
|
7
|
+
var persistence = require('./persistence-D_2GkJAO.cjs');
|
|
8
|
+
var BaseReasoningProcessor = require('./BaseReasoningProcessor-B6tJ_eL5.cjs');
|
|
9
|
+
var index = require('./index-Bg-YziG2.cjs');
|
|
10
|
+
var registerKillSessionHandler = require('./registerKillSessionHandler-BAXmJQRt.cjs');
|
|
11
11
|
require('axios');
|
|
12
12
|
require('chalk');
|
|
13
13
|
require('fs');
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "happy-imou-cloud",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.2",
|
|
4
4
|
"description": "hicloud - Imou 企业定制版。关键是 happy!移动端远程 AI 编程工具,支持 Claude Code、Codex 和 Gemini CLI",
|
|
5
5
|
"author": "long.zhu",
|
|
6
6
|
"license": "MIT",
|
|
@@ -84,7 +84,6 @@
|
|
|
84
84
|
},
|
|
85
85
|
"dependencies": {
|
|
86
86
|
"@agentclientprotocol/sdk": "^0.14.1",
|
|
87
|
-
"@modelcontextprotocol/sdk": "^1.25.3",
|
|
88
87
|
"@stablelib/base64": "^2.0.1",
|
|
89
88
|
"@stablelib/hex": "^2.0.1",
|
|
90
89
|
"@types/cross-spawn": "^6.0.6",
|