claude-remote 0.4.2 → 0.4.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.
- package/package.json +1 -1
- package/server.js +49 -31
package/package.json
CHANGED
package/server.js
CHANGED
|
@@ -5,7 +5,7 @@ const os = require('os');
|
|
|
5
5
|
const pty = require('node-pty');
|
|
6
6
|
const { WebSocketServer, WebSocket } = require('ws');
|
|
7
7
|
const crypto = require('crypto');
|
|
8
|
-
const { execSync } = require('child_process');
|
|
8
|
+
const { execSync, spawn } = require('child_process');
|
|
9
9
|
|
|
10
10
|
// --- CLI argument parsing ---
|
|
11
11
|
// Separate bridge args (CWD positional) from claude passthrough flags.
|
|
@@ -657,10 +657,6 @@ function createTempImageFile(buffer, mediaType, uploadId) {
|
|
|
657
657
|
return tmpFile;
|
|
658
658
|
}
|
|
659
659
|
|
|
660
|
-
function shellQuote(value) {
|
|
661
|
-
return `'${String(value || '').replace(/'/g, `'\\''`)}'`;
|
|
662
|
-
}
|
|
663
|
-
|
|
664
660
|
function getLinuxClipboardTool() {
|
|
665
661
|
if (process.platform === 'win32' || process.platform === 'darwin') return null;
|
|
666
662
|
try {
|
|
@@ -687,6 +683,38 @@ function assertLinuxClipboardAvailable() {
|
|
|
687
683
|
if (tool) return tool;
|
|
688
684
|
throw new Error('Linux image paste requires xclip or wl-copy on the server. Install one and try again.');
|
|
689
685
|
}
|
|
686
|
+
|
|
687
|
+
function startLinuxClipboardImage(tmpFile, mediaType) {
|
|
688
|
+
const type = String(mediaType || 'image/png').toLowerCase();
|
|
689
|
+
const tool = assertLinuxClipboardAvailable();
|
|
690
|
+
const imageBuffer = fs.readFileSync(tmpFile);
|
|
691
|
+
const args = tool === 'xclip'
|
|
692
|
+
? ['-selection', 'clipboard', '-t', type, '-i', '-loops', '1']
|
|
693
|
+
: ['--type', type, '--paste-once'];
|
|
694
|
+
const child = spawn(tool, args, {
|
|
695
|
+
detached: true,
|
|
696
|
+
stdio: ['pipe', 'ignore', 'pipe'],
|
|
697
|
+
});
|
|
698
|
+
let stderr = '';
|
|
699
|
+
child.on('error', (err) => {
|
|
700
|
+
log(`Linux clipboard process error (${tool}): ${err.message}`);
|
|
701
|
+
});
|
|
702
|
+
child.stderr.on('data', (chunk) => {
|
|
703
|
+
stderr += chunk.toString('utf8');
|
|
704
|
+
if (stderr.length > 2000) stderr = stderr.slice(-2000);
|
|
705
|
+
});
|
|
706
|
+
child.on('exit', (code, signal) => {
|
|
707
|
+
const extra = stderr.trim() ? ` stderr=${JSON.stringify(stderr.trim())}` : '';
|
|
708
|
+
log(`Linux clipboard process exited (${tool}) code=${code ?? 'null'} signal=${signal ?? 'null'}${extra}`);
|
|
709
|
+
});
|
|
710
|
+
child.stdin.on('error', (err) => {
|
|
711
|
+
if (err.code !== 'EPIPE') log(`Linux clipboard stdin error (${tool}): ${err.message}`);
|
|
712
|
+
});
|
|
713
|
+
child.stdin.end(imageBuffer);
|
|
714
|
+
child.unref();
|
|
715
|
+
log(`Linux clipboard process started (${tool}) pid=${child.pid ?? 'null'} type=${type} bytes=${imageBuffer.length}`);
|
|
716
|
+
return tool;
|
|
717
|
+
}
|
|
690
718
|
|
|
691
719
|
setInterval(() => {
|
|
692
720
|
const now = Date.now();
|
|
@@ -1689,33 +1717,23 @@ function handlePreparedImageUpload({ tmpFile, mediaType, text, logLabel = '', on
|
|
|
1689
1717
|
} else if (isMac) {
|
|
1690
1718
|
execSync(`osascript -e 'set the clipboard to (read POSIX file "${tmpFile}" as 芦class PNGf禄)'`, { timeout: 10000 });
|
|
1691
1719
|
} else {
|
|
1692
|
-
const
|
|
1693
|
-
|
|
1694
|
-
const quotedPath = shellQuote(tmpFile);
|
|
1695
|
-
const quotedType = shellQuote(type);
|
|
1696
|
-
if (tool === 'xclip') {
|
|
1697
|
-
execSync(`xclip -selection clipboard -t ${quotedType} -i < ${quotedPath}`, {
|
|
1698
|
-
timeout: 10000,
|
|
1699
|
-
shell: '/bin/sh',
|
|
1700
|
-
});
|
|
1701
|
-
} else {
|
|
1702
|
-
execSync(`wl-copy --type ${quotedType} < ${quotedPath}`, {
|
|
1703
|
-
timeout: 10000,
|
|
1704
|
-
shell: '/bin/sh',
|
|
1705
|
-
});
|
|
1706
|
-
}
|
|
1707
|
-
log(`Linux clipboard set with ${tool} (${type})`);
|
|
1720
|
+
const tool = startLinuxClipboardImage(tmpFile, mediaType);
|
|
1721
|
+
log(`Linux clipboard armed with ${tool}`);
|
|
1708
1722
|
}
|
|
1709
1723
|
log('Clipboard set with image');
|
|
1710
1724
|
|
|
1711
|
-
|
|
1712
|
-
|
|
1713
|
-
|
|
1714
|
-
|
|
1715
|
-
|
|
1716
|
-
|
|
1717
|
-
|
|
1718
|
-
|
|
1725
|
+
const pasteDelayMs = isWin || isMac ? 0 : 150;
|
|
1726
|
+
setTimeout(() => {
|
|
1727
|
+
if (!claudeProc) return;
|
|
1728
|
+
if (isWin) claudeProc.write('\x1bv');
|
|
1729
|
+
else claudeProc.write('\x16');
|
|
1730
|
+
log('Sent image paste keypress to PTY');
|
|
1731
|
+
}, pasteDelayMs);
|
|
1732
|
+
|
|
1733
|
+
setTimeout(() => {
|
|
1734
|
+
if (!claudeProc) return;
|
|
1735
|
+
const trimmedText = (text || '').trim();
|
|
1736
|
+
if (trimmedText) claudeProc.write(trimmedText);
|
|
1719
1737
|
|
|
1720
1738
|
setTimeout(() => {
|
|
1721
1739
|
if (claudeProc) claudeProc.write('\r');
|
|
@@ -1727,8 +1745,8 @@ function handlePreparedImageUpload({ tmpFile, mediaType, text, logLabel = '', on
|
|
|
1727
1745
|
try { fs.unlinkSync(tmpFile); } catch {}
|
|
1728
1746
|
}
|
|
1729
1747
|
}, 5000);
|
|
1730
|
-
}, 150);
|
|
1731
|
-
}, 1000);
|
|
1748
|
+
}, 150);
|
|
1749
|
+
}, 1000 + pasteDelayMs);
|
|
1732
1750
|
} catch (err) {
|
|
1733
1751
|
log(`Image upload error: ${err.message}`);
|
|
1734
1752
|
if (onCleanup) onCleanup();
|