claude-remote 0.2.0 → 0.2.1
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/package.json +1 -1
- package/server.js +36 -0
package/package.json
CHANGED
package/server.js
CHANGED
|
@@ -120,6 +120,7 @@ let tailTimer = null;
|
|
|
120
120
|
let switchWatcher = null;
|
|
121
121
|
let expectingSwitch = false;
|
|
122
122
|
let expectingSwitchTimer = null;
|
|
123
|
+
let pendingSwitchTarget = null;
|
|
123
124
|
let tailRemainder = Buffer.alloc(0);
|
|
124
125
|
let tailCatchingUp = false; // true while reading historical transcript content
|
|
125
126
|
const isTTY = process.stdin.isTTY && process.stdout.isTTY;
|
|
@@ -214,6 +215,10 @@ function maybeAttachHookSession(data, source) {
|
|
|
214
215
|
if (currentSessionId && !expectingSwitch) {
|
|
215
216
|
const currentHasContent = transcriptPath && fileLooksLikeTranscript(transcriptPath);
|
|
216
217
|
if (!targetHasContent || currentHasContent) {
|
|
218
|
+
if (currentSessionId !== target.sessionId) {
|
|
219
|
+
pendingSwitchTarget = { ...target, seenAt: Date.now(), source };
|
|
220
|
+
log(`Queued pending session-start: ${target.sessionId} (current=${currentSessionId} currentHasContent=${currentHasContent} targetHasContent=${targetHasContent})`);
|
|
221
|
+
}
|
|
217
222
|
log(`Ignored session-start: ${target.sessionId} (current=${currentSessionId} currentHasContent=${currentHasContent} targetHasContent=${targetHasContent})`);
|
|
218
223
|
return;
|
|
219
224
|
}
|
|
@@ -238,6 +243,31 @@ function maybeAttachHookSession(data, source) {
|
|
|
238
243
|
attachTranscript({ full: target.full }, 0);
|
|
239
244
|
}
|
|
240
245
|
|
|
246
|
+
function maybeAttachPendingSwitchTarget(reason, requireReady = true) {
|
|
247
|
+
if (!pendingSwitchTarget) return false;
|
|
248
|
+
if ((Date.now() - pendingSwitchTarget.seenAt) > 15000) {
|
|
249
|
+
log(`Dropped stale pending switch target: ${pendingSwitchTarget.sessionId}`);
|
|
250
|
+
pendingSwitchTarget = null;
|
|
251
|
+
return false;
|
|
252
|
+
}
|
|
253
|
+
if (pendingSwitchTarget.sessionId === currentSessionId) {
|
|
254
|
+
pendingSwitchTarget = null;
|
|
255
|
+
return false;
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
if (requireReady && !fileLooksLikeTranscript(pendingSwitchTarget.full)) {
|
|
259
|
+
return false;
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
const target = pendingSwitchTarget;
|
|
263
|
+
pendingSwitchTarget = null;
|
|
264
|
+
log(`Attaching pending switch target from ${reason}: ${target.sessionId}`);
|
|
265
|
+
if (tailTimer) { clearInterval(tailTimer); tailTimer = null; }
|
|
266
|
+
if (switchWatcher) { clearInterval(switchWatcher); switchWatcher = null; }
|
|
267
|
+
attachTranscript({ full: target.full }, 0);
|
|
268
|
+
return true;
|
|
269
|
+
}
|
|
270
|
+
|
|
241
271
|
// ============================================================
|
|
242
272
|
// 1. Static file server
|
|
243
273
|
// ============================================================
|
|
@@ -875,6 +905,9 @@ function extractSlashCommand(content) {
|
|
|
875
905
|
function attachTranscript(target, startOffset = 0) {
|
|
876
906
|
transcriptPath = target.full;
|
|
877
907
|
currentSessionId = path.basename(transcriptPath, '.jsonl');
|
|
908
|
+
if (pendingSwitchTarget && pendingSwitchTarget.sessionId === currentSessionId) {
|
|
909
|
+
pendingSwitchTarget = null;
|
|
910
|
+
}
|
|
878
911
|
transcriptOffset = Math.max(0, startOffset);
|
|
879
912
|
tailRemainder = Buffer.alloc(0);
|
|
880
913
|
eventBuffer = [];
|
|
@@ -915,6 +948,7 @@ function markExpectingSwitch() {
|
|
|
915
948
|
log('Expecting-switch flag expired (no new transcript found)');
|
|
916
949
|
}, 15000);
|
|
917
950
|
log('Expecting session switch (/clear detected)');
|
|
951
|
+
if (maybeAttachPendingSwitchTarget('markExpectingSwitch')) return;
|
|
918
952
|
}
|
|
919
953
|
|
|
920
954
|
function startSwitchWatcher() {
|
|
@@ -952,6 +986,7 @@ function startSwitchWatcher() {
|
|
|
952
986
|
function startTailing() {
|
|
953
987
|
tailRemainder = Buffer.alloc(0);
|
|
954
988
|
tailTimer = setInterval(() => {
|
|
989
|
+
if (maybeAttachPendingSwitchTarget('tail_pending_target')) return;
|
|
955
990
|
if (!transcriptPath) return;
|
|
956
991
|
try {
|
|
957
992
|
const stat = fs.statSync(transcriptPath);
|
|
@@ -1039,6 +1074,7 @@ function stopTailing() {
|
|
|
1039
1074
|
if (switchWatcher) { clearInterval(switchWatcher); switchWatcher = null; }
|
|
1040
1075
|
if (expectingSwitchTimer) { clearTimeout(expectingSwitchTimer); expectingSwitchTimer = null; }
|
|
1041
1076
|
expectingSwitch = false;
|
|
1077
|
+
pendingSwitchTarget = null;
|
|
1042
1078
|
tailRemainder = Buffer.alloc(0);
|
|
1043
1079
|
}
|
|
1044
1080
|
|