Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 11 additions & 6 deletions native/cli.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,10 @@ const networkStore = require("./network-store.cjs");
const { parseDoCommands } = require("./do-parser.cjs");
const { executeDoSteps } = require("./do-executor.cjs");

const SOCKET_PATH = "/tmp/surf.sock";
const IS_WIN = process.platform === "win32";
const SURF_TMP = IS_WIN ? path.join(os.tmpdir(), "surf") : "/tmp";
const SOCKET_PATH = IS_WIN ? "//./pipe/surf" : "/tmp/surf.sock";
if (IS_WIN) { try { fs.mkdirSync(SURF_TMP, { recursive: true }); } catch {} }

// ============================================================================
// Workflow Resolution and Management
Expand Down Expand Up @@ -268,12 +271,14 @@ function resizeImage(filePath, maxSize) {
const height = parseInt(sizeInfo.match(/pixelHeight:\s*(\d+)/)?.[1] || "0", 10);
return { success: true, width, height };
} else {
// Linux/other: use ImageMagick (try IM6 first, then IM7)
// Linux/Windows: use ImageMagick (try IM6 first, then IM7)
// On Windows, \> is interpreted as redirect by cmd.exe — quote the geometry
const resizeArg = IS_WIN ? `"${maxSize}x${maxSize}>"` : `${maxSize}x${maxSize}\\>`;
try {
execSync(`convert "${filePath}" -resize ${maxSize}x${maxSize}\\> "${filePath}"`, { stdio: "pipe" });
execSync(`convert "${filePath}" -resize ${resizeArg} "${filePath}"`, { stdio: "pipe" });
} catch {
// IM7 uses 'magick' as main command
execSync(`magick "${filePath}" -resize ${maxSize}x${maxSize}\\> "${filePath}"`, { stdio: "pipe" });
execSync(`magick "${filePath}" -resize ${resizeArg} "${filePath}"`, { stdio: "pipe" });
}
// Get dimensions (IM7 may need 'magick identify' instead of just 'identify')
let sizeInfo;
Expand Down Expand Up @@ -2449,7 +2454,7 @@ tool = ALIASES[tool] || tool;
const config = loadConfig();
const autoSaveEnabled = config.autoSaveScreenshots !== false && !options["no-save"];
if (tool === "screenshot" && !options.output && !options.savePath && autoSaveEnabled) {
options.savePath = `/tmp/surf-snap-${Date.now()}.png`;
options.savePath = path.join(SURF_TMP, `surf-snap-${Date.now()}.png`);
}

if (tool === "smoke") {
Expand Down Expand Up @@ -2813,7 +2818,7 @@ const sendRequest = (toolName, toolArgs = {}) => {

const performAutoCapture = async () => {
const timestamp = Date.now();
const screenshotPath = `/tmp/surf-error-${timestamp}.png`;
const screenshotPath = path.join(SURF_TMP, `surf-error-${timestamp}.png`);

try {
const [screenshotResp, consoleResp] = await Promise.all([
Expand Down
2 changes: 1 addition & 1 deletion native/do-executor.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@

const net = require("net");

const SOCKET_PATH = "/tmp/surf.sock";
const SOCKET_PATH = process.platform === "win32" ? "//./pipe/surf" : "/tmp/surf.sock";

// Maximum iterations for loops (safety cap)
const MAX_LOOP_ITERATIONS = 100;
Expand Down
32 changes: 18 additions & 14 deletions native/host.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,11 @@ const perplexityClient = require("./perplexity-client.cjs");
const grokClient = require("./grok-client.cjs");
const { mapToolToMessage, mapComputerAction, formatToolContent } = require("./host-helpers.cjs");

const SOCKET_PATH = "/tmp/surf.sock";
const IS_WIN = process.platform === "win32";
const SURF_TMP = IS_WIN ? path.join(os.tmpdir(), "surf") : "/tmp";
const SOCKET_PATH = IS_WIN ? "//./pipe/surf" : "/tmp/surf.sock";
// Ensure tmp dir exists on Windows
if (IS_WIN) { try { fs.mkdirSync(SURF_TMP, { recursive: true }); } catch {} }

// Cross-platform image resize (macOS: sips, Linux: ImageMagick)
function resizeImage(filePath, maxSize) {
Expand All @@ -27,12 +31,14 @@ function resizeImage(filePath, maxSize) {
const height = parseInt(sizeInfo.match(/pixelHeight:\s*(\d+)/)?.[1] || "0", 10);
return { success: true, width, height };
} else {
// Linux/other: use ImageMagick (try IM6 first, then IM7)
// Linux/Windows: use ImageMagick (try IM6 first, then IM7)
// On Windows, \> is interpreted as redirect by cmd.exe — quote the geometry
const resizeArg = IS_WIN ? `"${maxSize}x${maxSize}>"` : `${maxSize}x${maxSize}\\>`;
try {
execSync(`convert "${filePath}" -resize ${maxSize}x${maxSize}\\> "${filePath}"`, { stdio: "pipe" });
execSync(`convert "${filePath}" -resize ${resizeArg} "${filePath}"`, { stdio: "pipe" });
} catch {
// IM7 uses 'magick' as main command
execSync(`magick "${filePath}" -resize ${maxSize}x${maxSize}\\> "${filePath}"`, { stdio: "pipe" });
execSync(`magick "${filePath}" -resize ${resizeArg} "${filePath}"`, { stdio: "pipe" });
}
// Get dimensions (IM7 may need 'magick identify' instead of just 'identify')
let sizeInfo;
Expand Down Expand Up @@ -73,7 +79,7 @@ async function processAiQueue() {
setTimeout(processAiQueue, 2000);
}
}
const LOG_FILE = "/tmp/surf-host.log";
const LOG_FILE = path.join(SURF_TMP, "surf-host.log");
const AUTH_FILE = path.join(os.homedir(), ".pi", "agent", "auth.json");

const DEFAULT_RETRY_OPTIONS = {
Expand Down Expand Up @@ -288,9 +294,7 @@ const log = (msg) => {

log("Host starting...");

try {
fs.unlinkSync(SOCKET_PATH);
} catch {}
if (!IS_WIN) { try { fs.unlinkSync(SOCKET_PATH); } catch {} }

const pendingRequests = new Map();
const pendingToolRequests = new Map();
Expand Down Expand Up @@ -1204,15 +1208,15 @@ function processInput() {
} else if (autoScreenshot && tabId && !msg.error && !msg.base64) {

const screenshotId = ++requestCounter;
const screenshotPath = `/tmp/pi-auto-${Date.now()}.png`;
const screenshotPath = path.join(SURF_TMP, `pi-auto-${Date.now()}.png`);

const autoFiles = fs.readdirSync("/tmp")
const autoFiles = fs.readdirSync(SURF_TMP)
.filter(f => f.startsWith("pi-auto-") && f.endsWith(".png"))
.map(f => ({ name: f, time: parseInt(f.match(/pi-auto-(\d+)\.png/)?.[1] || "0", 10) }))
.sort((a, b) => b.time - a.time);
if (autoFiles.length >= 10) {
autoFiles.slice(9).forEach(f => {
try { fs.unlinkSync(path.join("/tmp", f.name)); } catch (e) {}
try { fs.unlinkSync(path.join(SURF_TMP, f.name)); } catch (e) {}
});
}
pendingToolRequests.set(screenshotId, {
Expand Down Expand Up @@ -1440,7 +1444,7 @@ const server = net.createServer((socket) => {

server.listen(SOCKET_PATH, () => {
log("Socket server listening on " + SOCKET_PATH);
fs.chmodSync(SOCKET_PATH, 0o600);
if (!IS_WIN) { try { fs.chmodSync(SOCKET_PATH, 0o600); } catch {} }
writeMessage({ type: "HOST_READY" });
log("Sent HOST_READY to extension");
});
Expand All @@ -1452,14 +1456,14 @@ server.on("error", (err) => {
process.on("SIGTERM", () => {
log("SIGTERM received");
server.close();
try { fs.unlinkSync(SOCKET_PATH); } catch {}
if (!IS_WIN) { try { fs.unlinkSync(SOCKET_PATH); } catch {} }
process.exit(0);
});

process.on("SIGINT", () => {
log("SIGINT received");
server.close();
try { fs.unlinkSync(SOCKET_PATH); } catch {}
if (!IS_WIN) { try { fs.unlinkSync(SOCKET_PATH); } catch {} }
process.exit(0);
});

Expand Down
2 changes: 1 addition & 1 deletion native/mcp-server.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ const { McpServer } = require("@modelcontextprotocol/sdk/server/mcp.js");
const { StdioServerTransport } = require("@modelcontextprotocol/sdk/server/stdio.js");
const { z } = require("zod");

const SOCKET_PATH = "/tmp/surf.sock";
const SOCKET_PATH = process.platform === "win32" ? "//./pipe/surf" : "/tmp/surf.sock";
const REQUEST_TIMEOUT = 30000;

const TOOL_SCHEMAS = {
Expand Down
4 changes: 3 additions & 1 deletion native/network-store.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,9 @@ const crypto = require("crypto");
const readline = require("readline");

// Configuration
const DEFAULT_BASE = "/tmp/surf";
const DEFAULT_BASE = process.platform === "win32"
? path.join(require("os").tmpdir(), "surf")
: "/tmp/surf";
const DEFAULT_TTL = 24 * 60 * 60 * 1000; // 24 hours
const DEFAULT_MAX_SIZE = 200 * 1024 * 1024; // 200MB
const AUTO_CLEANUP_INTERVAL = 60 * 60 * 1000; // 1 hour
Expand Down
10 changes: 8 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.