claude-remote 0.3.0 → 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.
Files changed (2) hide show
  1. package/package.json +1 -1
  2. package/server.js +32 -3
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-remote",
3
- "version": "0.3.0",
3
+ "version": "0.3.1",
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
@@ -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 tmpDir = process.env.CLAUDE_CODE_TMPDIR || os.tmpdir();
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;
@@ -860,13 +865,16 @@ wss.on('connection', (ws, req) => {
860
865
  break;
861
866
  }
862
867
  try {
868
+ const shouldCleanupAfterSubmit = process.platform === 'win32' || process.platform === 'darwin';
863
869
  handlePreparedImageUpload({
864
870
  tmpFile: upload.tmpFile,
865
871
  mediaType: upload.mediaType,
866
872
  text: msg.text || '',
867
873
  logLabel: upload.name || uploadId,
868
- onCleanup: () => cleanupImageUpload(uploadId),
874
+ onCleanup: shouldCleanupAfterSubmit ? () => cleanupImageUpload(uploadId) : null,
869
875
  });
876
+ upload.submitted = true;
877
+ upload.updatedAt = Date.now();
870
878
  setTurnState('running', { reason: 'image_submit' });
871
879
  sendUploadStatus(ws, uploadId, 'submitted');
872
880
  } catch (err) {
@@ -1493,11 +1501,27 @@ function handlePreparedImageUpload({ tmpFile, mediaType, text, logLabel = '', on
1493
1501
 
1494
1502
  const isWin = process.platform === 'win32';
1495
1503
  const isMac = process.platform === 'darwin';
1504
+ const isLinux = !isWin && !isMac;
1496
1505
 
1497
1506
  try {
1498
1507
  const stat = fs.statSync(tmpFile);
1499
1508
  log(`Image ready: ${logLabel || path.basename(tmpFile)} (${stat.size} bytes)`);
1500
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
+
1501
1525
  if (isWin) {
1502
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()`;
1503
1527
  execSync(`powershell -NoProfile -STA -Command "${psCmd}"`, { timeout: 10000 });
@@ -1563,6 +1587,11 @@ function handleImageUpload(msg) {
1563
1587
  mediaType: msg.mediaType,
1564
1588
  text: msg.text || '',
1565
1589
  });
1590
+ if (process.platform !== 'win32' && process.platform !== 'darwin') {
1591
+ setTimeout(() => {
1592
+ try { fs.unlinkSync(tmpFile); } catch {}
1593
+ }, IMAGE_UPLOAD_TTL_MS).unref();
1594
+ }
1566
1595
  setTurnState('running', { reason: 'legacy_image_upload' });
1567
1596
  } catch (err) {
1568
1597
  log(`Image upload error: ${err.message}`);