happy-imou-cloud 2.0.1 → 2.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (27) hide show
  1. package/dist/{BaseReasoningProcessor-DQE2l7Xu.mjs → BaseReasoningProcessor-B37yOHxo.mjs} +2 -2
  2. package/dist/{BaseReasoningProcessor-01KqA3Kz.cjs → BaseReasoningProcessor-_wxlqKB8.cjs} +4 -4
  3. package/dist/{api-B8v4tczT.cjs → api-D9dIR956.cjs} +97 -44
  4. package/dist/{api-B5Ui8Fw0.mjs → api-DpQIC-DJ.mjs} +56 -3
  5. package/dist/{command-D8yNlaDo.cjs → command-CdXv1zNF.cjs} +3 -3
  6. package/dist/{command-BfIuJmeo.mjs → command-DRqrBuHM.mjs} +3 -3
  7. package/dist/{index-BByhFIIq.mjs → index-CriPm_z9.mjs} +15 -17
  8. package/dist/{index-BOqJ9hwi.cjs → index-LYPXVO_L.cjs} +98 -100
  9. package/dist/index.cjs +3 -3
  10. package/dist/index.mjs +3 -3
  11. package/dist/lib.cjs +1 -1
  12. package/dist/lib.d.cts +6 -0
  13. package/dist/lib.d.mts +6 -0
  14. package/dist/lib.mjs +1 -1
  15. package/dist/{persistence-CzpZpiL3.mjs → persistence-CqgPgbzN.mjs} +29 -7
  16. package/dist/{persistence-C33AMdtv.cjs → persistence-PzKU0QCa.cjs} +54 -32
  17. package/dist/{registerKillSessionHandler-BkzQulD9.cjs → registerKillSessionHandler-BDBPoQSA.cjs} +2 -2
  18. package/dist/{registerKillSessionHandler-BtSK7IOa.mjs → registerKillSessionHandler-C3M_-4Zg.mjs} +2 -2
  19. package/dist/{runClaude-C_WLfM6c.mjs → runClaude-D6Pdkevn.mjs} +250 -46
  20. package/dist/{runClaude-CNVufgZb.cjs → runClaude-IeRSC5qX.cjs} +270 -66
  21. package/dist/{runCodex-8eWjTPJr.mjs → runCodex-CsfUU1Wb.mjs} +216 -401
  22. package/dist/{runCodex-Dzy8anlX.cjs → runCodex-WRmgSK6L.cjs} +216 -401
  23. package/dist/{runGemini-nbr0mm-S.mjs → runGemini-CrH3dQ0Y.mjs} +5 -5
  24. package/dist/{runGemini-CgsVKP7m.cjs → runGemini-qBh6zs5G.cjs} +5 -5
  25. package/package.json +1 -2
  26. package/dist/future-Dq4Ha1Dn.cjs +0 -24
  27. package/dist/future-xRdLl3vf.mjs +0 -22
@@ -1,14 +1,13 @@
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-B5Ui8Fw0.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-BByhFIIq.mjs';
5
- import { F as Future } from './future-xRdLl3vf.mjs';
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-DpQIC-DJ.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-CriPm_z9.mjs';
6
5
  import { R as RawJSONLinesSchema } from './types-CiliQpqS.mjs';
7
- import { join, resolve } from 'node:path';
6
+ import { dirname, basename, join, resolve } from 'node:path';
8
7
  import { readFile } from 'node:fs/promises';
9
- import { watch, access } from 'fs/promises';
8
+ import { stat, watch, access } from 'fs/promises';
10
9
  import { useStdout, useInput, Box, Text, render } from 'ink';
11
- import { a as MessageBuffer, M as MessageQueue2, h as hashObject, r as registerKillSessionHandler } from './registerKillSessionHandler-BtSK7IOa.mjs';
10
+ import { a as MessageBuffer, M as MessageQueue2, h as hashObject, r as registerKillSessionHandler } from './registerKillSessionHandler-C3M_-4Zg.mjs';
12
11
  import React, { useState, useRef, useEffect, useCallback } from 'react';
13
12
  import { execSync, spawn } from 'node:child_process';
14
13
  import { createInterface } from 'node:readline';
@@ -21,7 +20,7 @@ import 'tweetnacl';
21
20
  import 'expo-server-sdk';
22
21
  import 'chalk';
23
22
  import { isDeepStrictEqual } from 'node:util';
24
- import { readSettings } from './persistence-CzpZpiL3.mjs';
23
+ import { readSettings } from './persistence-CqgPgbzN.mjs';
25
24
  import { createServer } from 'node:http';
26
25
  import 'fs';
27
26
  import 'zod';
@@ -59,6 +58,7 @@ class Session {
59
58
  /** JavaScript runtime to use for spawning Claude Code (default: 'node') */
60
59
  jsRuntime;
61
60
  sessionId;
61
+ transcriptPath = null;
62
62
  mode = "local";
63
63
  thinking = false;
64
64
  /** Callbacks to be notified when session ID is found/changed */
@@ -112,15 +112,33 @@ class Session {
112
112
  * Updates internal state, syncs to API metadata, and notifies
113
113
  * all registered callbacks (e.g., SessionScanner) about the change.
114
114
  */
115
- onSessionFound = (sessionId) => {
115
+ onSessionFound = (sessionId, hookData) => {
116
+ const nextTranscriptPathRaw = hookData?.transcript_path ?? hookData?.transcriptPath;
117
+ const nextTranscriptPath = typeof nextTranscriptPathRaw === "string" ? nextTranscriptPathRaw : null;
118
+ const previousSessionId = this.sessionId;
119
+ const previousTranscriptPath = this.transcriptPath;
116
120
  this.sessionId = sessionId;
121
+ if (previousSessionId !== sessionId) {
122
+ this.transcriptPath = nextTranscriptPath;
123
+ } else if (nextTranscriptPath) {
124
+ this.transcriptPath = nextTranscriptPath;
125
+ }
117
126
  this.client.updateMetadata((metadata) => ({
118
127
  ...metadata,
119
- claudeSessionId: sessionId
128
+ claudeSessionId: sessionId,
129
+ claudeTranscriptPath: this.transcriptPath || void 0
120
130
  }));
121
- logger.debug(`[Session] Claude Code session ID ${sessionId} added to metadata`);
131
+ logger.debug(`[Session] Claude session info updated: sessionId=${sessionId}, transcriptPath=${this.transcriptPath ?? "none"}`);
132
+ const didTranscriptPathChange = nextTranscriptPath !== null && nextTranscriptPath !== previousTranscriptPath;
133
+ if (previousSessionId === sessionId && !didTranscriptPathChange) {
134
+ return;
135
+ }
136
+ const info = {
137
+ sessionId,
138
+ transcriptPath: this.transcriptPath
139
+ };
122
140
  for (const callback of this.sessionFoundCallbacks) {
123
- callback(sessionId);
141
+ callback(info);
124
142
  }
125
143
  };
126
144
  /**
@@ -143,6 +161,7 @@ class Session {
143
161
  */
144
162
  clearSessionId = () => {
145
163
  this.sessionId = null;
164
+ this.transcriptPath = null;
146
165
  logger.debug("[Session] Session ID cleared");
147
166
  };
148
167
  /**
@@ -179,6 +198,27 @@ class Session {
179
198
  };
180
199
  }
181
200
 
201
+ class Future {
202
+ _resolve;
203
+ _reject;
204
+ _promise;
205
+ constructor() {
206
+ this._promise = new Promise((resolve, reject) => {
207
+ this._resolve = resolve;
208
+ this._reject = reject;
209
+ });
210
+ }
211
+ resolve(value) {
212
+ this._resolve(value);
213
+ }
214
+ reject(reason) {
215
+ this._reject(reason);
216
+ }
217
+ get promise() {
218
+ return this._promise;
219
+ }
220
+ }
221
+
182
222
  class InvalidateSync {
183
223
  _invalidated = false;
184
224
  _invalidatedDouble = false;
@@ -247,9 +287,51 @@ class InvalidateSync {
247
287
 
248
288
  function startFileWatcher(file, onFileChange) {
249
289
  const abortController = new AbortController();
290
+ const parentDir = dirname(file);
291
+ const targetName = basename(file);
250
292
  void (async () => {
251
293
  while (true) {
252
294
  try {
295
+ try {
296
+ await stat(file);
297
+ } catch (e) {
298
+ if (abortController.signal.aborted) {
299
+ return;
300
+ }
301
+ if (e?.code === "ENOENT") {
302
+ logger.debug(`[FILE_WATCHER] Waiting for file to exist: ${file}`);
303
+ const dirWatcher = watch(parentDir, { persistent: true, signal: abortController.signal });
304
+ try {
305
+ await stat(file);
306
+ } catch (err) {
307
+ if (err?.code !== "ENOENT") {
308
+ throw err;
309
+ }
310
+ for await (const event of dirWatcher) {
311
+ if (abortController.signal.aborted) {
312
+ return;
313
+ }
314
+ const name = typeof event?.filename === "string" ? String(event.filename) : null;
315
+ if (name && name !== targetName) {
316
+ continue;
317
+ }
318
+ try {
319
+ await stat(file);
320
+ logger.debug(`[FILE_WATCHER] File appeared: ${file}`);
321
+ break;
322
+ } catch (nextErr) {
323
+ if (nextErr?.code === "ENOENT") {
324
+ continue;
325
+ }
326
+ throw nextErr;
327
+ }
328
+ }
329
+ }
330
+ } else {
331
+ throw e;
332
+ }
333
+ }
334
+ onFileChange(file);
253
335
  logger.debug(`[FILE_WATCHER] Starting watcher for ${file}`);
254
336
  const watcher = watch(file, { persistent: true, signal: abortController.signal });
255
337
  for await (const event of watcher) {
@@ -279,19 +361,67 @@ const INTERNAL_CLAUDE_EVENT_TYPES = /* @__PURE__ */ new Set([
279
361
  "queue-operation"
280
362
  ]);
281
363
  async function createSessionScanner(opts) {
282
- const projectDir = getProjectPath(opts.workingDirectory);
364
+ const initialProjectDir = getProjectPath(opts.workingDirectory);
365
+ let projectDirOverride = null;
366
+ const sessionFileOverrides = /* @__PURE__ */ new Map();
367
+ const transcriptMissingWarningMs = opts.transcriptMissingWarningMs ?? 5e3;
368
+ const warnedMissingTranscripts = /* @__PURE__ */ new Set();
369
+ const missingTranscriptTimers = /* @__PURE__ */ new Map();
370
+ function effectiveProjectDir() {
371
+ return projectDirOverride ?? initialProjectDir;
372
+ }
373
+ function getSessionFilePath(sessionId) {
374
+ const override = sessionFileOverrides.get(sessionId);
375
+ return override ?? join(effectiveProjectDir(), `${sessionId}.jsonl`);
376
+ }
377
+ function scheduleTranscriptMissingWarning(sessionId) {
378
+ if (!opts.onTranscriptMissing) {
379
+ return;
380
+ }
381
+ if (!Number.isFinite(transcriptMissingWarningMs) || transcriptMissingWarningMs <= 0) {
382
+ return;
383
+ }
384
+ if (warnedMissingTranscripts.has(sessionId) || missingTranscriptTimers.has(sessionId)) {
385
+ return;
386
+ }
387
+ const timeoutId = setTimeout(async () => {
388
+ missingTranscriptTimers.delete(sessionId);
389
+ if (warnedMissingTranscripts.has(sessionId)) {
390
+ return;
391
+ }
392
+ const filePath = getSessionFilePath(sessionId);
393
+ try {
394
+ await readFile(filePath, "utf-8");
395
+ return;
396
+ } catch {
397
+ }
398
+ warnedMissingTranscripts.add(sessionId);
399
+ try {
400
+ opts.onTranscriptMissing?.({ sessionId, filePath });
401
+ } catch (err) {
402
+ logger.debug("[SESSION_SCANNER] onTranscriptMissing callback threw:", err);
403
+ }
404
+ }, transcriptMissingWarningMs);
405
+ missingTranscriptTimers.set(sessionId, timeoutId);
406
+ }
283
407
  let finishedSessions = /* @__PURE__ */ new Set();
284
408
  let pendingSessions = /* @__PURE__ */ new Set();
285
409
  let currentSessionId = null;
286
410
  let watchers = /* @__PURE__ */ new Map();
287
411
  let processedMessageKeys = /* @__PURE__ */ new Set();
412
+ if (opts.sessionId && typeof opts.transcriptPath === "string" && opts.transcriptPath.trim()) {
413
+ const transcriptPath = opts.transcriptPath.trim();
414
+ sessionFileOverrides.set(opts.sessionId, transcriptPath);
415
+ projectDirOverride = dirname(transcriptPath);
416
+ }
288
417
  if (opts.sessionId) {
289
- let messages = await readSessionLog(projectDir, opts.sessionId);
418
+ let messages = await readSessionLog(getSessionFilePath(opts.sessionId));
290
419
  logger.debug(`[SESSION_SCANNER] Marking ${messages.length} existing messages as processed from session ${opts.sessionId}`);
291
420
  for (let m of messages) {
292
421
  processedMessageKeys.add(messageKey(m));
293
422
  }
294
423
  currentSessionId = opts.sessionId;
424
+ scheduleTranscriptMissingWarning(opts.sessionId);
295
425
  }
296
426
  const sync = new InvalidateSync(async () => {
297
427
  let sessions = [];
@@ -307,7 +437,7 @@ async function createSessionScanner(opts) {
307
437
  }
308
438
  }
309
439
  for (let session of sessions) {
310
- const sessionMessages = await readSessionLog(projectDir, session);
440
+ const sessionMessages = await readSessionLog(getSessionFilePath(session));
311
441
  let skipped = 0;
312
442
  let sent = 0;
313
443
  for (let file of sessionMessages) {
@@ -332,11 +462,27 @@ async function createSessionScanner(opts) {
332
462
  }
333
463
  }
334
464
  for (let p of sessions) {
335
- if (!watchers.has(p)) {
465
+ const desiredPath = getSessionFilePath(p);
466
+ const existing = watchers.get(p);
467
+ if (!existing) {
336
468
  logger.debug(`[SESSION_SCANNER] Starting watcher for session: ${p}`);
337
- watchers.set(p, startFileWatcher(join(projectDir, `${p}.jsonl`), () => {
338
- sync.invalidate();
339
- }));
469
+ watchers.set(p, {
470
+ filePath: desiredPath,
471
+ stop: startFileWatcher(desiredPath, () => {
472
+ sync.invalidate();
473
+ })
474
+ });
475
+ continue;
476
+ }
477
+ if (existing.filePath !== desiredPath) {
478
+ logger.debug(`[SESSION_SCANNER] Restarting watcher for session: ${p} (${existing.filePath} -> ${desiredPath})`);
479
+ existing.stop();
480
+ watchers.set(p, {
481
+ filePath: desiredPath,
482
+ stop: startFileWatcher(desiredPath, () => {
483
+ sync.invalidate();
484
+ })
485
+ });
340
486
  }
341
487
  }
342
488
  });
@@ -348,23 +494,55 @@ async function createSessionScanner(opts) {
348
494
  cleanup: async () => {
349
495
  clearInterval(intervalId);
350
496
  for (let w of watchers.values()) {
351
- w();
497
+ w.stop();
352
498
  }
353
499
  watchers.clear();
500
+ for (const timeoutId of missingTranscriptTimers.values()) {
501
+ clearTimeout(timeoutId);
502
+ }
503
+ missingTranscriptTimers.clear();
354
504
  await sync.invalidateAndAwait();
355
505
  sync.stop();
356
506
  },
357
- onNewSession: (sessionId) => {
507
+ onNewSession: (arg) => {
508
+ const sessionId = typeof arg === "string" ? arg : arg.sessionId;
509
+ const transcriptPathRaw = typeof arg === "string" ? null : arg.transcriptPath;
510
+ const transcriptPath = typeof transcriptPathRaw === "string" && transcriptPathRaw.trim() ? transcriptPathRaw.trim() : null;
511
+ let didUpdatePaths = false;
512
+ if (transcriptPath) {
513
+ const previousOverride = sessionFileOverrides.get(sessionId);
514
+ if (previousOverride !== transcriptPath) {
515
+ sessionFileOverrides.set(sessionId, transcriptPath);
516
+ didUpdatePaths = true;
517
+ }
518
+ const nextProjectDir = dirname(transcriptPath);
519
+ if (projectDirOverride !== nextProjectDir) {
520
+ projectDirOverride = nextProjectDir;
521
+ didUpdatePaths = true;
522
+ }
523
+ }
358
524
  if (currentSessionId === sessionId) {
359
- logger.debug(`[SESSION_SCANNER] New session: ${sessionId} is the same as the current session, skipping`);
525
+ if (didUpdatePaths) {
526
+ sync.invalidate();
527
+ } else {
528
+ logger.debug(`[SESSION_SCANNER] New session: ${sessionId} is the same as the current session, skipping`);
529
+ }
360
530
  return;
361
531
  }
362
532
  if (finishedSessions.has(sessionId)) {
363
- logger.debug(`[SESSION_SCANNER] New session: ${sessionId} is already finished, skipping`);
533
+ if (didUpdatePaths) {
534
+ sync.invalidate();
535
+ } else {
536
+ logger.debug(`[SESSION_SCANNER] New session: ${sessionId} is already finished, skipping`);
537
+ }
364
538
  return;
365
539
  }
366
540
  if (pendingSessions.has(sessionId)) {
367
- logger.debug(`[SESSION_SCANNER] New session: ${sessionId} is already pending, skipping`);
541
+ if (didUpdatePaths) {
542
+ sync.invalidate();
543
+ } else {
544
+ logger.debug(`[SESSION_SCANNER] New session: ${sessionId} is already pending, skipping`);
545
+ }
368
546
  return;
369
547
  }
370
548
  if (currentSessionId) {
@@ -372,6 +550,7 @@ async function createSessionScanner(opts) {
372
550
  }
373
551
  logger.debug(`[SESSION_SCANNER] New session: ${sessionId}`);
374
552
  currentSessionId = sessionId;
553
+ scheduleTranscriptMissingWarning(sessionId);
375
554
  sync.invalidate();
376
555
  }
377
556
  };
@@ -389,14 +568,13 @@ function messageKey(message) {
389
568
  throw Error();
390
569
  }
391
570
  }
392
- async function readSessionLog(projectDir, sessionId) {
393
- const expectedSessionFile = join(projectDir, `${sessionId}.jsonl`);
394
- logger.debug(`[SESSION_SCANNER] Reading session file: ${expectedSessionFile}`);
571
+ async function readSessionLog(sessionFilePath) {
572
+ logger.debug(`[SESSION_SCANNER] Reading session file: ${sessionFilePath}`);
395
573
  let file;
396
574
  try {
397
- file = await readFile(expectedSessionFile, "utf-8");
575
+ file = await readFile(sessionFilePath, "utf-8");
398
576
  } catch (error) {
399
- logger.debug(`[SESSION_SCANNER] Session file not found: ${expectedSessionFile}`);
577
+ logger.debug(`[SESSION_SCANNER] Session file not found: ${sessionFilePath}`);
400
578
  return [];
401
579
  }
402
580
  let lines = file.split("\n");
@@ -426,15 +604,25 @@ async function readSessionLog(projectDir, sessionId) {
426
604
  async function claudeLocalLauncher(session) {
427
605
  const scanner = await createSessionScanner({
428
606
  sessionId: session.sessionId,
607
+ transcriptPath: session.transcriptPath,
429
608
  workingDirectory: session.path,
430
609
  onMessage: (message) => {
431
610
  if (message.type !== "summary") {
432
611
  session.client.sendClaudeSessionMessage(message);
433
612
  }
613
+ },
614
+ onTranscriptMissing: () => {
615
+ session.client.sendSessionEvent({
616
+ type: "message",
617
+ message: "Claude transcript file not found yet, waiting for it to appear..."
618
+ });
434
619
  }
435
620
  });
436
- const scannerSessionCallback = (sessionId) => {
437
- scanner.onNewSession(sessionId);
621
+ const scannerSessionCallback = (info) => {
622
+ scanner.onNewSession({
623
+ sessionId: info.sessionId,
624
+ transcriptPath: info.transcriptPath
625
+ });
438
626
  };
439
627
  session.addSessionFoundCallback(scannerSessionCallback);
440
628
  let exitReason = null;
@@ -472,7 +660,6 @@ async function claudeLocalLauncher(session) {
472
660
  }
473
661
  const handleSessionStart = (sessionId) => {
474
662
  session.onSessionFound(sessionId);
475
- scanner.onNewSession(sessionId);
476
663
  };
477
664
  while (true) {
478
665
  if (exitReason) {
@@ -1421,7 +1608,7 @@ const systemPrompt = (() => {
1421
1608
 
1422
1609
  async function claudeRemote(opts) {
1423
1610
  let startFrom = opts.sessionId;
1424
- if (opts.sessionId && !claudeCheckSession(opts.sessionId, opts.path)) {
1611
+ if (opts.sessionId && !claudeCheckSession(opts.sessionId, opts.path, opts.transcriptPath)) {
1425
1612
  startFrom = null;
1426
1613
  }
1427
1614
  if (!startFrom && opts.claudeArgs) {
@@ -1523,11 +1710,14 @@ async function claudeRemote(opts) {
1523
1710
  updateThinking(true);
1524
1711
  const systemInit = message;
1525
1712
  if (systemInit.session_id) {
1526
- logger.debug(`[claudeRemote] Waiting for session file to be written to disk: ${systemInit.session_id}`);
1527
- const projectDir = getProjectPath(opts.path);
1528
- const found = await awaitFileExist(join(projectDir, `${systemInit.session_id}.jsonl`));
1713
+ const transcriptPath = opts.transcriptPath && opts.sessionId === systemInit.session_id ? opts.transcriptPath : join(getProjectPath(opts.path), `${systemInit.session_id}.jsonl`);
1714
+ logger.debug(`[claudeRemote] Waiting for session file to be written to disk: ${transcriptPath}`);
1715
+ const found = await awaitFileExist(transcriptPath);
1529
1716
  logger.debug(`[claudeRemote] Session file found: ${systemInit.session_id} ${found}`);
1530
- opts.onSessionFound(systemInit.session_id);
1717
+ opts.onSessionFound(systemInit.session_id, {
1718
+ transcript_path: transcriptPath,
1719
+ transcriptPath
1720
+ });
1531
1721
  }
1532
1722
  }
1533
1723
  if (message.type === "result") {
@@ -1980,11 +2170,21 @@ function formatClaudeMessageForInk(message, messageBuffer, onAssistantResult) {
1980
2170
  case "assistant": {
1981
2171
  const assistantMsg = message;
1982
2172
  if (assistantMsg.message && assistantMsg.message.content) {
1983
- messageBuffer.addMessage("\u{1F916} Assistant:", "assistant");
2173
+ let assistantHeaderShown = false;
1984
2174
  for (const block of assistantMsg.message.content) {
1985
- if (block.type === "text") {
2175
+ if (block.type === "thinking" && typeof block.thinking === "string" && block.thinking.trim()) {
2176
+ messageBuffer.addMessage(`[Thinking] ${block.thinking}`, "status");
2177
+ } else if (block.type === "text") {
2178
+ if (!assistantHeaderShown) {
2179
+ messageBuffer.addMessage("\u{1F916} Assistant:", "assistant");
2180
+ assistantHeaderShown = true;
2181
+ }
1986
2182
  messageBuffer.addMessage(block.text || "", "assistant");
1987
2183
  } else if (block.type === "tool_use") {
2184
+ if (!assistantHeaderShown) {
2185
+ messageBuffer.addMessage("\u{1F916} Assistant:", "assistant");
2186
+ assistantHeaderShown = true;
2187
+ }
1988
2188
  messageBuffer.addMessage(`\u{1F527} Tool: ${block.name}`, "tool");
1989
2189
  if (block.input) {
1990
2190
  const inputStr = JSON.stringify(block.input, null, 2);
@@ -2630,6 +2830,7 @@ async function claudeRemoteLauncher(session) {
2630
2830
  try {
2631
2831
  const remoteResult = await claudeRemote({
2632
2832
  sessionId: session.sessionId,
2833
+ transcriptPath: session.transcriptPath,
2633
2834
  path: session.path,
2634
2835
  allowedTools: session.allowedTools ?? [],
2635
2836
  mcpServers: session.mcpServers,
@@ -2663,9 +2864,9 @@ async function claudeRemoteLauncher(session) {
2663
2864
  }
2664
2865
  return null;
2665
2866
  },
2666
- onSessionFound: (sessionId) => {
2867
+ onSessionFound: (sessionId, data) => {
2667
2868
  sdkToLogConverter.updateSessionId(sessionId);
2668
- session.onSessionFound(sessionId);
2869
+ session.onSessionFound(sessionId, data);
2669
2870
  },
2670
2871
  onThinkingChange: session.onThinkingChange,
2671
2872
  claudeEnvVars: session.claudeEnvVars,
@@ -2854,13 +3055,20 @@ async function startHookServer(options) {
2854
3055
  }
2855
3056
  clearTimeout(timeout);
2856
3057
  const body = Buffer.concat(chunks).toString("utf-8");
2857
- logger.debug("[hookServer] Received session hook:", body);
2858
3058
  let data = {};
2859
3059
  try {
2860
3060
  data = JSON.parse(body);
2861
3061
  } catch (parseError) {
2862
3062
  logger.debug("[hookServer] Failed to parse hook data as JSON:", parseError);
2863
3063
  }
3064
+ logger.debug("[hookServer] Received session hook", {
3065
+ sessionId: data.session_id || data.sessionId || null,
3066
+ transcriptPath: data.transcript_path || data.transcriptPath || null,
3067
+ cwd: data.cwd,
3068
+ hookEventName: data.hook_event_name,
3069
+ source: data.source,
3070
+ bodyLength: body.length
3071
+ });
2864
3072
  const sessionId = data.session_id || data.sessionId;
2865
3073
  if (sessionId) {
2866
3074
  logger.debug(`[hookServer] Session hook received session ID: ${sessionId}`);
@@ -3062,11 +3270,7 @@ async function runClaude(credentials, options = {}) {
3062
3270
  onSessionHook: (sessionId, data) => {
3063
3271
  logger.debug(`[START] Session hook received: ${sessionId}`, data);
3064
3272
  if (currentSession) {
3065
- const previousSessionId = currentSession.sessionId;
3066
- if (previousSessionId !== sessionId) {
3067
- logger.debug(`[START] Claude session ID changed: ${previousSessionId} -> ${sessionId}`);
3068
- currentSession.onSessionFound(sessionId);
3069
- }
3273
+ currentSession.onSessionFound(sessionId, data);
3070
3274
  }
3071
3275
  }
3072
3276
  });