claude-remote 0.1.3 → 0.1.5

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 (2) hide show
  1. package/package.json +1 -1
  2. package/server.js +27 -4
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-remote",
3
- "version": "0.1.3",
3
+ "version": "0.1.5",
4
4
  "description": "Remote control bridge for Claude Code REPL - drive from phone/WebUI",
5
5
  "main": "server.js",
6
6
  "bin": {
package/server.js CHANGED
@@ -121,6 +121,7 @@ let switchWatcher = null;
121
121
  let expectingSwitch = false;
122
122
  let expectingSwitchTimer = null;
123
123
  let tailRemainder = Buffer.alloc(0);
124
+ let tailCatchingUp = false; // true while reading historical transcript content
124
125
  const isTTY = process.stdin.isTTY && process.stdout.isTTY;
125
126
  const LEGACY_REPLAY_DELAY_MS = 1500;
126
127
  const IMAGE_UPLOAD_TTL_MS = 15 * 60 * 1000;
@@ -201,7 +202,9 @@ function maybeAttachHookSession(data, source) {
201
202
  return;
202
203
  }
203
204
 
204
- if (currentSessionId && currentSessionId !== target.sessionId && !expectingSwitch) {
205
+ // session-start is authoritative always allow it to switch sessions.
206
+ // pre-tool-use is opportunistic — only accept if expecting a switch.
207
+ if (currentSessionId && currentSessionId !== target.sessionId && !expectingSwitch && source !== 'session-start') {
205
208
  log(`Ignored hook session from ${source}: ${target.sessionId} (current=${currentSessionId})`);
206
209
  return;
207
210
  }
@@ -824,7 +827,16 @@ function attachTranscript(target, startOffset = 0) {
824
827
  eventBuffer = [];
825
828
  eventSeq = 0;
826
829
 
827
- log(`Transcript attached: ${currentSessionId} (offset=${transcriptOffset})`);
830
+ // If transcript file already has content, mark as catching up so we don't
831
+ // broadcast working_started for historical user messages.
832
+ try {
833
+ const stat = fs.statSync(transcriptPath);
834
+ tailCatchingUp = stat.size > transcriptOffset;
835
+ } catch {
836
+ tailCatchingUp = false;
837
+ }
838
+
839
+ log(`Transcript attached: ${currentSessionId} (offset=${transcriptOffset} catchUp=${tailCatchingUp})`);
828
840
  broadcast({
829
841
  type: 'transcript_ready',
830
842
  transcript: transcriptPath,
@@ -884,7 +896,14 @@ function startTailing() {
884
896
  if (!transcriptPath) return;
885
897
  try {
886
898
  const stat = fs.statSync(transcriptPath);
887
- if (stat.size <= transcriptOffset) return;
899
+ if (stat.size <= transcriptOffset) {
900
+ // Caught up to file end — initial catch-up phase is over
901
+ if (tailCatchingUp) {
902
+ tailCatchingUp = false;
903
+ log('Tail catch-up complete, live mode');
904
+ }
905
+ return;
906
+ }
888
907
 
889
908
  const fd = fs.openSync(transcriptPath, 'r');
890
909
  const buf = Buffer.alloc(stat.size - transcriptOffset);
@@ -903,7 +922,11 @@ function startTailing() {
903
922
  const event = JSON.parse(line);
904
923
  // Detect /clear from JSONL events (covers terminal direct input)
905
924
  if (event.type === 'user' || (event.message && event.message.role === 'user')) {
906
- broadcast({ type: 'working_started' });
925
+ // Only broadcast working_started for live (new) user messages,
926
+ // not for historical events during catch-up.
927
+ if (!tailCatchingUp) {
928
+ broadcast({ type: 'working_started' });
929
+ }
907
930
  const content = event.message && event.message.content;
908
931
  if (typeof content === 'string' && /^\/clear\s*$/i.test(content.trim())) {
909
932
  markExpectingSwitch();