claude-remote 0.2.4 → 0.3.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 +44 -3
package/package.json
CHANGED
package/server.js
CHANGED
|
@@ -129,6 +129,7 @@ let tailCatchingUp = false; // true while reading historical transcript content
|
|
|
129
129
|
const isTTY = process.stdin.isTTY && process.stdout.isTTY;
|
|
130
130
|
const LEGACY_REPLAY_DELAY_MS = 1500;
|
|
131
131
|
const IMAGE_UPLOAD_TTL_MS = 15 * 60 * 1000;
|
|
132
|
+
const IMAGE_UPLOAD_DIR = path.join(CLAUDE_HOME, 'remote-uploads');
|
|
132
133
|
let turnStateVersion = 0;
|
|
133
134
|
let turnState = {
|
|
134
135
|
phase: 'idle',
|
|
@@ -566,14 +567,18 @@ function cleanupImageUpload(uploadId) {
|
|
|
566
567
|
|
|
567
568
|
function cleanupClientUploads(ws) {
|
|
568
569
|
for (const [uploadId, upload] of pendingImageUploads) {
|
|
569
|
-
if (upload.owner === ws) cleanupImageUpload(uploadId);
|
|
570
|
+
if (upload.owner === ws && !upload.submitted) cleanupImageUpload(uploadId);
|
|
570
571
|
}
|
|
571
572
|
}
|
|
572
573
|
|
|
573
574
|
function createTempImageFile(buffer, mediaType, uploadId) {
|
|
574
|
-
const
|
|
575
|
+
const isLinux = process.platform !== 'win32' && process.platform !== 'darwin';
|
|
576
|
+
const tmpDir = isLinux
|
|
577
|
+
? IMAGE_UPLOAD_DIR
|
|
578
|
+
: (process.env.CLAUDE_CODE_TMPDIR || os.tmpdir());
|
|
575
579
|
const type = String(mediaType || 'image/png').toLowerCase();
|
|
576
580
|
const ext = type.includes('jpeg') || type.includes('jpg') ? '.jpg' : '.png';
|
|
581
|
+
fs.mkdirSync(tmpDir, { recursive: true });
|
|
577
582
|
const tmpFile = path.join(tmpDir, `bridge_upload_${uploadId}_${Date.now()}${ext}`);
|
|
578
583
|
fs.writeFileSync(tmpFile, buffer);
|
|
579
584
|
return tmpFile;
|
|
@@ -668,6 +673,18 @@ wss.on('connection', (ws, req) => {
|
|
|
668
673
|
sendReplay(ws, canResume ? msg.lastSeq : null);
|
|
669
674
|
break;
|
|
670
675
|
}
|
|
676
|
+
case 'foreground_probe': {
|
|
677
|
+
const probeId = typeof msg.probeId === 'string' ? msg.probeId : '';
|
|
678
|
+
sendWs(ws, {
|
|
679
|
+
type: 'foreground_probe_ack',
|
|
680
|
+
probeId,
|
|
681
|
+
sessionId: currentSessionId,
|
|
682
|
+
lastSeq: latestEventSeq(),
|
|
683
|
+
cwd: CWD,
|
|
684
|
+
}, 'foreground_probe');
|
|
685
|
+
log(`Foreground probe ack -> ${wsLabel(ws)} probeId=${probeId || 'none'} session=${currentSessionId ?? 'null'} lastSeq=${latestEventSeq()}`);
|
|
686
|
+
break;
|
|
687
|
+
}
|
|
671
688
|
case 'input':
|
|
672
689
|
// Raw terminal keystrokes from xterm.js in WebUI
|
|
673
690
|
if (claudeProc) claudeProc.write(msg.data);
|
|
@@ -848,13 +865,16 @@ wss.on('connection', (ws, req) => {
|
|
|
848
865
|
break;
|
|
849
866
|
}
|
|
850
867
|
try {
|
|
868
|
+
const shouldCleanupAfterSubmit = process.platform === 'win32' || process.platform === 'darwin';
|
|
851
869
|
handlePreparedImageUpload({
|
|
852
870
|
tmpFile: upload.tmpFile,
|
|
853
871
|
mediaType: upload.mediaType,
|
|
854
872
|
text: msg.text || '',
|
|
855
873
|
logLabel: upload.name || uploadId,
|
|
856
|
-
onCleanup: () => cleanupImageUpload(uploadId),
|
|
874
|
+
onCleanup: shouldCleanupAfterSubmit ? () => cleanupImageUpload(uploadId) : null,
|
|
857
875
|
});
|
|
876
|
+
upload.submitted = true;
|
|
877
|
+
upload.updatedAt = Date.now();
|
|
858
878
|
setTurnState('running', { reason: 'image_submit' });
|
|
859
879
|
sendUploadStatus(ws, uploadId, 'submitted');
|
|
860
880
|
} catch (err) {
|
|
@@ -1481,11 +1501,27 @@ function handlePreparedImageUpload({ tmpFile, mediaType, text, logLabel = '', on
|
|
|
1481
1501
|
|
|
1482
1502
|
const isWin = process.platform === 'win32';
|
|
1483
1503
|
const isMac = process.platform === 'darwin';
|
|
1504
|
+
const isLinux = !isWin && !isMac;
|
|
1484
1505
|
|
|
1485
1506
|
try {
|
|
1486
1507
|
const stat = fs.statSync(tmpFile);
|
|
1487
1508
|
log(`Image ready: ${logLabel || path.basename(tmpFile)} (${stat.size} bytes)`);
|
|
1488
1509
|
|
|
1510
|
+
if (isLinux) {
|
|
1511
|
+
const quotedPath = JSON.stringify(tmpFile);
|
|
1512
|
+
const trimmedText = (text || '').trim();
|
|
1513
|
+
const prompt = trimmedText
|
|
1514
|
+
? `Please analyze the image at this path: ${quotedPath}\n\nUser note:\n${trimmedText}`
|
|
1515
|
+
: `Analyze this image: ${quotedPath}`;
|
|
1516
|
+
|
|
1517
|
+
claudeProc.write(prompt);
|
|
1518
|
+
setTimeout(() => {
|
|
1519
|
+
if (claudeProc) claudeProc.write('\r');
|
|
1520
|
+
log(`Sent Linux image path prompt: ${tmpFile}`);
|
|
1521
|
+
}, 150);
|
|
1522
|
+
return;
|
|
1523
|
+
}
|
|
1524
|
+
|
|
1489
1525
|
if (isWin) {
|
|
1490
1526
|
const psCmd = `Add-Type -AssemblyName System.Drawing; Add-Type -AssemblyName System.Windows.Forms; $img = [System.Drawing.Image]::FromFile('${tmpFile.replace(/'/g, "''")}'); [System.Windows.Forms.Clipboard]::SetImage($img); $img.Dispose()`;
|
|
1491
1527
|
execSync(`powershell -NoProfile -STA -Command "${psCmd}"`, { timeout: 10000 });
|
|
@@ -1551,6 +1587,11 @@ function handleImageUpload(msg) {
|
|
|
1551
1587
|
mediaType: msg.mediaType,
|
|
1552
1588
|
text: msg.text || '',
|
|
1553
1589
|
});
|
|
1590
|
+
if (process.platform !== 'win32' && process.platform !== 'darwin') {
|
|
1591
|
+
setTimeout(() => {
|
|
1592
|
+
try { fs.unlinkSync(tmpFile); } catch {}
|
|
1593
|
+
}, IMAGE_UPLOAD_TTL_MS).unref();
|
|
1594
|
+
}
|
|
1554
1595
|
setTurnState('running', { reason: 'legacy_image_upload' });
|
|
1555
1596
|
} catch (err) {
|
|
1556
1597
|
log(`Image upload error: ${err.message}`);
|