remotelink 0.3.6 → 0.3.8

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/README.md CHANGED
@@ -49,6 +49,15 @@ npx remotelink --help Show help
49
49
 
50
50
  The package also exposes the aliases `remote-link` and `remote-arc`.
51
51
 
52
+ ## Native execution core
53
+
54
+ Remote Arc no longer shells out to a third-party computer-control MCP server.
55
+ The CLI bundles Remote Arc's own cross-platform execution core for filesystem,
56
+ process, terminal, Local Undo, and Safety Guard behavior.
57
+
58
+ MCP remains the interoperability protocol between AI clients and Remote Arc;
59
+ local OS execution is implemented and versioned by Remote Arc itself.
60
+
52
61
  ## Capability model
53
62
 
54
63
  Newly paired devices start with only read-oriented skills enabled:
package/dist/index.js CHANGED
@@ -2,31 +2,245 @@
2
2
 
3
3
  // src/index.ts
4
4
  import os2 from "os";
5
- import path2 from "path";
6
- import fs2 from "fs/promises";
7
- import { spawn } from "child_process";
8
- import process2 from "process";
9
- import { Client } from "@modelcontextprotocol/client";
10
- import { StdioClientTransport } from "@modelcontextprotocol/client/stdio";
5
+ import path3 from "path";
6
+ import fs3 from "fs/promises";
7
+ import { spawn as spawn2 } from "child_process";
8
+ import process3 from "process";
11
9
  import WebSocket from "ws";
12
10
 
13
- // src/local-safety.ts
11
+ // ../execution-core/src/filesystem.ts
12
+ import fs from "fs/promises";
13
+ import path from "path";
14
+ var MAX_DIRECTORY_ENTRIES = 2e3;
15
+ var DEFAULT_READ_LINES = 240;
16
+ var MAX_TEXT_FILE_BYTES = 20 * 1024 * 1024;
17
+ var printableSize = (bytes) => {
18
+ if (bytes < 1024) return `${bytes} B`;
19
+ if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;
20
+ return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
21
+ };
22
+ async function listDirectory(targetPath, depth = 2) {
23
+ const maxDepth = Math.max(1, Math.min(10, Math.trunc(depth || 2)));
24
+ const lines = [];
25
+ let entriesSeen = 0;
26
+ async function walk(directory, level, prefix) {
27
+ if (entriesSeen >= MAX_DIRECTORY_ENTRIES) return;
28
+ const entries = await fs.readdir(directory, { withFileTypes: true });
29
+ entries.sort((a, b) => {
30
+ if (a.isDirectory() !== b.isDirectory()) return a.isDirectory() ? -1 : 1;
31
+ return a.name.localeCompare(b.name);
32
+ });
33
+ for (const entry of entries) {
34
+ if (entriesSeen >= MAX_DIRECTORY_ENTRIES) break;
35
+ entriesSeen += 1;
36
+ const absolute = path.join(directory, entry.name);
37
+ const label = entry.isDirectory() ? "[DIR]" : entry.isSymbolicLink() ? "[LINK]" : "[FILE]";
38
+ lines.push(`${prefix}${label} ${entry.name}`);
39
+ if (entry.isDirectory() && level < maxDepth) {
40
+ await walk(absolute, level + 1, prefix + " ");
41
+ }
42
+ }
43
+ }
44
+ const stat = await fs.stat(targetPath);
45
+ if (!stat.isDirectory()) throw new Error("Path is not a directory: " + targetPath);
46
+ await walk(targetPath, 1, "");
47
+ if (entriesSeen >= MAX_DIRECTORY_ENTRIES) {
48
+ lines.push(`\u2026 truncated after ${MAX_DIRECTORY_ENTRIES} entries`);
49
+ }
50
+ return `Directory: ${targetPath}
51
+ Depth: ${maxDepth}
52
+
53
+ ${lines.join("\n") || "(empty)"}`;
54
+ }
55
+ async function readTextFile(targetPath, offset, length) {
56
+ const stat = await fs.stat(targetPath);
57
+ if (!stat.isFile()) throw new Error("Path is not a file: " + targetPath);
58
+ if (stat.size > MAX_TEXT_FILE_BYTES) {
59
+ throw new Error(
60
+ `File is too large for read_file (${printableSize(stat.size)} > 20 MB). Use a terminal command or a more targeted tool instead.`
61
+ );
62
+ }
63
+ const buffer = await fs.readFile(targetPath);
64
+ const sample = buffer.subarray(0, Math.min(buffer.length, 8192));
65
+ if (sample.includes(0)) {
66
+ throw new Error("Binary file detected. read_file currently supports text files only.");
67
+ }
68
+ const text = buffer.toString("utf8");
69
+ const lines = text.split(/\r?\n/);
70
+ const requestedOffset = Number.isFinite(offset) ? Math.trunc(offset) : 0;
71
+ const start = requestedOffset < 0 ? Math.max(0, lines.length + requestedOffset) : Math.min(lines.length, Math.max(0, requestedOffset));
72
+ const requestedLength = Number.isFinite(length) && length > 0 ? Math.trunc(length) : DEFAULT_READ_LINES;
73
+ const end = Math.min(lines.length, start + requestedLength);
74
+ const chunk = lines.slice(start, end).join("\n");
75
+ const location = start === 0 ? "start" : end === lines.length ? `line ${start + 1} to end` : `lines ${start + 1}-${end}`;
76
+ return `[Reading ${end - start} lines from ${location} (total: ${lines.length} lines, ${printableSize(stat.size)})]
77
+
78
+ ${chunk}`;
79
+ }
80
+ async function getFileInfo(targetPath) {
81
+ const stat = await fs.lstat(targetPath);
82
+ return {
83
+ path: targetPath,
84
+ type: stat.isFile() ? "file" : stat.isDirectory() ? "directory" : stat.isSymbolicLink() ? "symlink" : "other",
85
+ size: stat.size,
86
+ size_human: printableSize(stat.size),
87
+ mode: stat.mode,
88
+ created_at: stat.birthtime.toISOString(),
89
+ modified_at: stat.mtime.toISOString(),
90
+ accessed_at: stat.atime.toISOString()
91
+ };
92
+ }
93
+ async function writeTextFile(targetPath, content, mode = "rewrite") {
94
+ await fs.mkdir(path.dirname(targetPath), { recursive: true });
95
+ if (mode === "append") {
96
+ await fs.appendFile(targetPath, content, "utf8");
97
+ } else {
98
+ await fs.writeFile(targetPath, content, "utf8");
99
+ }
100
+ const stat = await fs.stat(targetPath);
101
+ return {
102
+ path: targetPath,
103
+ mode,
104
+ bytes: Buffer.byteLength(content),
105
+ file_size: stat.size
106
+ };
107
+ }
108
+ async function editTextBlock(filePath, oldString, newString, expectedReplacements = 1) {
109
+ if (!oldString) throw new Error("old_string cannot be empty.");
110
+ const current = await fs.readFile(filePath, "utf8");
111
+ const parts = current.split(oldString);
112
+ const replacements = parts.length - 1;
113
+ if (replacements !== expectedReplacements) {
114
+ throw new Error(
115
+ `Expected ${expectedReplacements} replacement(s) in ${filePath}, found ${replacements}. No changes were written.`
116
+ );
117
+ }
118
+ const next = parts.join(newString);
119
+ await fs.writeFile(filePath, next, "utf8");
120
+ return {
121
+ path: filePath,
122
+ replacements,
123
+ bytes_before: Buffer.byteLength(current),
124
+ bytes_after: Buffer.byteLength(next)
125
+ };
126
+ }
127
+
128
+ // ../execution-core/src/process.ts
129
+ import { execFile, spawn } from "child_process";
130
+ import process2 from "process";
131
+ var MAX_CAPTURE_BYTES = 2 * 1024 * 1024;
132
+ function appendCapped(current, chunk) {
133
+ if (Buffer.byteLength(current) >= MAX_CAPTURE_BYTES) return current;
134
+ const next = current + chunk.toString();
135
+ if (Buffer.byteLength(next) <= MAX_CAPTURE_BYTES) return next;
136
+ return next.slice(0, MAX_CAPTURE_BYTES) + "\n\u2026 output truncated \u2026";
137
+ }
138
+ async function listProcesses() {
139
+ const output = await new Promise((resolve, reject) => {
140
+ const command = process2.platform === "win32" ? "tasklist.exe" : "ps";
141
+ const args = process2.platform === "win32" ? ["/FO", "CSV", "/NH"] : ["-axo", "pid,ppid,user,%cpu,%mem,etime,command"];
142
+ execFile(command, args, { maxBuffer: MAX_CAPTURE_BYTES }, (error, stdout, stderr) => {
143
+ if (error) {
144
+ reject(new Error(`Could not list processes: ${stderr || error.message}`));
145
+ return;
146
+ }
147
+ resolve(stdout.trim());
148
+ });
149
+ });
150
+ return `Processes on ${process2.platform}:
151
+
152
+ ${output}`;
153
+ }
154
+ async function terminateTree(child) {
155
+ if (!child.pid) return;
156
+ if (process2.platform === "win32") {
157
+ await new Promise((resolve) => {
158
+ const killer = spawn(
159
+ "taskkill.exe",
160
+ ["/PID", String(child.pid), "/T", "/F"],
161
+ { windowsHide: true, stdio: "ignore" }
162
+ );
163
+ killer.once("close", () => resolve());
164
+ killer.once("error", () => resolve());
165
+ });
166
+ return;
167
+ }
168
+ try {
169
+ process2.kill(-child.pid, "SIGTERM");
170
+ } catch {
171
+ child.kill("SIGTERM");
172
+ }
173
+ await new Promise((resolve) => setTimeout(resolve, 300));
174
+ try {
175
+ process2.kill(-child.pid, "SIGKILL");
176
+ } catch {
177
+ if (!child.killed) child.kill("SIGKILL");
178
+ }
179
+ }
180
+ async function runShellCommand(command, timeoutMs = 5e3) {
181
+ const timeout = Math.max(100, Math.min(12e4, Math.trunc(timeoutMs || 5e3)));
182
+ const startedAt = Date.now();
183
+ return await new Promise((resolve, reject) => {
184
+ const child = spawn(command, {
185
+ shell: true,
186
+ windowsHide: true,
187
+ detached: process2.platform !== "win32",
188
+ stdio: ["ignore", "pipe", "pipe"]
189
+ });
190
+ let stdout = "";
191
+ let stderr = "";
192
+ let timedOut = false;
193
+ let settled = false;
194
+ child.stdout?.on("data", (chunk) => {
195
+ stdout = appendCapped(stdout, chunk);
196
+ });
197
+ child.stderr?.on("data", (chunk) => {
198
+ stderr = appendCapped(stderr, chunk);
199
+ });
200
+ const timer = setTimeout(async () => {
201
+ timedOut = true;
202
+ await terminateTree(child);
203
+ }, timeout);
204
+ child.once("error", (error) => {
205
+ if (settled) return;
206
+ settled = true;
207
+ clearTimeout(timer);
208
+ reject(error);
209
+ });
210
+ child.once("close", (code, signal) => {
211
+ if (settled) return;
212
+ settled = true;
213
+ clearTimeout(timer);
214
+ resolve({
215
+ command,
216
+ exit_code: code,
217
+ signal,
218
+ stdout,
219
+ stderr,
220
+ duration_ms: Date.now() - startedAt,
221
+ timed_out: timedOut
222
+ });
223
+ });
224
+ });
225
+ }
226
+
227
+ // ../execution-core/src/safety.ts
14
228
  import crypto from "crypto";
15
229
  import { createReadStream } from "fs";
16
- import fs from "fs/promises";
230
+ import fs2 from "fs/promises";
17
231
  import os from "os";
18
- import path from "path";
19
- var UNDO_ROOT = path.join(os.homedir(), ".remotearc", "undo");
232
+ import path2 from "path";
20
233
  var RETENTION_MS = 7 * 24 * 60 * 60 * 1e3;
21
234
  var MAX_SNAPSHOT_BYTES = 20 * 1024 * 1024;
22
235
  var MAX_UNDO_BYTES = 200 * 1024 * 1024;
236
+ var undoRoot = () => process.env.REMOTEARC_UNDO_ROOT || path2.join(os.homedir(), ".remotearc", "undo");
23
237
  async function ensureUndoRoot() {
24
- await fs.mkdir(UNDO_ROOT, { recursive: true, mode: 448 });
238
+ await fs2.mkdir(undoRoot(), { recursive: true, mode: 448 });
25
239
  }
26
240
  async function readManifest(directory) {
27
241
  try {
28
242
  return JSON.parse(
29
- await fs.readFile(path.join(directory, "manifest.json"), "utf8")
243
+ await fs2.readFile(path2.join(directory, "manifest.json"), "utf8")
30
244
  );
31
245
  } catch {
32
246
  return null;
@@ -34,8 +248,8 @@ async function readManifest(directory) {
34
248
  }
35
249
  async function snapshotDirectories() {
36
250
  await ensureUndoRoot();
37
- const entries = await fs.readdir(UNDO_ROOT, { withFileTypes: true });
38
- return entries.filter((entry) => entry.isDirectory()).map((entry) => path.join(UNDO_ROOT, entry.name));
251
+ const entries = await fs2.readdir(undoRoot(), { withFileTypes: true });
252
+ return entries.filter((entry) => entry.isDirectory()).map((entry) => path2.join(undoRoot(), entry.name));
39
253
  }
40
254
  async function cleanupUndoStore() {
41
255
  const now = Date.now();
@@ -43,12 +257,12 @@ async function cleanupUndoStore() {
43
257
  for (const directory of await snapshotDirectories()) {
44
258
  const manifest = await readManifest(directory);
45
259
  if (!manifest) {
46
- await fs.rm(directory, { recursive: true, force: true }).catch(() => void 0);
260
+ await fs2.rm(directory, { recursive: true, force: true }).catch(() => void 0);
47
261
  continue;
48
262
  }
49
263
  const created = Date.parse(manifest.createdAt);
50
264
  if (!Number.isFinite(created) || now - created > RETENTION_MS) {
51
- await fs.rm(directory, { recursive: true, force: true }).catch(() => void 0);
265
+ await fs2.rm(directory, { recursive: true, force: true }).catch(() => void 0);
52
266
  continue;
53
267
  }
54
268
  snapshots.push({ directory, manifest });
@@ -59,7 +273,7 @@ async function cleanupUndoStore() {
59
273
  let total = snapshots.reduce((sum, item) => sum + item.manifest.bytes, 0);
60
274
  for (const item of snapshots) {
61
275
  if (total <= MAX_UNDO_BYTES) break;
62
- await fs.rm(item.directory, { recursive: true, force: true }).catch(() => void 0);
276
+ await fs2.rm(item.directory, { recursive: true, force: true }).catch(() => void 0);
63
277
  total -= item.manifest.bytes;
64
278
  }
65
279
  }
@@ -76,22 +290,22 @@ async function createUndoSnapshot(tool, args) {
76
290
  let bytes = 0;
77
291
  let original = null;
78
292
  try {
79
- const stat = await fs.stat(targetPath);
293
+ const stat = await fs2.stat(targetPath);
80
294
  if (!stat.isFile()) return null;
81
295
  existed = true;
82
296
  mode = stat.mode;
83
297
  bytes = stat.size;
84
298
  if (bytes > MAX_SNAPSHOT_BYTES) return null;
85
- original = await fs.readFile(targetPath);
299
+ original = await fs2.readFile(targetPath);
86
300
  } catch (error) {
87
301
  const code = error && typeof error === "object" && "code" in error ? String(error.code) : "";
88
302
  if (code !== "ENOENT") throw error;
89
303
  }
90
304
  const id = `${Date.now()}-${crypto.randomUUID().slice(0, 8)}`;
91
- const directory = path.join(UNDO_ROOT, id);
92
- await fs.mkdir(directory, { recursive: true, mode: 448 });
305
+ const directory = path2.join(undoRoot(), id);
306
+ await fs2.mkdir(directory, { recursive: true, mode: 448 });
93
307
  if (original) {
94
- await fs.writeFile(path.join(directory, "content.bin"), original, { mode: 384 });
308
+ await fs2.writeFile(path2.join(directory, "content.bin"), original, { mode: 384 });
95
309
  }
96
310
  const manifest = {
97
311
  id,
@@ -102,8 +316,8 @@ async function createUndoSnapshot(tool, args) {
102
316
  ...mode !== void 0 ? { mode } : {},
103
317
  bytes
104
318
  };
105
- await fs.writeFile(
106
- path.join(directory, "manifest.json"),
319
+ await fs2.writeFile(
320
+ path2.join(directory, "manifest.json"),
107
321
  JSON.stringify(manifest, null, 2) + "\n",
108
322
  { mode: 384 }
109
323
  );
@@ -112,18 +326,15 @@ async function createUndoSnapshot(tool, args) {
112
326
  }
113
327
  async function hashFile(filePath) {
114
328
  const hash = crypto.createHash("sha256");
115
- for await (const chunk of createReadStream(filePath)) {
116
- hash.update(chunk);
117
- }
329
+ for await (const chunk of createReadStream(filePath)) hash.update(chunk);
118
330
  return hash.digest("hex");
119
331
  }
120
332
  async function finalizeUndoSnapshot(snapshot) {
121
333
  if (!snapshot) return false;
122
334
  try {
123
- const postChangeHash = await hashFile(snapshot.manifest.targetPath);
124
- snapshot.manifest.postChangeHash = postChangeHash;
125
- await fs.writeFile(
126
- path.join(snapshot.directory, "manifest.json"),
335
+ snapshot.manifest.postChangeHash = await hashFile(snapshot.manifest.targetPath);
336
+ await fs2.writeFile(
337
+ path2.join(snapshot.directory, "manifest.json"),
127
338
  JSON.stringify(snapshot.manifest, null, 2) + "\n",
128
339
  { mode: 384 }
129
340
  );
@@ -135,7 +346,7 @@ async function finalizeUndoSnapshot(snapshot) {
135
346
  }
136
347
  async function discardUndoSnapshot(snapshot) {
137
348
  if (!snapshot) return;
138
- await fs.rm(snapshot.directory, { recursive: true, force: true }).catch(() => void 0);
349
+ await fs2.rm(snapshot.directory, { recursive: true, force: true }).catch(() => void 0);
139
350
  }
140
351
  async function undoLastChange() {
141
352
  const candidates = [];
@@ -169,16 +380,16 @@ async function undoLastChange() {
169
380
  );
170
381
  }
171
382
  if (latest.manifest.existed) {
172
- const original = await fs.readFile(path.join(latest.directory, "content.bin"));
173
- await fs.mkdir(path.dirname(latest.manifest.targetPath), { recursive: true });
174
- await fs.writeFile(latest.manifest.targetPath, original);
383
+ const original = await fs2.readFile(path2.join(latest.directory, "content.bin"));
384
+ await fs2.mkdir(path2.dirname(latest.manifest.targetPath), { recursive: true });
385
+ await fs2.writeFile(latest.manifest.targetPath, original);
175
386
  if (latest.manifest.mode !== void 0) {
176
- await fs.chmod(latest.manifest.targetPath, latest.manifest.mode).catch(() => void 0);
387
+ await fs2.chmod(latest.manifest.targetPath, latest.manifest.mode).catch(() => void 0);
177
388
  }
178
389
  } else {
179
- await fs.rm(latest.manifest.targetPath, { force: true });
390
+ await fs2.rm(latest.manifest.targetPath, { force: true });
180
391
  }
181
- await fs.rm(latest.directory, { recursive: true, force: true });
392
+ await fs2.rm(latest.directory, { recursive: true, force: true });
182
393
  return {
183
394
  restored: true,
184
395
  action_id: latest.manifest.id,
@@ -236,12 +447,7 @@ function assertCommandAllowed(command) {
236
447
  }
237
448
  }
238
449
 
239
- // src/index.ts
240
- var VERSION = "0.3.6";
241
- var DEFAULT_ORIGIN = "https://mcp.remotearc.app";
242
- var CONFIG_DIR = path2.join(os2.homedir(), ".remotearc");
243
- var CONFIG_PATH = path2.join(CONFIG_DIR, "config.json");
244
- var LEGACY_CONFIG_PATH = path2.join(os2.homedir(), ".remote-link", "config.json");
450
+ // ../execution-core/src/core.ts
245
451
  var SAFE_TOOLS = /* @__PURE__ */ new Set([
246
452
  "list_directory",
247
453
  "read_file",
@@ -250,13 +456,214 @@ var SAFE_TOOLS = /* @__PURE__ */ new Set([
250
456
  ]);
251
457
  var DEVELOPER_TOOLS = /* @__PURE__ */ new Set([
252
458
  ...SAFE_TOOLS,
253
- "start_process",
254
459
  "write_file",
255
460
  "edit_block",
256
461
  "undo_last_change"
257
462
  ]);
463
+ var FULL_TOOLS = /* @__PURE__ */ new Set([
464
+ ...DEVELOPER_TOOLS,
465
+ "start_process"
466
+ ]);
467
+ var DEFINITIONS = [
468
+ {
469
+ name: "list_directory",
470
+ description: "List files and directories on this computer without following directory symlinks.",
471
+ inputSchema: {
472
+ type: "object",
473
+ properties: {
474
+ path: { type: "string" },
475
+ depth: { type: "integer", minimum: 1, maximum: 10, default: 2 }
476
+ },
477
+ required: ["path"],
478
+ additionalProperties: false
479
+ }
480
+ },
481
+ {
482
+ name: "read_file",
483
+ description: "Read a text file by line range. Negative offsets read from the end.",
484
+ inputSchema: {
485
+ type: "object",
486
+ properties: {
487
+ path: { type: "string" },
488
+ offset: { type: "integer" },
489
+ length: { type: "integer", minimum: 1 }
490
+ },
491
+ required: ["path"],
492
+ additionalProperties: false
493
+ }
494
+ },
495
+ {
496
+ name: "get_file_info",
497
+ description: "Get local file or directory metadata.",
498
+ inputSchema: {
499
+ type: "object",
500
+ properties: { path: { type: "string" } },
501
+ required: ["path"],
502
+ additionalProperties: false
503
+ }
504
+ },
505
+ {
506
+ name: "list_processes",
507
+ description: "List processes running on this computer.",
508
+ inputSchema: { type: "object", properties: {}, additionalProperties: false }
509
+ },
510
+ {
511
+ name: "write_file",
512
+ description: "Write or append UTF-8 text. Remote Arc creates a local-only Undo snapshot first.",
513
+ inputSchema: {
514
+ type: "object",
515
+ properties: {
516
+ path: { type: "string" },
517
+ content: { type: "string" },
518
+ mode: { type: "string", enum: ["rewrite", "append"], default: "rewrite" }
519
+ },
520
+ required: ["path", "content"],
521
+ additionalProperties: false
522
+ }
523
+ },
524
+ {
525
+ name: "edit_block",
526
+ description: "Apply an exact text replacement with conflict-safe Local Undo.",
527
+ inputSchema: {
528
+ type: "object",
529
+ properties: {
530
+ file_path: { type: "string" },
531
+ old_string: { type: "string" },
532
+ new_string: { type: "string" },
533
+ expected_replacements: { type: "integer", minimum: 1, default: 1 }
534
+ },
535
+ required: ["file_path", "old_string", "new_string"],
536
+ additionalProperties: false
537
+ }
538
+ },
539
+ {
540
+ name: "undo_last_change",
541
+ description: "Undo the newest reversible Remote Arc file edit stored only on this device.",
542
+ inputSchema: { type: "object", properties: {}, additionalProperties: false }
543
+ },
544
+ {
545
+ name: "start_process",
546
+ description: "Run a shell command with timeout and output capture. Catastrophic command patterns are blocked locally.",
547
+ inputSchema: {
548
+ type: "object",
549
+ properties: {
550
+ command: { type: "string" },
551
+ timeout_ms: { type: "integer", minimum: 100, maximum: 12e4, default: 5e3 }
552
+ },
553
+ required: ["command"],
554
+ additionalProperties: false
555
+ }
556
+ }
557
+ ];
558
+ var textResult = (value) => ({
559
+ content: [
560
+ {
561
+ type: "text",
562
+ text: typeof value === "string" ? value : JSON.stringify(value, null, 2)
563
+ }
564
+ ]
565
+ });
566
+ function requiredString(args, key) {
567
+ const value = args[key];
568
+ if (typeof value !== "string") throw new Error(`${key} must be a string.`);
569
+ return value;
570
+ }
571
+ function optionalNumber(args, key) {
572
+ const value = args[key];
573
+ return typeof value === "number" && Number.isFinite(value) ? value : void 0;
574
+ }
575
+ var RemoteArcExecutionCore = class {
576
+ constructor(mode = "managed") {
577
+ this.mode = mode;
578
+ }
579
+ mode;
580
+ allowedTools() {
581
+ if (this.mode === "safe") return SAFE_TOOLS;
582
+ if (this.mode === "developer") return DEVELOPER_TOOLS;
583
+ return FULL_TOOLS;
584
+ }
585
+ listTools() {
586
+ const allowed = this.allowedTools();
587
+ return DEFINITIONS.filter((tool) => allowed.has(tool.name));
588
+ }
589
+ async callTool(name, args = {}) {
590
+ const toolName = name;
591
+ if (!this.allowedTools().has(toolName)) {
592
+ throw new Error(`Tool blocked by local permission mode: ${name}`);
593
+ }
594
+ switch (toolName) {
595
+ case "list_directory":
596
+ return textResult(
597
+ await listDirectory(
598
+ requiredString(args, "path"),
599
+ optionalNumber(args, "depth") ?? 2
600
+ )
601
+ );
602
+ case "read_file":
603
+ return textResult(
604
+ await readTextFile(
605
+ requiredString(args, "path"),
606
+ optionalNumber(args, "offset"),
607
+ optionalNumber(args, "length")
608
+ )
609
+ );
610
+ case "get_file_info":
611
+ return textResult(await getFileInfo(requiredString(args, "path")));
612
+ case "list_processes":
613
+ return textResult(await listProcesses());
614
+ case "undo_last_change":
615
+ return textResult(await undoLastChange());
616
+ case "start_process": {
617
+ const command = requiredString(args, "command");
618
+ assertCommandAllowed(command);
619
+ return textResult(
620
+ await runShellCommand(
621
+ command,
622
+ optionalNumber(args, "timeout_ms") ?? 5e3
623
+ )
624
+ );
625
+ }
626
+ case "write_file":
627
+ case "edit_block": {
628
+ const snapshot = await createUndoSnapshot(toolName, args);
629
+ try {
630
+ const result = toolName === "write_file" ? await writeTextFile(
631
+ requiredString(args, "path"),
632
+ requiredString(args, "content"),
633
+ args.mode === "append" ? "append" : "rewrite"
634
+ ) : await editTextBlock(
635
+ requiredString(args, "file_path"),
636
+ requiredString(args, "old_string"),
637
+ requiredString(args, "new_string"),
638
+ optionalNumber(args, "expected_replacements") ?? 1
639
+ );
640
+ const undoAvailable = await finalizeUndoSnapshot(snapshot);
641
+ return textResult({
642
+ ...result,
643
+ undo_available: undoAvailable,
644
+ undo_storage: undoAvailable ? "local-device-only" : null
645
+ });
646
+ } catch (error) {
647
+ await discardUndoSnapshot(snapshot);
648
+ throw error;
649
+ }
650
+ }
651
+ default:
652
+ throw new Error("Unknown Remote Arc tool: " + name);
653
+ }
654
+ }
655
+ async close() {
656
+ }
657
+ };
658
+
659
+ // src/index.ts
660
+ var VERSION = "0.3.8";
661
+ var DEFAULT_ORIGIN = "https://mcp.remotearc.app";
662
+ var CONFIG_DIR = path3.join(os2.homedir(), ".remotearc");
663
+ var CONFIG_PATH = path3.join(CONFIG_DIR, "config.json");
664
+ var LEGACY_CONFIG_PATH = path3.join(os2.homedir(), ".remote-link", "config.json");
258
665
  var sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
259
- var supportsColor = process2.stdout.isTTY && !process2.env.NO_COLOR;
666
+ var supportsColor = process3.stdout.isTTY && !process3.env.NO_COLOR;
260
667
  var paint = (code, value) => supportsColor ? `\x1B[${code}m${value}\x1B[0m` : value;
261
668
  var dim = (value) => paint("2", value);
262
669
  var cyan = (value) => paint("36", value);
@@ -274,16 +681,16 @@ function nowTime() {
274
681
  }
275
682
  function logLine(level, message) {
276
683
  const icon = level === "success" ? green("\u2713") : level === "warn" ? yellow("!") : level === "error" ? red("\xD7") : level === "event" ? cyan("\u2192") : cyan("\u2022");
277
- process2.stdout.write(`${dim(nowTime())} ${icon} ${message}
684
+ process3.stdout.write(`${dim(nowTime())} ${icon} ${message}
278
685
  `);
279
686
  }
280
687
  function banner() {
281
- process2.stdout.write("\n");
282
- process2.stdout.write(bold("Remote Arc") + " " + dim(`v${VERSION}`) + "\n");
283
- process2.stdout.write(dim("Secure remote MCP bridge") + "\n\n");
688
+ process3.stdout.write("\n");
689
+ process3.stdout.write(bold("Remote Arc") + " " + dim(`v${VERSION}`) + "\n");
690
+ process3.stdout.write(dim("Secure remote MCP bridge") + "\n\n");
284
691
  }
285
692
  function argFlag(name) {
286
- return process2.argv.includes(name);
693
+ return process3.argv.includes(name);
287
694
  }
288
695
  function selectedMode() {
289
696
  if (argFlag("--safe")) return "safe";
@@ -297,11 +704,11 @@ function modeLabel(mode) {
297
704
  }
298
705
  async function readConfig() {
299
706
  try {
300
- return JSON.parse(await fs2.readFile(CONFIG_PATH, "utf8"));
707
+ return JSON.parse(await fs3.readFile(CONFIG_PATH, "utf8"));
301
708
  } catch {
302
709
  try {
303
710
  const legacy = JSON.parse(
304
- await fs2.readFile(LEGACY_CONFIG_PATH, "utf8")
711
+ await fs3.readFile(LEGACY_CONFIG_PATH, "utf8")
305
712
  );
306
713
  await writeConfig(legacy);
307
714
  logLine("success", "Migrated existing Remote Link pairing to Remote Arc.");
@@ -312,22 +719,22 @@ async function readConfig() {
312
719
  }
313
720
  }
314
721
  async function writeConfig(config) {
315
- await fs2.mkdir(CONFIG_DIR, { recursive: true });
316
- await fs2.writeFile(CONFIG_PATH, JSON.stringify(config, null, 2) + "\n", {
722
+ await fs3.mkdir(CONFIG_DIR, { recursive: true });
723
+ await fs3.writeFile(CONFIG_PATH, JSON.stringify(config, null, 2) + "\n", {
317
724
  mode: 384
318
725
  });
319
726
  }
320
727
  async function resetConfig() {
321
728
  await Promise.all([
322
- fs2.rm(CONFIG_PATH, { force: true }),
323
- fs2.rm(LEGACY_CONFIG_PATH, { force: true })
729
+ fs3.rm(CONFIG_PATH, { force: true }),
730
+ fs3.rm(LEGACY_CONFIG_PATH, { force: true })
324
731
  ]);
325
732
  logLine("success", "Removed saved device credentials.");
326
733
  }
327
734
  function openBrowser(url) {
328
- const command = process2.platform === "win32" ? "cmd" : process2.platform === "darwin" ? "open" : "xdg-open";
329
- const args = process2.platform === "win32" ? ["/c", "start", "", url] : [url];
330
- const child = spawn(command, args, {
735
+ const command = process3.platform === "win32" ? "cmd" : process3.platform === "darwin" ? "open" : "xdg-open";
736
+ const args = process3.platform === "win32" ? ["/c", "start", "", url] : [url];
737
+ const child = spawn2(command, args, {
331
738
  detached: true,
332
739
  stdio: "ignore"
333
740
  });
@@ -340,8 +747,8 @@ async function pair(origin, mode) {
340
747
  headers: { "content-type": "application/json" },
341
748
  body: JSON.stringify({
342
749
  device_name: deviceName,
343
- platform: process2.platform,
344
- arch: process2.arch,
750
+ platform: process3.platform,
751
+ arch: process3.arch,
345
752
  hostname: os2.hostname()
346
753
  })
347
754
  });
@@ -350,10 +757,10 @@ async function pair(origin, mode) {
350
757
  }
351
758
  const pairing = await response.json();
352
759
  banner();
353
- logLine("info", `Device: ${bold(deviceName)} \xB7 ${process2.platform}/${process2.arch} \xB7 ${modeLabel(mode)}`);
760
+ logLine("info", `Device: ${bold(deviceName)} \xB7 ${process3.platform}/${process3.arch} \xB7 ${modeLabel(mode)}`);
354
761
  logLine("event", "Pairing required \u2014 opening secure browser approval.");
355
- process2.stdout.write("\n Pairing code " + bold(cyan(pairing.user_code)) + "\n");
356
- process2.stdout.write(" " + dim(pairing.verification_uri_complete) + "\n\n");
762
+ process3.stdout.write("\n Pairing code " + bold(cyan(pairing.user_code)) + "\n");
763
+ process3.stdout.write(" " + dim(pairing.verification_uri_complete) + "\n\n");
357
764
  openBrowser(pairing.verification_uri_complete);
358
765
  logLine("info", "Waiting for authorization\u2026");
359
766
  const startedAt = Date.now();
@@ -368,7 +775,7 @@ async function pair(origin, mode) {
368
775
  })
369
776
  });
370
777
  if (tokenResponse.status === 428) {
371
- if (process2.stdout.isTTY) process2.stdout.write(dim("\xB7"));
778
+ if (process3.stdout.isTTY) process3.stdout.write(dim("\xB7"));
372
779
  continue;
373
780
  }
374
781
  if (!tokenResponse.ok) {
@@ -376,7 +783,7 @@ async function pair(origin, mode) {
376
783
  throw new Error("Pairing failed: " + body);
377
784
  }
378
785
  const result = await tokenResponse.json();
379
- process2.stdout.write("\n");
786
+ process3.stdout.write("\n");
380
787
  logLine("success", "Device authorized.");
381
788
  const config = {
382
789
  deviceId: result.device_id,
@@ -391,115 +798,43 @@ async function pair(origin, mode) {
391
798
  throw new Error("Pairing expired. Run Remote Arc again to retry.");
392
799
  }
393
800
  var ExecutionCore = class {
801
+ core;
394
802
  constructor(mode) {
395
- this.mode = mode;
396
- }
397
- mode;
398
- client = null;
399
- async connect() {
400
- if (this.client) return this.client;
401
- const client = new Client({
402
- name: "remotearc-cli-core",
403
- version: VERSION
404
- });
405
- const command = process2.platform === "win32" ? "npx.cmd" : "npx";
406
- const transport = new StdioClientTransport({
407
- command,
408
- args: ["-y", "@wonderwhy-er/desktop-commander@latest"],
409
- stderr: "inherit"
410
- });
411
- logLine("info", "Starting local execution core\u2026");
412
- await client.connect(transport);
413
- this.client = client;
414
- logLine("success", "Local execution core ready.");
415
- return client;
803
+ this.core = new RemoteArcExecutionCore(
804
+ isLocalSafeMode(mode) ? "safe" : "managed"
805
+ );
416
806
  }
417
807
  async tools() {
418
- const list = await (await this.connect()).listTools();
419
- const locallyAvailable = isLocalSafeMode(this.mode) ? SAFE_TOOLS : DEVELOPER_TOOLS;
420
- const tools = list.tools.filter((tool) => locallyAvailable.has(tool.name));
421
- if (!isLocalSafeMode(this.mode)) {
422
- tools.push({
423
- name: "undo_last_change",
424
- description: "Undo the most recent reversible file change made through Remote Arc on this device. Snapshots stay on the device and expire automatically.",
425
- inputSchema: {
426
- type: "object",
427
- properties: {},
428
- additionalProperties: false
429
- }
430
- });
431
- }
432
- return tools;
808
+ return this.core.listTools();
433
809
  }
434
810
  async call(name, args) {
435
- const locallyAvailable = isLocalSafeMode(this.mode) ? SAFE_TOOLS : DEVELOPER_TOOLS;
436
- if (!locallyAvailable.has(name)) {
437
- throw new Error("Tool blocked by local safety cap: " + name);
438
- }
439
- if (name === "undo_last_change") {
440
- const result = await undoLastChange();
441
- logLine("success", "Local Undo restored the latest reversible file change.");
442
- return {
443
- content: [{ type: "text", text: JSON.stringify(result, null, 2) }]
444
- };
445
- }
446
- if (name === "start_process") {
447
- assertCommandAllowed(String(args.command || ""));
448
- }
449
- const reversibleTool = name === "write_file" || name === "edit_block" ? name : null;
450
- const snapshot = reversibleTool ? await createUndoSnapshot(reversibleTool, args) : null;
451
- if (reversibleTool && !snapshot) {
452
- logLine("warn", "Local Undo is unavailable for this file change.");
453
- }
454
- try {
455
- const result = await (await this.connect()).callTool({
456
- name,
457
- arguments: args
458
- });
459
- if (snapshot) {
460
- const finalized = await finalizeUndoSnapshot(snapshot);
461
- if (finalized) {
462
- logLine(
463
- "info",
464
- `Local Undo ready \xB7 ${dim(snapshot.id)} \xB7 kept on this device only`
465
- );
466
- } else {
467
- logLine("warn", "Local Undo snapshot could not be finalized.");
468
- }
469
- }
470
- return result;
471
- } catch (error) {
472
- await discardUndoSnapshot(snapshot);
473
- throw error;
474
- }
811
+ return this.core.callTool(name, args);
475
812
  }
476
813
  async close() {
477
- if (!this.client) return;
478
- await this.client.close();
479
- this.client = null;
814
+ await this.core.close();
480
815
  }
481
816
  };
482
817
  async function connectAgent(config) {
483
818
  const core = new ExecutionCore(config.mode);
484
819
  banner();
485
- logLine("info", `Device: ${bold(config.deviceName)} \xB7 ${process2.platform}/${process2.arch}`);
820
+ logLine("info", `Device: ${bold(config.deviceName)} \xB7 ${process3.platform}/${process3.arch}`);
486
821
  logLine(
487
822
  "info",
488
823
  `Permission profile: ${isLocalSafeMode(config.mode) ? green("safe local cap") : cyan("dashboard-managed")}`
489
824
  );
490
825
  const tools = await core.tools();
491
826
  logLine("success", `Local tools ready: ${tools.length} exposed`);
492
- process2.stdout.write(" " + dim(tools.map((tool) => tool.name).join(" \xB7 ")) + "\n");
827
+ process3.stdout.write(" " + dim(tools.map((tool) => tool.name).join(" \xB7 ")) + "\n");
493
828
  const wsUrl = new URL("/agent", config.origin.replace(/^http/, "ws"));
494
829
  let stopped = false;
495
830
  let backoff = 1e3;
496
831
  const shutdown = async () => {
497
832
  stopped = true;
498
833
  await core.close().catch(() => void 0);
499
- process2.exit(0);
834
+ process3.exit(0);
500
835
  };
501
- process2.on("SIGINT", shutdown);
502
- process2.on("SIGTERM", shutdown);
836
+ process3.on("SIGINT", shutdown);
837
+ process3.on("SIGTERM", shutdown);
503
838
  while (!stopped) {
504
839
  logLine("event", `Connecting relay ${dim(wsUrl.host)}\u2026`);
505
840
  const ws = new WebSocket(wsUrl, {
@@ -519,8 +854,8 @@ async function connectAgent(config) {
519
854
  device: {
520
855
  id: config.deviceId,
521
856
  name: config.deviceName,
522
- platform: process2.platform,
523
- arch: process2.arch,
857
+ platform: process3.platform,
858
+ arch: process3.arch,
524
859
  hostname: os2.hostname(),
525
860
  agentVersion: VERSION
526
861
  },
@@ -529,8 +864,8 @@ async function connectAgent(config) {
529
864
  );
530
865
  logLine("success", `Relay connected \xB7 ${bold(config.deviceName)} \xB7 ${config.mode} mode`);
531
866
  logLine("success", "Device presence published.");
532
- process2.stdout.write(" " + dim(config.origin) + "\n");
533
- process2.stdout.write(" " + dim("Ctrl+C to disconnect") + "\n\n");
867
+ process3.stdout.write(" " + dim(config.origin) + "\n");
868
+ process3.stdout.write(" " + dim("Ctrl+C to disconnect") + "\n\n");
534
869
  const sendHeartbeat = async () => {
535
870
  try {
536
871
  await fetch(new URL("/api/device/heartbeat", config.origin), {
@@ -541,7 +876,10 @@ async function connectAgent(config) {
541
876
  }
542
877
  };
543
878
  void sendHeartbeat();
544
- const heartbeatTimer = setInterval(() => void sendHeartbeat(), 6e4);
879
+ const heartbeatTimer = setInterval(
880
+ () => void sendHeartbeat(),
881
+ 15 * 6e4
882
+ );
545
883
  await new Promise((resolve) => {
546
884
  ws.on("message", async (raw) => {
547
885
  let message;
@@ -604,7 +942,7 @@ async function connectAgent(config) {
604
942
  }
605
943
  async function main() {
606
944
  if (argFlag("--help") || argFlag("-h")) {
607
- process2.stdout.write(
945
+ process3.stdout.write(
608
946
  [
609
947
  "Remote Arc",
610
948
  "",
@@ -626,14 +964,14 @@ async function main() {
626
964
  return;
627
965
  }
628
966
  if (argFlag("--version") || argFlag("-v")) {
629
- process2.stdout.write(VERSION + "\n");
967
+ process3.stdout.write(VERSION + "\n");
630
968
  return;
631
969
  }
632
970
  if (argFlag("--reset")) {
633
971
  await resetConfig();
634
972
  return;
635
973
  }
636
- const origin = process2.env.REMOTEARC_ORIGIN || process2.env.REMOTE_LINK_ORIGIN || process2.argv.find((value) => value.startsWith("--origin="))?.slice(9) || DEFAULT_ORIGIN;
974
+ const origin = process3.env.REMOTEARC_ORIGIN || process3.env.REMOTE_LINK_ORIGIN || process3.argv.find((value) => value.startsWith("--origin="))?.slice(9) || DEFAULT_ORIGIN;
637
975
  let config = await readConfig();
638
976
  if (config && ["https://remote.samyao.me", "https://remotearc.app"].includes(config.origin)) {
639
977
  config.origin = DEFAULT_ORIGIN;
@@ -656,6 +994,6 @@ main().catch((error) => {
656
994
  "error",
657
995
  "Fatal: " + (error instanceof Error ? error.message : String(error))
658
996
  );
659
- process2.exit(1);
997
+ process3.exit(1);
660
998
  });
661
999
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/local-safety.ts"],"sourcesContent":["#!/usr/bin/env node\nimport os from \"node:os\";\nimport path from \"node:path\";\nimport fs from \"node:fs/promises\";\nimport { spawn } from \"node:child_process\";\nimport process from \"node:process\";\nimport { Client } from \"@modelcontextprotocol/client\";\nimport { StdioClientTransport } from \"@modelcontextprotocol/client/stdio\";\nimport WebSocket from \"ws\";\nimport {\n assertCommandAllowed,\n createUndoSnapshot,\n discardUndoSnapshot,\n finalizeUndoSnapshot,\n undoLastChange,\n} from \"./local-safety.js\";\n\nconst VERSION = \"0.3.6\";\nconst DEFAULT_ORIGIN = \"https://mcp.remotearc.app\";\nconst CONFIG_DIR = path.join(os.homedir(), \".remotearc\");\nconst CONFIG_PATH = path.join(CONFIG_DIR, \"config.json\");\nconst LEGACY_CONFIG_PATH = path.join(os.homedir(), \".remote-link\", \"config.json\");\n\ntype Mode = \"managed\" | \"safe\" | \"developer\";\n\ntype SavedConfig = {\n deviceId: string;\n deviceToken: string;\n deviceName: string;\n origin: string;\n mode: Mode;\n};\n\ntype PairingStart = {\n device_code: string;\n device_secret: string;\n user_code: string;\n verification_uri: string;\n verification_uri_complete: string;\n expires_in: number;\n interval: number;\n};\n\ntype PairingToken = {\n device_id: string;\n device_token: string;\n relay_url: string;\n};\n\nconst SAFE_TOOLS = new Set([\n \"list_directory\",\n \"read_file\",\n \"get_file_info\",\n \"list_processes\",\n]);\n\nconst DEVELOPER_TOOLS = new Set([\n ...SAFE_TOOLS,\n \"start_process\",\n \"write_file\",\n \"edit_block\",\n \"undo_last_change\",\n]);\n\nconst sleep = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms));\n\nconst supportsColor = process.stdout.isTTY && !process.env.NO_COLOR;\nconst paint = (code: string, value: string) =>\n supportsColor ? `\\x1b[${code}m${value}\\x1b[0m` : value;\nconst dim = (value: string) => paint(\"2\", value);\nconst cyan = (value: string) => paint(\"36\", value);\nconst green = (value: string) => paint(\"32\", value);\nconst yellow = (value: string) => paint(\"33\", value);\nconst red = (value: string) => paint(\"31\", value);\nconst bold = (value: string) => paint(\"1\", value);\n\nfunction nowTime() {\n return new Date().toLocaleTimeString([], {\n hour: \"2-digit\",\n minute: \"2-digit\",\n second: \"2-digit\",\n hour12: false,\n });\n}\n\nfunction logLine(\n level: \"info\" | \"success\" | \"warn\" | \"error\" | \"event\",\n message: string,\n) {\n const icon =\n level === \"success\" ? green(\"✓\") :\n level === \"warn\" ? yellow(\"!\") :\n level === \"error\" ? red(\"×\") :\n level === \"event\" ? cyan(\"→\") :\n cyan(\"•\");\n process.stdout.write(`${dim(nowTime())} ${icon} ${message}\\n`);\n}\n\nfunction banner() {\n process.stdout.write(\"\\n\");\n process.stdout.write(bold(\"Remote Arc\") + \" \" + dim(`v${VERSION}`) + \"\\n\");\n process.stdout.write(dim(\"Secure remote MCP bridge\") + \"\\n\\n\");\n}\n\nfunction argFlag(name: string) {\n return process.argv.includes(name);\n}\n\nfunction selectedMode(): Mode {\n if (argFlag(\"--safe\")) return \"safe\";\n return \"managed\";\n}\n\nfunction isLocalSafeMode(mode: Mode) {\n return mode === \"safe\";\n}\n\nfunction modeLabel(mode: Mode) {\n return isLocalSafeMode(mode) ? \"safe local cap\" : \"dashboard-managed\";\n}\n\nasync function readConfig(): Promise<SavedConfig | null> {\n try {\n return JSON.parse(await fs.readFile(CONFIG_PATH, \"utf8\")) as SavedConfig;\n } catch {\n try {\n const legacy = JSON.parse(\n await fs.readFile(LEGACY_CONFIG_PATH, \"utf8\"),\n ) as SavedConfig;\n await writeConfig(legacy);\n logLine(\"success\", \"Migrated existing Remote Link pairing to Remote Arc.\");\n return legacy;\n } catch {\n return null;\n }\n }\n}\n\nasync function writeConfig(config: SavedConfig) {\n await fs.mkdir(CONFIG_DIR, { recursive: true });\n await fs.writeFile(CONFIG_PATH, JSON.stringify(config, null, 2) + \"\\n\", {\n mode: 0o600,\n });\n}\n\nasync function resetConfig() {\n await Promise.all([\n fs.rm(CONFIG_PATH, { force: true }),\n fs.rm(LEGACY_CONFIG_PATH, { force: true }),\n ]);\n logLine(\"success\", \"Removed saved device credentials.\");\n}\n\nfunction openBrowser(url: string) {\n const command =\n process.platform === \"win32\"\n ? \"cmd\"\n : process.platform === \"darwin\"\n ? \"open\"\n : \"xdg-open\";\n const args =\n process.platform === \"win32\"\n ? [\"/c\", \"start\", \"\", url]\n : [url];\n\n const child = spawn(command, args, {\n detached: true,\n stdio: \"ignore\",\n });\n child.unref();\n}\n\nasync function pair(origin: string, mode: Mode): Promise<SavedConfig> {\n const deviceName = os.hostname();\n const response = await fetch(origin + \"/api/device/start\", {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\" },\n body: JSON.stringify({\n device_name: deviceName,\n platform: process.platform,\n arch: process.arch,\n hostname: os.hostname(),\n }),\n });\n\n if (!response.ok) {\n throw new Error(\"Could not start device pairing: \" + response.status);\n }\n\n const pairing = (await response.json()) as PairingStart;\n\n banner();\n logLine(\"info\", `Device: ${bold(deviceName)} · ${process.platform}/${process.arch} · ${modeLabel(mode)}`);\n logLine(\"event\", \"Pairing required — opening secure browser approval.\");\n process.stdout.write(\"\\n Pairing code \" + bold(cyan(pairing.user_code)) + \"\\n\");\n process.stdout.write(\" \" + dim(pairing.verification_uri_complete) + \"\\n\\n\");\n openBrowser(pairing.verification_uri_complete);\n logLine(\"info\", \"Waiting for authorization…\");\n\n const startedAt = Date.now();\n while (Date.now() - startedAt < pairing.expires_in * 1000) {\n await sleep(Math.max(pairing.interval, 2) * 1000);\n\n const tokenResponse = await fetch(origin + \"/api/device/token\", {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\" },\n body: JSON.stringify({\n device_code: pairing.device_code,\n device_secret: pairing.device_secret,\n }),\n });\n\n if (tokenResponse.status === 428) {\n if (process.stdout.isTTY) process.stdout.write(dim(\"·\"));\n continue;\n }\n\n if (!tokenResponse.ok) {\n const body = await tokenResponse.text();\n throw new Error(\"Pairing failed: \" + body);\n }\n\n const result = (await tokenResponse.json()) as PairingToken;\n process.stdout.write(\"\\n\");\n logLine(\"success\", \"Device authorized.\");\n\n const config: SavedConfig = {\n deviceId: result.device_id,\n deviceToken: result.device_token,\n deviceName,\n origin,\n mode,\n };\n await writeConfig(config);\n return config;\n }\n\n throw new Error(\"Pairing expired. Run Remote Arc again to retry.\");\n}\n\nclass ExecutionCore {\n private client: Client | null = null;\n\n constructor(private readonly mode: Mode) {}\n\n async connect() {\n if (this.client) return this.client;\n\n const client = new Client({\n name: \"remotearc-cli-core\",\n version: VERSION,\n });\n\n const command = process.platform === \"win32\" ? \"npx.cmd\" : \"npx\";\n const transport = new StdioClientTransport({\n command,\n args: [\"-y\", \"@wonderwhy-er/desktop-commander@latest\"],\n stderr: \"inherit\",\n });\n\n logLine(\"info\", \"Starting local execution core…\");\n await client.connect(transport);\n this.client = client;\n logLine(\"success\", \"Local execution core ready.\");\n return client;\n }\n\n async tools() {\n const list = await (await this.connect()).listTools();\n const locallyAvailable = isLocalSafeMode(this.mode) ? SAFE_TOOLS : DEVELOPER_TOOLS;\n const tools = list.tools.filter((tool) => locallyAvailable.has(tool.name));\n\n if (!isLocalSafeMode(this.mode)) {\n tools.push({\n name: \"undo_last_change\",\n description:\n \"Undo the most recent reversible file change made through Remote Arc on this device. Snapshots stay on the device and expire automatically.\",\n inputSchema: {\n type: \"object\",\n properties: {},\n additionalProperties: false,\n },\n });\n }\n\n return tools;\n }\n\n async call(name: string, args: Record<string, unknown>) {\n const locallyAvailable = isLocalSafeMode(this.mode) ? SAFE_TOOLS : DEVELOPER_TOOLS;\n if (!locallyAvailable.has(name)) {\n throw new Error(\"Tool blocked by local safety cap: \" + name);\n }\n\n if (name === \"undo_last_change\") {\n const result = await undoLastChange();\n logLine(\"success\", \"Local Undo restored the latest reversible file change.\");\n return {\n content: [{ type: \"text\" as const, text: JSON.stringify(result, null, 2) }],\n };\n }\n\n if (name === \"start_process\") {\n assertCommandAllowed(String(args.command || \"\"));\n }\n\n const reversibleTool =\n name === \"write_file\" || name === \"edit_block\"\n ? (name as \"write_file\" | \"edit_block\")\n : null;\n const snapshot = reversibleTool\n ? await createUndoSnapshot(reversibleTool, args)\n : null;\n\n if (reversibleTool && !snapshot) {\n logLine(\"warn\", \"Local Undo is unavailable for this file change.\");\n }\n\n try {\n const result = await (await this.connect()).callTool({\n name,\n arguments: args,\n });\n if (snapshot) {\n const finalized = await finalizeUndoSnapshot(snapshot);\n if (finalized) {\n logLine(\n \"info\",\n `Local Undo ready · ${dim(snapshot.id)} · kept on this device only`,\n );\n } else {\n logLine(\"warn\", \"Local Undo snapshot could not be finalized.\");\n }\n }\n return result;\n } catch (error) {\n await discardUndoSnapshot(snapshot);\n throw error;\n }\n }\n\n async close() {\n if (!this.client) return;\n await this.client.close();\n this.client = null;\n }\n}\n\nasync function connectAgent(config: SavedConfig) {\n const core = new ExecutionCore(config.mode);\n banner();\n logLine(\"info\", `Device: ${bold(config.deviceName)} · ${process.platform}/${process.arch}`);\n logLine(\n \"info\",\n `Permission profile: ${isLocalSafeMode(config.mode) ? green(\"safe local cap\") : cyan(\"dashboard-managed\")}`,\n );\n\n const tools = await core.tools();\n logLine(\"success\", `Local tools ready: ${tools.length} exposed`);\n process.stdout.write(\" \" + dim(tools.map((tool) => tool.name).join(\" · \")) + \"\\n\");\n const wsUrl = new URL(\"/agent\", config.origin.replace(/^http/, \"ws\"));\n\n let stopped = false;\n let backoff = 1000;\n\n const shutdown = async () => {\n stopped = true;\n await core.close().catch(() => undefined);\n process.exit(0);\n };\n process.on(\"SIGINT\", shutdown);\n process.on(\"SIGTERM\", shutdown);\n\n while (!stopped) {\n logLine(\"event\", `Connecting relay ${dim(wsUrl.host)}…`);\n const ws = new WebSocket(wsUrl, {\n headers: {\n Authorization: \"Bearer \" + config.deviceToken,\n },\n });\n\n try {\n await new Promise<void>((resolve, reject) => {\n ws.once(\"open\", resolve);\n ws.once(\"error\", reject);\n });\n\n backoff = 1000;\n ws.send(\n JSON.stringify({\n type: \"hello\",\n device: {\n id: config.deviceId,\n name: config.deviceName,\n platform: process.platform,\n arch: process.arch,\n hostname: os.hostname(),\n agentVersion: VERSION,\n },\n tools: tools.map((tool) => tool.name),\n }),\n );\n\n logLine(\"success\", `Relay connected · ${bold(config.deviceName)} · ${config.mode} mode`);\n logLine(\"success\", \"Device presence published.\");\n process.stdout.write(\" \" + dim(config.origin) + \"\\n\");\n process.stdout.write(\" \" + dim(\"Ctrl+C to disconnect\") + \"\\n\\n\");\n\n const sendHeartbeat = async () => {\n try {\n await fetch(new URL(\"/api/device/heartbeat\", config.origin), {\n method: \"POST\",\n headers: { Authorization: \"Bearer \" + config.deviceToken },\n });\n } catch {\n // WebSocket reconnect logic remains the source of truth for connectivity.\n }\n };\n void sendHeartbeat();\n const heartbeatTimer = setInterval(() => void sendHeartbeat(), 60_000);\n\n await new Promise<void>((resolve) => {\n ws.on(\"message\", async (raw) => {\n let message: {\n type?: string;\n id?: string;\n tool?: string;\n arguments?: Record<string, unknown>;\n };\n\n try {\n message = JSON.parse(raw.toString());\n } catch {\n return;\n }\n\n if (\n message.type !== \"call\" ||\n !message.id ||\n !message.tool\n ) {\n return;\n }\n\n const callStarted = Date.now();\n logLine(\"event\", `tool.call ${bold(message.tool)} · ${dim(message.id.slice(0, 8))}`);\n try {\n const result = await core.call(\n message.tool,\n message.arguments || {},\n );\n logLine(\"success\", `tool.done ${message.tool} · ${Date.now() - callStarted}ms`);\n ws.send(\n JSON.stringify({\n type: \"result\",\n id: message.id,\n result,\n }),\n );\n } catch (error) {\n logLine(\"error\", `tool.fail ${message.tool} · ${error instanceof Error ? error.message : String(error)}`);\n ws.send(\n JSON.stringify({\n type: \"result\",\n id: message.id,\n error: error instanceof Error ? error.message : String(error),\n }),\n );\n }\n });\n\n ws.once(\"close\", resolve);\n ws.once(\"error\", resolve);\n });\n clearInterval(heartbeatTimer);\n } catch (error) {\n logLine(\n \"error\",\n \"Relay connection failed: \" +\n (error instanceof Error ? error.message : String(error)),\n );\n } finally {\n ws.removeAllListeners();\n ws.close();\n }\n\n if (!stopped) {\n logLine(\n \"warn\",\n \"Relay disconnected · retrying in \" + Math.round(backoff / 1000) + \"s\",\n );\n await sleep(backoff);\n backoff = Math.min(backoff * 2, 30_000);\n }\n }\n}\n\nasync function main() {\n if (argFlag(\"--help\") || argFlag(\"-h\")) {\n process.stdout.write(\n [\n \"Remote Arc\",\n \"\",\n \"Usage:\",\n \" npx remotelink\",\n \"\",\n \"After the npm release:\",\n \" npx remotelink\",\n \"\",\n \"Options:\",\n \" --safe Hard local read-only cap; dashboard cannot enable write tools\",\n \" --developer Legacy alias for dashboard-managed capabilities\",\n \" --reset Remove this computer's saved pairing\",\n \" --version Print CLI version\",\n \" --help Show this help\",\n \"\",\n ].join(\"\\n\"),\n );\n return;\n }\n\n if (argFlag(\"--version\") || argFlag(\"-v\")) {\n process.stdout.write(VERSION + \"\\n\");\n return;\n }\n\n if (argFlag(\"--reset\")) {\n await resetConfig();\n return;\n }\n\n const origin =\n process.env.REMOTEARC_ORIGIN || process.env.REMOTE_LINK_ORIGIN ||\n process.argv.find((value) => value.startsWith(\"--origin=\"))?.slice(9) ||\n DEFAULT_ORIGIN;\n\n let config = await readConfig();\n if (config && [\"https://remote.samyao.me\", \"https://remotearc.app\"].includes(config.origin)) {\n config.origin = DEFAULT_ORIGIN;\n await writeConfig(config);\n logLine(\"info\", \"Migrated relay origin to \" + DEFAULT_ORIGIN);\n }\n if (!config) {\n config = await pair(origin, selectedMode());\n } else if (argFlag(\"--safe\") || argFlag(\"--developer\")) {\n config.mode = argFlag(\"--safe\") ? \"safe\" : \"managed\";\n await writeConfig(config);\n }\n\n if (config) {\n logLine(\"info\", `Using paired device identity ${dim(config.deviceId.slice(0, 8))}…`);\n }\n await connectAgent(config);\n}\n\nmain().catch((error) => {\n logLine(\n \"error\",\n \"Fatal: \" + (error instanceof Error ? error.message : String(error)),\n );\n process.exit(1);\n});\n","import crypto from \"node:crypto\";\nimport { createReadStream } from \"node:fs\";\nimport fs from \"node:fs/promises\";\nimport os from \"node:os\";\nimport path from \"node:path\";\n\nconst UNDO_ROOT = path.join(os.homedir(), \".remotearc\", \"undo\");\nconst RETENTION_MS = 7 * 24 * 60 * 60 * 1000;\nconst MAX_SNAPSHOT_BYTES = 20 * 1024 * 1024;\nconst MAX_UNDO_BYTES = 200 * 1024 * 1024;\n\ntype UndoManifest = {\n id: string;\n createdAt: string;\n tool: \"write_file\" | \"edit_block\";\n targetPath: string;\n existed: boolean;\n mode?: number;\n bytes: number;\n postChangeHash?: string;\n};\n\nexport type UndoSnapshot = {\n id: string;\n directory: string;\n manifest: UndoManifest;\n};\n\nasync function ensureUndoRoot() {\n await fs.mkdir(UNDO_ROOT, { recursive: true, mode: 0o700 });\n}\n\nasync function readManifest(directory: string): Promise<UndoManifest | null> {\n try {\n return JSON.parse(\n await fs.readFile(path.join(directory, \"manifest.json\"), \"utf8\"),\n ) as UndoManifest;\n } catch {\n return null;\n }\n}\n\nasync function snapshotDirectories() {\n await ensureUndoRoot();\n const entries = await fs.readdir(UNDO_ROOT, { withFileTypes: true });\n return entries\n .filter((entry) => entry.isDirectory())\n .map((entry) => path.join(UNDO_ROOT, entry.name));\n}\n\nasync function cleanupUndoStore() {\n const now = Date.now();\n const snapshots: Array<{ directory: string; manifest: UndoManifest }> = [];\n\n for (const directory of await snapshotDirectories()) {\n const manifest = await readManifest(directory);\n if (!manifest) {\n await fs.rm(directory, { recursive: true, force: true }).catch(() => undefined);\n continue;\n }\n\n const created = Date.parse(manifest.createdAt);\n if (!Number.isFinite(created) || now - created > RETENTION_MS) {\n await fs.rm(directory, { recursive: true, force: true }).catch(() => undefined);\n continue;\n }\n\n snapshots.push({ directory, manifest });\n }\n\n snapshots.sort(\n (a, b) => Date.parse(a.manifest.createdAt) - Date.parse(b.manifest.createdAt),\n );\n\n let total = snapshots.reduce((sum, item) => sum + item.manifest.bytes, 0);\n for (const item of snapshots) {\n if (total <= MAX_UNDO_BYTES) break;\n await fs.rm(item.directory, { recursive: true, force: true }).catch(() => undefined);\n total -= item.manifest.bytes;\n }\n}\n\nfunction mutationPath(\n tool: \"write_file\" | \"edit_block\",\n args: Record<string, unknown>,\n) {\n const candidate = tool === \"write_file\" ? args.path : args.file_path;\n return typeof candidate === \"string\" && candidate.trim() ? candidate : null;\n}\n\nexport async function createUndoSnapshot(\n tool: \"write_file\" | \"edit_block\",\n args: Record<string, unknown>,\n): Promise<UndoSnapshot | null> {\n const targetPath = mutationPath(tool, args);\n if (!targetPath) return null;\n\n await cleanupUndoStore();\n\n let existed = false;\n let mode: number | undefined;\n let bytes = 0;\n let original: Buffer | null = null;\n\n try {\n const stat = await fs.stat(targetPath);\n if (!stat.isFile()) return null;\n existed = true;\n mode = stat.mode;\n bytes = stat.size;\n if (bytes > MAX_SNAPSHOT_BYTES) return null;\n original = await fs.readFile(targetPath);\n } catch (error) {\n const code =\n error && typeof error === \"object\" && \"code\" in error\n ? String((error as { code?: unknown }).code)\n : \"\";\n if (code !== \"ENOENT\") throw error;\n }\n\n const id = `${Date.now()}-${crypto.randomUUID().slice(0, 8)}`;\n const directory = path.join(UNDO_ROOT, id);\n await fs.mkdir(directory, { recursive: true, mode: 0o700 });\n\n if (original) {\n await fs.writeFile(path.join(directory, \"content.bin\"), original, { mode: 0o600 });\n }\n\n const manifest: UndoManifest = {\n id,\n createdAt: new Date().toISOString(),\n tool,\n targetPath,\n existed,\n ...(mode !== undefined ? { mode } : {}),\n bytes,\n };\n\n await fs.writeFile(\n path.join(directory, \"manifest.json\"),\n JSON.stringify(manifest, null, 2) + \"\\n\",\n { mode: 0o600 },\n );\n\n await cleanupUndoStore();\n return { id, directory, manifest };\n}\n\nasync function hashFile(filePath: string) {\n const hash = crypto.createHash(\"sha256\");\n for await (const chunk of createReadStream(filePath)) {\n hash.update(chunk);\n }\n return hash.digest(\"hex\");\n}\n\nexport async function finalizeUndoSnapshot(snapshot: UndoSnapshot | null) {\n if (!snapshot) return false;\n try {\n const postChangeHash = await hashFile(snapshot.manifest.targetPath);\n snapshot.manifest.postChangeHash = postChangeHash;\n await fs.writeFile(\n path.join(snapshot.directory, \"manifest.json\"),\n JSON.stringify(snapshot.manifest, null, 2) + \"\\n\",\n { mode: 0o600 },\n );\n return true;\n } catch {\n await discardUndoSnapshot(snapshot);\n return false;\n }\n}\n\nexport async function discardUndoSnapshot(snapshot: UndoSnapshot | null) {\n if (!snapshot) return;\n await fs.rm(snapshot.directory, { recursive: true, force: true }).catch(() => undefined);\n}\n\nexport async function undoLastChange() {\n const candidates: Array<{ directory: string; manifest: UndoManifest }> = [];\n for (const directory of await snapshotDirectories()) {\n const manifest = await readManifest(directory);\n if (manifest) candidates.push({ directory, manifest });\n }\n\n candidates.sort(\n (a, b) => Date.parse(b.manifest.createdAt) - Date.parse(a.manifest.createdAt),\n );\n const latest = candidates[0];\n if (!latest) {\n throw new Error(\"No reversible Remote Arc file change is available on this device.\");\n }\n\n if (!latest.manifest.postChangeHash) {\n throw new Error(\n \"This snapshot predates conflict-safe Local Undo and cannot be restored automatically.\",\n );\n }\n\n let currentHash: string;\n try {\n currentHash = await hashFile(latest.manifest.targetPath);\n } catch {\n throw new Error(\n \"The target file changed or disappeared after the Remote Arc edit. Automatic undo was refused to avoid overwriting newer work.\",\n );\n }\n\n if (currentHash !== latest.manifest.postChangeHash) {\n throw new Error(\n \"The target file changed again after the Remote Arc edit. Automatic undo was refused to avoid overwriting newer work.\",\n );\n }\n\n if (latest.manifest.existed) {\n const original = await fs.readFile(path.join(latest.directory, \"content.bin\"));\n await fs.mkdir(path.dirname(latest.manifest.targetPath), { recursive: true });\n await fs.writeFile(latest.manifest.targetPath, original);\n if (latest.manifest.mode !== undefined) {\n await fs.chmod(latest.manifest.targetPath, latest.manifest.mode).catch(() => undefined);\n }\n } else {\n await fs.rm(latest.manifest.targetPath, { force: true });\n }\n\n await fs.rm(latest.directory, { recursive: true, force: true });\n\n return {\n restored: true,\n action_id: latest.manifest.id,\n tool: latest.manifest.tool,\n path: latest.manifest.targetPath,\n snapshot_location: \"local-device-only\",\n };\n}\n\ntype GuardRule = {\n pattern: RegExp;\n reason: string;\n};\n\nconst DESTRUCTIVE_COMMAND_RULES: GuardRule[] = [\n {\n pattern: /(?:^|[;&|]\\s*)(?:sudo\\s+)?rm\\s+[^\\n]*(?:-rf|-fr|-[a-z]*r[a-z]*f)[^\\n]*(?:\\s\\/\\s*$|\\s\\/\\*|\\s~(?:\\s|$)|\\s\\$HOME(?:\\s|$))/i,\n reason: \"recursive deletion of a root or home path\",\n },\n {\n pattern: /\\b(?:mkfs(?:\\.\\w+)?|wipefs|fdisk|parted)\\b/i,\n reason: \"disk or filesystem destructive operation\",\n },\n {\n pattern: /\\bdd\\b[^\\n]*\\bof=\\/dev\\/(?:sd|nvme|vd|xvd|mmcblk)/i,\n reason: \"raw disk overwrite\",\n },\n {\n pattern: /\\bdiskutil\\s+erase(?:disk|volume)\\b/i,\n reason: \"disk erase\",\n },\n {\n pattern: /\\b(?:format(?:\\.com)?\\s+[a-z]:|diskpart\\b|clear-disk\\b|initialize-disk\\b)/i,\n reason: \"Windows disk destructive operation\",\n },\n {\n pattern: /\\b(?:shutdown|reboot|halt|poweroff)\\b/i,\n reason: \"system shutdown or reboot\",\n },\n {\n pattern: /\\bremove-item\\b[^\\n]*(?:-recurse[^\\n]*-force|-force[^\\n]*-recurse)[^\\n]*(?:[a-z]:\\\\(?:\\*|\\s|$)|\\$env:systemdrive)/i,\n reason: \"recursive forced deletion of a drive root\",\n },\n {\n pattern: /\\b(?:del|erase|rd|rmdir)\\b[^\\n]*\\/s[^\\n]*\\/q[^\\n]*[a-z]:\\\\/i,\n reason: \"recursive Windows drive deletion\",\n },\n {\n pattern: /:\\(\\)\\s*\\{\\s*:\\|:&\\s*\\};\\s*:/,\n reason: \"fork bomb\",\n },\n];\n\nexport function assertCommandAllowed(command: string) {\n if (process.env.REMOTEARC_ALLOW_DESTRUCTIVE === \"1\") return;\n\n for (const rule of DESTRUCTIVE_COMMAND_RULES) {\n if (rule.pattern.test(command)) {\n throw new Error(\n \"Blocked by Remote Arc Safety Guard: \" +\n rule.reason +\n \". Run this action manually on the device if you intentionally need it.\",\n );\n }\n }\n}\n"],"mappings":"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","names":["os","path","fs","process","path","os","process","fs"]}
1
+ {"version":3,"sources":["../src/index.ts","../../execution-core/src/filesystem.ts","../../execution-core/src/process.ts","../../execution-core/src/safety.ts","../../execution-core/src/core.ts"],"sourcesContent":["#!/usr/bin/env node\nimport os from \"node:os\";\nimport path from \"node:path\";\nimport fs from \"node:fs/promises\";\nimport { spawn } from \"node:child_process\";\nimport process from \"node:process\";\nimport WebSocket from \"ws\";\nimport { RemoteArcExecutionCore } from \"@remotearc/execution-core\";\n\nconst VERSION = \"0.3.8\";\nconst DEFAULT_ORIGIN = \"https://mcp.remotearc.app\";\nconst CONFIG_DIR = path.join(os.homedir(), \".remotearc\");\nconst CONFIG_PATH = path.join(CONFIG_DIR, \"config.json\");\nconst LEGACY_CONFIG_PATH = path.join(os.homedir(), \".remote-link\", \"config.json\");\n\ntype Mode = \"managed\" | \"safe\" | \"developer\";\n\ntype SavedConfig = {\n deviceId: string;\n deviceToken: string;\n deviceName: string;\n origin: string;\n mode: Mode;\n};\n\ntype PairingStart = {\n device_code: string;\n device_secret: string;\n user_code: string;\n verification_uri: string;\n verification_uri_complete: string;\n expires_in: number;\n interval: number;\n};\n\ntype PairingToken = {\n device_id: string;\n device_token: string;\n relay_url: string;\n};\n\nconst sleep = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms));\n\nconst supportsColor = process.stdout.isTTY && !process.env.NO_COLOR;\nconst paint = (code: string, value: string) =>\n supportsColor ? `\\x1b[${code}m${value}\\x1b[0m` : value;\nconst dim = (value: string) => paint(\"2\", value);\nconst cyan = (value: string) => paint(\"36\", value);\nconst green = (value: string) => paint(\"32\", value);\nconst yellow = (value: string) => paint(\"33\", value);\nconst red = (value: string) => paint(\"31\", value);\nconst bold = (value: string) => paint(\"1\", value);\n\nfunction nowTime() {\n return new Date().toLocaleTimeString([], {\n hour: \"2-digit\",\n minute: \"2-digit\",\n second: \"2-digit\",\n hour12: false,\n });\n}\n\nfunction logLine(\n level: \"info\" | \"success\" | \"warn\" | \"error\" | \"event\",\n message: string,\n) {\n const icon =\n level === \"success\" ? green(\"✓\") :\n level === \"warn\" ? yellow(\"!\") :\n level === \"error\" ? red(\"×\") :\n level === \"event\" ? cyan(\"→\") :\n cyan(\"•\");\n process.stdout.write(`${dim(nowTime())} ${icon} ${message}\\n`);\n}\n\nfunction banner() {\n process.stdout.write(\"\\n\");\n process.stdout.write(bold(\"Remote Arc\") + \" \" + dim(`v${VERSION}`) + \"\\n\");\n process.stdout.write(dim(\"Secure remote MCP bridge\") + \"\\n\\n\");\n}\n\nfunction argFlag(name: string) {\n return process.argv.includes(name);\n}\n\nfunction selectedMode(): Mode {\n if (argFlag(\"--safe\")) return \"safe\";\n return \"managed\";\n}\n\nfunction isLocalSafeMode(mode: Mode) {\n return mode === \"safe\";\n}\n\nfunction modeLabel(mode: Mode) {\n return isLocalSafeMode(mode) ? \"safe local cap\" : \"dashboard-managed\";\n}\n\nasync function readConfig(): Promise<SavedConfig | null> {\n try {\n return JSON.parse(await fs.readFile(CONFIG_PATH, \"utf8\")) as SavedConfig;\n } catch {\n try {\n const legacy = JSON.parse(\n await fs.readFile(LEGACY_CONFIG_PATH, \"utf8\"),\n ) as SavedConfig;\n await writeConfig(legacy);\n logLine(\"success\", \"Migrated existing Remote Link pairing to Remote Arc.\");\n return legacy;\n } catch {\n return null;\n }\n }\n}\n\nasync function writeConfig(config: SavedConfig) {\n await fs.mkdir(CONFIG_DIR, { recursive: true });\n await fs.writeFile(CONFIG_PATH, JSON.stringify(config, null, 2) + \"\\n\", {\n mode: 0o600,\n });\n}\n\nasync function resetConfig() {\n await Promise.all([\n fs.rm(CONFIG_PATH, { force: true }),\n fs.rm(LEGACY_CONFIG_PATH, { force: true }),\n ]);\n logLine(\"success\", \"Removed saved device credentials.\");\n}\n\nfunction openBrowser(url: string) {\n const command =\n process.platform === \"win32\"\n ? \"cmd\"\n : process.platform === \"darwin\"\n ? \"open\"\n : \"xdg-open\";\n const args =\n process.platform === \"win32\"\n ? [\"/c\", \"start\", \"\", url]\n : [url];\n\n const child = spawn(command, args, {\n detached: true,\n stdio: \"ignore\",\n });\n child.unref();\n}\n\nasync function pair(origin: string, mode: Mode): Promise<SavedConfig> {\n const deviceName = os.hostname();\n const response = await fetch(origin + \"/api/device/start\", {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\" },\n body: JSON.stringify({\n device_name: deviceName,\n platform: process.platform,\n arch: process.arch,\n hostname: os.hostname(),\n }),\n });\n\n if (!response.ok) {\n throw new Error(\"Could not start device pairing: \" + response.status);\n }\n\n const pairing = (await response.json()) as PairingStart;\n\n banner();\n logLine(\"info\", `Device: ${bold(deviceName)} · ${process.platform}/${process.arch} · ${modeLabel(mode)}`);\n logLine(\"event\", \"Pairing required — opening secure browser approval.\");\n process.stdout.write(\"\\n Pairing code \" + bold(cyan(pairing.user_code)) + \"\\n\");\n process.stdout.write(\" \" + dim(pairing.verification_uri_complete) + \"\\n\\n\");\n openBrowser(pairing.verification_uri_complete);\n logLine(\"info\", \"Waiting for authorization…\");\n\n const startedAt = Date.now();\n while (Date.now() - startedAt < pairing.expires_in * 1000) {\n await sleep(Math.max(pairing.interval, 2) * 1000);\n\n const tokenResponse = await fetch(origin + \"/api/device/token\", {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\" },\n body: JSON.stringify({\n device_code: pairing.device_code,\n device_secret: pairing.device_secret,\n }),\n });\n\n if (tokenResponse.status === 428) {\n if (process.stdout.isTTY) process.stdout.write(dim(\"·\"));\n continue;\n }\n\n if (!tokenResponse.ok) {\n const body = await tokenResponse.text();\n throw new Error(\"Pairing failed: \" + body);\n }\n\n const result = (await tokenResponse.json()) as PairingToken;\n process.stdout.write(\"\\n\");\n logLine(\"success\", \"Device authorized.\");\n\n const config: SavedConfig = {\n deviceId: result.device_id,\n deviceToken: result.device_token,\n deviceName,\n origin,\n mode,\n };\n await writeConfig(config);\n return config;\n }\n\n throw new Error(\"Pairing expired. Run Remote Arc again to retry.\");\n}\n\nclass ExecutionCore {\n private readonly core: RemoteArcExecutionCore;\n\n constructor(mode: Mode) {\n this.core = new RemoteArcExecutionCore(\n isLocalSafeMode(mode) ? \"safe\" : \"managed\",\n );\n }\n\n async tools() {\n return this.core.listTools();\n }\n\n async call(name: string, args: Record<string, unknown>) {\n return this.core.callTool(name, args);\n }\n\n async close() {\n await this.core.close();\n }\n}\n\nasync function connectAgent(config: SavedConfig) {\n const core = new ExecutionCore(config.mode);\n banner();\n logLine(\"info\", `Device: ${bold(config.deviceName)} · ${process.platform}/${process.arch}`);\n logLine(\n \"info\",\n `Permission profile: ${isLocalSafeMode(config.mode) ? green(\"safe local cap\") : cyan(\"dashboard-managed\")}`,\n );\n\n const tools = await core.tools();\n logLine(\"success\", `Local tools ready: ${tools.length} exposed`);\n process.stdout.write(\" \" + dim(tools.map((tool) => tool.name).join(\" · \")) + \"\\n\");\n const wsUrl = new URL(\"/agent\", config.origin.replace(/^http/, \"ws\"));\n\n let stopped = false;\n let backoff = 1000;\n\n const shutdown = async () => {\n stopped = true;\n await core.close().catch(() => undefined);\n process.exit(0);\n };\n process.on(\"SIGINT\", shutdown);\n process.on(\"SIGTERM\", shutdown);\n\n while (!stopped) {\n logLine(\"event\", `Connecting relay ${dim(wsUrl.host)}…`);\n const ws = new WebSocket(wsUrl, {\n headers: {\n Authorization: \"Bearer \" + config.deviceToken,\n },\n });\n\n try {\n await new Promise<void>((resolve, reject) => {\n ws.once(\"open\", resolve);\n ws.once(\"error\", reject);\n });\n\n backoff = 1000;\n ws.send(\n JSON.stringify({\n type: \"hello\",\n device: {\n id: config.deviceId,\n name: config.deviceName,\n platform: process.platform,\n arch: process.arch,\n hostname: os.hostname(),\n agentVersion: VERSION,\n },\n tools: tools.map((tool) => tool.name),\n }),\n );\n\n logLine(\"success\", `Relay connected · ${bold(config.deviceName)} · ${config.mode} mode`);\n logLine(\"success\", \"Device presence published.\");\n process.stdout.write(\" \" + dim(config.origin) + \"\\n\");\n process.stdout.write(\" \" + dim(\"Ctrl+C to disconnect\") + \"\\n\\n\");\n\n const sendHeartbeat = async () => {\n try {\n await fetch(new URL(\"/api/device/heartbeat\", config.origin), {\n method: \"POST\",\n headers: { Authorization: \"Bearer \" + config.deviceToken },\n });\n } catch {\n // WebSocket reconnect logic remains the source of truth for connectivity.\n }\n };\n void sendHeartbeat();\n const heartbeatTimer = setInterval(\n () => void sendHeartbeat(),\n 15 * 60_000,\n );\n\n await new Promise<void>((resolve) => {\n ws.on(\"message\", async (raw) => {\n let message: {\n type?: string;\n id?: string;\n tool?: string;\n arguments?: Record<string, unknown>;\n };\n\n try {\n message = JSON.parse(raw.toString());\n } catch {\n return;\n }\n\n if (\n message.type !== \"call\" ||\n !message.id ||\n !message.tool\n ) {\n return;\n }\n\n const callStarted = Date.now();\n logLine(\"event\", `tool.call ${bold(message.tool)} · ${dim(message.id.slice(0, 8))}`);\n try {\n const result = await core.call(\n message.tool,\n message.arguments || {},\n );\n logLine(\"success\", `tool.done ${message.tool} · ${Date.now() - callStarted}ms`);\n ws.send(\n JSON.stringify({\n type: \"result\",\n id: message.id,\n result,\n }),\n );\n } catch (error) {\n logLine(\"error\", `tool.fail ${message.tool} · ${error instanceof Error ? error.message : String(error)}`);\n ws.send(\n JSON.stringify({\n type: \"result\",\n id: message.id,\n error: error instanceof Error ? error.message : String(error),\n }),\n );\n }\n });\n\n ws.once(\"close\", resolve);\n ws.once(\"error\", resolve);\n });\n clearInterval(heartbeatTimer);\n } catch (error) {\n logLine(\n \"error\",\n \"Relay connection failed: \" +\n (error instanceof Error ? error.message : String(error)),\n );\n } finally {\n ws.removeAllListeners();\n ws.close();\n }\n\n if (!stopped) {\n logLine(\n \"warn\",\n \"Relay disconnected · retrying in \" + Math.round(backoff / 1000) + \"s\",\n );\n await sleep(backoff);\n backoff = Math.min(backoff * 2, 30_000);\n }\n }\n}\n\nasync function main() {\n if (argFlag(\"--help\") || argFlag(\"-h\")) {\n process.stdout.write(\n [\n \"Remote Arc\",\n \"\",\n \"Usage:\",\n \" npx remotelink\",\n \"\",\n \"After the npm release:\",\n \" npx remotelink\",\n \"\",\n \"Options:\",\n \" --safe Hard local read-only cap; dashboard cannot enable write tools\",\n \" --developer Legacy alias for dashboard-managed capabilities\",\n \" --reset Remove this computer's saved pairing\",\n \" --version Print CLI version\",\n \" --help Show this help\",\n \"\",\n ].join(\"\\n\"),\n );\n return;\n }\n\n if (argFlag(\"--version\") || argFlag(\"-v\")) {\n process.stdout.write(VERSION + \"\\n\");\n return;\n }\n\n if (argFlag(\"--reset\")) {\n await resetConfig();\n return;\n }\n\n const origin =\n process.env.REMOTEARC_ORIGIN || process.env.REMOTE_LINK_ORIGIN ||\n process.argv.find((value) => value.startsWith(\"--origin=\"))?.slice(9) ||\n DEFAULT_ORIGIN;\n\n let config = await readConfig();\n if (config && [\"https://remote.samyao.me\", \"https://remotearc.app\"].includes(config.origin)) {\n config.origin = DEFAULT_ORIGIN;\n await writeConfig(config);\n logLine(\"info\", \"Migrated relay origin to \" + DEFAULT_ORIGIN);\n }\n if (!config) {\n config = await pair(origin, selectedMode());\n } else if (argFlag(\"--safe\") || argFlag(\"--developer\")) {\n config.mode = argFlag(\"--safe\") ? \"safe\" : \"managed\";\n await writeConfig(config);\n }\n\n if (config) {\n logLine(\"info\", `Using paired device identity ${dim(config.deviceId.slice(0, 8))}…`);\n }\n await connectAgent(config);\n}\n\nmain().catch((error) => {\n logLine(\n \"error\",\n \"Fatal: \" + (error instanceof Error ? error.message : String(error)),\n );\n process.exit(1);\n});\n","import fs from \"node:fs/promises\";\nimport path from \"node:path\";\n\nconst MAX_DIRECTORY_ENTRIES = 2000;\nconst DEFAULT_READ_LINES = 240;\nconst MAX_TEXT_FILE_BYTES = 20 * 1024 * 1024;\n\nconst printableSize = (bytes: number) => {\n if (bytes < 1024) return `${bytes} B`;\n if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;\n return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;\n};\n\nexport async function listDirectory(targetPath: string, depth = 2) {\n const maxDepth = Math.max(1, Math.min(10, Math.trunc(depth || 2)));\n const lines: string[] = [];\n let entriesSeen = 0;\n\n async function walk(directory: string, level: number, prefix: string) {\n if (entriesSeen >= MAX_DIRECTORY_ENTRIES) return;\n const entries = await fs.readdir(directory, { withFileTypes: true });\n entries.sort((a, b) => {\n if (a.isDirectory() !== b.isDirectory()) return a.isDirectory() ? -1 : 1;\n return a.name.localeCompare(b.name);\n });\n\n for (const entry of entries) {\n if (entriesSeen >= MAX_DIRECTORY_ENTRIES) break;\n entriesSeen += 1;\n const absolute = path.join(directory, entry.name);\n const label = entry.isDirectory()\n ? \"[DIR]\"\n : entry.isSymbolicLink()\n ? \"[LINK]\"\n : \"[FILE]\";\n lines.push(`${prefix}${label} ${entry.name}`);\n\n if (entry.isDirectory() && level < maxDepth) {\n await walk(absolute, level + 1, prefix + \" \");\n }\n }\n }\n\n const stat = await fs.stat(targetPath);\n if (!stat.isDirectory()) throw new Error(\"Path is not a directory: \" + targetPath);\n\n await walk(targetPath, 1, \"\");\n if (entriesSeen >= MAX_DIRECTORY_ENTRIES) {\n lines.push(`… truncated after ${MAX_DIRECTORY_ENTRIES} entries`);\n }\n\n return `Directory: ${targetPath}\\nDepth: ${maxDepth}\\n\\n${lines.join(\"\\n\") || \"(empty)\"}`;\n}\n\nexport async function readTextFile(\n targetPath: string,\n offset?: number,\n length?: number,\n) {\n const stat = await fs.stat(targetPath);\n if (!stat.isFile()) throw new Error(\"Path is not a file: \" + targetPath);\n if (stat.size > MAX_TEXT_FILE_BYTES) {\n throw new Error(\n `File is too large for read_file (${printableSize(stat.size)} > 20 MB). Use a terminal command or a more targeted tool instead.`,\n );\n }\n\n const buffer = await fs.readFile(targetPath);\n const sample = buffer.subarray(0, Math.min(buffer.length, 8192));\n if (sample.includes(0)) {\n throw new Error(\"Binary file detected. read_file currently supports text files only.\");\n }\n\n const text = buffer.toString(\"utf8\");\n const lines = text.split(/\\r?\\n/);\n const requestedOffset = Number.isFinite(offset) ? Math.trunc(offset as number) : 0;\n const start =\n requestedOffset < 0\n ? Math.max(0, lines.length + requestedOffset)\n : Math.min(lines.length, Math.max(0, requestedOffset));\n const requestedLength =\n Number.isFinite(length) && (length as number) > 0\n ? Math.trunc(length as number)\n : DEFAULT_READ_LINES;\n const end = Math.min(lines.length, start + requestedLength);\n const chunk = lines.slice(start, end).join(\"\\n\");\n\n const location =\n start === 0\n ? \"start\"\n : end === lines.length\n ? `line ${start + 1} to end`\n : `lines ${start + 1}-${end}`;\n\n return `[Reading ${end - start} lines from ${location} (total: ${lines.length} lines, ${printableSize(stat.size)})]\\n\\n${chunk}`;\n}\n\nexport async function getFileInfo(targetPath: string) {\n const stat = await fs.lstat(targetPath);\n return {\n path: targetPath,\n type: stat.isFile()\n ? \"file\"\n : stat.isDirectory()\n ? \"directory\"\n : stat.isSymbolicLink()\n ? \"symlink\"\n : \"other\",\n size: stat.size,\n size_human: printableSize(stat.size),\n mode: stat.mode,\n created_at: stat.birthtime.toISOString(),\n modified_at: stat.mtime.toISOString(),\n accessed_at: stat.atime.toISOString(),\n };\n}\n\nexport async function writeTextFile(\n targetPath: string,\n content: string,\n mode: \"rewrite\" | \"append\" = \"rewrite\",\n) {\n await fs.mkdir(path.dirname(targetPath), { recursive: true });\n if (mode === \"append\") {\n await fs.appendFile(targetPath, content, \"utf8\");\n } else {\n await fs.writeFile(targetPath, content, \"utf8\");\n }\n const stat = await fs.stat(targetPath);\n return {\n path: targetPath,\n mode,\n bytes: Buffer.byteLength(content),\n file_size: stat.size,\n };\n}\n\nexport async function editTextBlock(\n filePath: string,\n oldString: string,\n newString: string,\n expectedReplacements = 1,\n) {\n if (!oldString) throw new Error(\"old_string cannot be empty.\");\n const current = await fs.readFile(filePath, \"utf8\");\n const parts = current.split(oldString);\n const replacements = parts.length - 1;\n\n if (replacements !== expectedReplacements) {\n throw new Error(\n `Expected ${expectedReplacements} replacement(s) in ${filePath}, found ${replacements}. No changes were written.`,\n );\n }\n\n const next = parts.join(newString);\n await fs.writeFile(filePath, next, \"utf8\");\n return {\n path: filePath,\n replacements,\n bytes_before: Buffer.byteLength(current),\n bytes_after: Buffer.byteLength(next),\n };\n}\n","import { execFile, spawn } from \"node:child_process\";\nimport process from \"node:process\";\n\nconst MAX_CAPTURE_BYTES = 2 * 1024 * 1024;\n\nfunction appendCapped(current: string, chunk: Buffer | string) {\n if (Buffer.byteLength(current) >= MAX_CAPTURE_BYTES) return current;\n const next = current + chunk.toString();\n if (Buffer.byteLength(next) <= MAX_CAPTURE_BYTES) return next;\n return next.slice(0, MAX_CAPTURE_BYTES) + \"\\n… output truncated …\";\n}\n\nexport async function listProcesses() {\n const output = await new Promise<string>((resolve, reject) => {\n const command = process.platform === \"win32\" ? \"tasklist.exe\" : \"ps\";\n const args =\n process.platform === \"win32\"\n ? [\"/FO\", \"CSV\", \"/NH\"]\n : [\"-axo\", \"pid,ppid,user,%cpu,%mem,etime,command\"];\n execFile(command, args, { maxBuffer: MAX_CAPTURE_BYTES }, (error, stdout, stderr) => {\n if (error) {\n reject(new Error(`Could not list processes: ${stderr || error.message}`));\n return;\n }\n resolve(stdout.trim());\n });\n });\n\n return `Processes on ${process.platform}:\\n\\n${output}`;\n}\n\nasync function terminateTree(child: ReturnType<typeof spawn>) {\n if (!child.pid) return;\n if (process.platform === \"win32\") {\n await new Promise<void>((resolve) => {\n const killer = spawn(\n \"taskkill.exe\",\n [\"/PID\", String(child.pid), \"/T\", \"/F\"],\n { windowsHide: true, stdio: \"ignore\" },\n );\n killer.once(\"close\", () => resolve());\n killer.once(\"error\", () => resolve());\n });\n return;\n }\n\n try {\n process.kill(-child.pid, \"SIGTERM\");\n } catch {\n child.kill(\"SIGTERM\");\n }\n await new Promise((resolve) => setTimeout(resolve, 300));\n try {\n process.kill(-child.pid, \"SIGKILL\");\n } catch {\n if (!child.killed) child.kill(\"SIGKILL\");\n }\n}\n\nexport async function runShellCommand(command: string, timeoutMs = 5000) {\n const timeout = Math.max(100, Math.min(120_000, Math.trunc(timeoutMs || 5000)));\n const startedAt = Date.now();\n\n return await new Promise<{\n command: string;\n exit_code: number | null;\n signal: NodeJS.Signals | null;\n stdout: string;\n stderr: string;\n duration_ms: number;\n timed_out: boolean;\n }>((resolve, reject) => {\n const child = spawn(command, {\n shell: true,\n windowsHide: true,\n detached: process.platform !== \"win32\",\n stdio: [\"ignore\", \"pipe\", \"pipe\"],\n });\n\n let stdout = \"\";\n let stderr = \"\";\n let timedOut = false;\n let settled = false;\n\n child.stdout?.on(\"data\", (chunk) => {\n stdout = appendCapped(stdout, chunk);\n });\n child.stderr?.on(\"data\", (chunk) => {\n stderr = appendCapped(stderr, chunk);\n });\n\n const timer = setTimeout(async () => {\n timedOut = true;\n await terminateTree(child);\n }, timeout);\n\n child.once(\"error\", (error) => {\n if (settled) return;\n settled = true;\n clearTimeout(timer);\n reject(error);\n });\n\n child.once(\"close\", (code, signal) => {\n if (settled) return;\n settled = true;\n clearTimeout(timer);\n resolve({\n command,\n exit_code: code,\n signal,\n stdout,\n stderr,\n duration_ms: Date.now() - startedAt,\n timed_out: timedOut,\n });\n });\n });\n}\n","import crypto from \"node:crypto\";\nimport { createReadStream } from \"node:fs\";\nimport fs from \"node:fs/promises\";\nimport os from \"node:os\";\nimport path from \"node:path\";\n\nconst RETENTION_MS = 7 * 24 * 60 * 60 * 1000;\nconst MAX_SNAPSHOT_BYTES = 20 * 1024 * 1024;\nconst MAX_UNDO_BYTES = 200 * 1024 * 1024;\n\ntype UndoManifest = {\n id: string;\n createdAt: string;\n tool: \"write_file\" | \"edit_block\";\n targetPath: string;\n existed: boolean;\n mode?: number;\n bytes: number;\n postChangeHash?: string;\n};\n\nexport type UndoSnapshot = {\n id: string;\n directory: string;\n manifest: UndoManifest;\n};\n\nconst undoRoot = () =>\n process.env.REMOTEARC_UNDO_ROOT ||\n path.join(os.homedir(), \".remotearc\", \"undo\");\n\nasync function ensureUndoRoot() {\n await fs.mkdir(undoRoot(), { recursive: true, mode: 0o700 });\n}\n\nasync function readManifest(directory: string): Promise<UndoManifest | null> {\n try {\n return JSON.parse(\n await fs.readFile(path.join(directory, \"manifest.json\"), \"utf8\"),\n ) as UndoManifest;\n } catch {\n return null;\n }\n}\n\nasync function snapshotDirectories() {\n await ensureUndoRoot();\n const entries = await fs.readdir(undoRoot(), { withFileTypes: true });\n return entries\n .filter((entry) => entry.isDirectory())\n .map((entry) => path.join(undoRoot(), entry.name));\n}\n\nasync function cleanupUndoStore() {\n const now = Date.now();\n const snapshots: Array<{ directory: string; manifest: UndoManifest }> = [];\n\n for (const directory of await snapshotDirectories()) {\n const manifest = await readManifest(directory);\n if (!manifest) {\n await fs.rm(directory, { recursive: true, force: true }).catch(() => undefined);\n continue;\n }\n\n const created = Date.parse(manifest.createdAt);\n if (!Number.isFinite(created) || now - created > RETENTION_MS) {\n await fs.rm(directory, { recursive: true, force: true }).catch(() => undefined);\n continue;\n }\n\n snapshots.push({ directory, manifest });\n }\n\n snapshots.sort(\n (a, b) => Date.parse(a.manifest.createdAt) - Date.parse(b.manifest.createdAt),\n );\n\n let total = snapshots.reduce((sum, item) => sum + item.manifest.bytes, 0);\n for (const item of snapshots) {\n if (total <= MAX_UNDO_BYTES) break;\n await fs.rm(item.directory, { recursive: true, force: true }).catch(() => undefined);\n total -= item.manifest.bytes;\n }\n}\n\nfunction mutationPath(\n tool: \"write_file\" | \"edit_block\",\n args: Record<string, unknown>,\n) {\n const candidate = tool === \"write_file\" ? args.path : args.file_path;\n return typeof candidate === \"string\" && candidate.trim() ? candidate : null;\n}\n\nexport async function createUndoSnapshot(\n tool: \"write_file\" | \"edit_block\",\n args: Record<string, unknown>,\n): Promise<UndoSnapshot | null> {\n const targetPath = mutationPath(tool, args);\n if (!targetPath) return null;\n\n await cleanupUndoStore();\n\n let existed = false;\n let mode: number | undefined;\n let bytes = 0;\n let original: Buffer | null = null;\n\n try {\n const stat = await fs.stat(targetPath);\n if (!stat.isFile()) return null;\n existed = true;\n mode = stat.mode;\n bytes = stat.size;\n if (bytes > MAX_SNAPSHOT_BYTES) return null;\n original = await fs.readFile(targetPath);\n } catch (error) {\n const code =\n error && typeof error === \"object\" && \"code\" in error\n ? String((error as { code?: unknown }).code)\n : \"\";\n if (code !== \"ENOENT\") throw error;\n }\n\n const id = `${Date.now()}-${crypto.randomUUID().slice(0, 8)}`;\n const directory = path.join(undoRoot(), id);\n await fs.mkdir(directory, { recursive: true, mode: 0o700 });\n\n if (original) {\n await fs.writeFile(path.join(directory, \"content.bin\"), original, { mode: 0o600 });\n }\n\n const manifest: UndoManifest = {\n id,\n createdAt: new Date().toISOString(),\n tool,\n targetPath,\n existed,\n ...(mode !== undefined ? { mode } : {}),\n bytes,\n };\n\n await fs.writeFile(\n path.join(directory, \"manifest.json\"),\n JSON.stringify(manifest, null, 2) + \"\\n\",\n { mode: 0o600 },\n );\n\n await cleanupUndoStore();\n return { id, directory, manifest };\n}\n\nasync function hashFile(filePath: string) {\n const hash = crypto.createHash(\"sha256\");\n for await (const chunk of createReadStream(filePath)) hash.update(chunk);\n return hash.digest(\"hex\");\n}\n\nexport async function finalizeUndoSnapshot(snapshot: UndoSnapshot | null) {\n if (!snapshot) return false;\n try {\n snapshot.manifest.postChangeHash = await hashFile(snapshot.manifest.targetPath);\n await fs.writeFile(\n path.join(snapshot.directory, \"manifest.json\"),\n JSON.stringify(snapshot.manifest, null, 2) + \"\\n\",\n { mode: 0o600 },\n );\n return true;\n } catch {\n await discardUndoSnapshot(snapshot);\n return false;\n }\n}\n\nexport async function discardUndoSnapshot(snapshot: UndoSnapshot | null) {\n if (!snapshot) return;\n await fs.rm(snapshot.directory, { recursive: true, force: true }).catch(() => undefined);\n}\n\nexport async function undoLastChange() {\n const candidates: Array<{ directory: string; manifest: UndoManifest }> = [];\n for (const directory of await snapshotDirectories()) {\n const manifest = await readManifest(directory);\n if (manifest) candidates.push({ directory, manifest });\n }\n\n candidates.sort(\n (a, b) => Date.parse(b.manifest.createdAt) - Date.parse(a.manifest.createdAt),\n );\n const latest = candidates[0];\n if (!latest) {\n throw new Error(\"No reversible Remote Arc file change is available on this device.\");\n }\n\n if (!latest.manifest.postChangeHash) {\n throw new Error(\n \"This snapshot predates conflict-safe Local Undo and cannot be restored automatically.\",\n );\n }\n\n let currentHash: string;\n try {\n currentHash = await hashFile(latest.manifest.targetPath);\n } catch {\n throw new Error(\n \"The target file changed or disappeared after the Remote Arc edit. Automatic undo was refused to avoid overwriting newer work.\",\n );\n }\n\n if (currentHash !== latest.manifest.postChangeHash) {\n throw new Error(\n \"The target file changed again after the Remote Arc edit. Automatic undo was refused to avoid overwriting newer work.\",\n );\n }\n\n if (latest.manifest.existed) {\n const original = await fs.readFile(path.join(latest.directory, \"content.bin\"));\n await fs.mkdir(path.dirname(latest.manifest.targetPath), { recursive: true });\n await fs.writeFile(latest.manifest.targetPath, original);\n if (latest.manifest.mode !== undefined) {\n await fs.chmod(latest.manifest.targetPath, latest.manifest.mode).catch(() => undefined);\n }\n } else {\n await fs.rm(latest.manifest.targetPath, { force: true });\n }\n\n await fs.rm(latest.directory, { recursive: true, force: true });\n\n return {\n restored: true,\n action_id: latest.manifest.id,\n tool: latest.manifest.tool,\n path: latest.manifest.targetPath,\n snapshot_location: \"local-device-only\",\n };\n}\n\ntype GuardRule = { pattern: RegExp; reason: string };\n\nconst DESTRUCTIVE_COMMAND_RULES: GuardRule[] = [\n {\n pattern: /(?:^|[;&|]\\s*)(?:sudo\\s+)?rm\\s+[^\\n]*(?:-rf|-fr|-[a-z]*r[a-z]*f)[^\\n]*(?:\\s\\/\\s*$|\\s\\/\\*|\\s~(?:\\s|$)|\\s\\$HOME(?:\\s|$))/i,\n reason: \"recursive deletion of a root or home path\",\n },\n {\n pattern: /\\b(?:mkfs(?:\\.\\w+)?|wipefs|fdisk|parted)\\b/i,\n reason: \"disk or filesystem destructive operation\",\n },\n {\n pattern: /\\bdd\\b[^\\n]*\\bof=\\/dev\\/(?:sd|nvme|vd|xvd|mmcblk)/i,\n reason: \"raw disk overwrite\",\n },\n {\n pattern: /\\bdiskutil\\s+erase(?:disk|volume)\\b/i,\n reason: \"disk erase\",\n },\n {\n pattern: /\\b(?:format(?:\\.com)?\\s+[a-z]:|diskpart\\b|clear-disk\\b|initialize-disk\\b)/i,\n reason: \"Windows disk destructive operation\",\n },\n {\n pattern: /\\b(?:shutdown|reboot|halt|poweroff)\\b/i,\n reason: \"system shutdown or reboot\",\n },\n {\n pattern: /\\bremove-item\\b[^\\n]*(?:-recurse[^\\n]*-force|-force[^\\n]*-recurse)[^\\n]*(?:[a-z]:\\\\(?:\\*|\\s|$)|\\$env:systemdrive)/i,\n reason: \"recursive forced deletion of a drive root\",\n },\n {\n pattern: /\\b(?:del|erase|rd|rmdir)\\b[^\\n]*\\/s[^\\n]*\\/q[^\\n]*[a-z]:\\\\/i,\n reason: \"recursive Windows drive deletion\",\n },\n {\n pattern: /:\\(\\)\\s*\\{\\s*:\\|:&\\s*\\};\\s*:/,\n reason: \"fork bomb\",\n },\n];\n\nexport function assertCommandAllowed(command: string) {\n if (process.env.REMOTEARC_ALLOW_DESTRUCTIVE === \"1\") return;\n\n for (const rule of DESTRUCTIVE_COMMAND_RULES) {\n if (rule.pattern.test(command)) {\n throw new Error(\n \"Blocked by Remote Arc Safety Guard: \" +\n rule.reason +\n \". Run this action manually on the device if you intentionally need it.\",\n );\n }\n }\n}\n","import {\n editTextBlock,\n getFileInfo,\n listDirectory,\n readTextFile,\n writeTextFile,\n} from \"./filesystem.js\";\nimport { listProcesses, runShellCommand } from \"./process.js\";\nimport {\n assertCommandAllowed,\n createUndoSnapshot,\n discardUndoSnapshot,\n finalizeUndoSnapshot,\n undoLastChange,\n} from \"./safety.js\";\nimport type {\n ExecutionMode,\n ToolArguments,\n ToolDefinition,\n ToolName,\n ToolResult,\n} from \"./types.js\";\n\nconst SAFE_TOOLS = new Set<ToolName>([\n \"list_directory\",\n \"read_file\",\n \"get_file_info\",\n \"list_processes\",\n]);\n\nconst DEVELOPER_TOOLS = new Set<ToolName>([\n ...SAFE_TOOLS,\n \"write_file\",\n \"edit_block\",\n \"undo_last_change\",\n]);\n\nconst FULL_TOOLS = new Set<ToolName>([\n ...DEVELOPER_TOOLS,\n \"start_process\",\n]);\n\nconst DEFINITIONS: ToolDefinition[] = [\n {\n name: \"list_directory\",\n description: \"List files and directories on this computer without following directory symlinks.\",\n inputSchema: {\n type: \"object\",\n properties: {\n path: { type: \"string\" },\n depth: { type: \"integer\", minimum: 1, maximum: 10, default: 2 },\n },\n required: [\"path\"],\n additionalProperties: false,\n },\n },\n {\n name: \"read_file\",\n description: \"Read a text file by line range. Negative offsets read from the end.\",\n inputSchema: {\n type: \"object\",\n properties: {\n path: { type: \"string\" },\n offset: { type: \"integer\" },\n length: { type: \"integer\", minimum: 1 },\n },\n required: [\"path\"],\n additionalProperties: false,\n },\n },\n {\n name: \"get_file_info\",\n description: \"Get local file or directory metadata.\",\n inputSchema: {\n type: \"object\",\n properties: { path: { type: \"string\" } },\n required: [\"path\"],\n additionalProperties: false,\n },\n },\n {\n name: \"list_processes\",\n description: \"List processes running on this computer.\",\n inputSchema: { type: \"object\", properties: {}, additionalProperties: false },\n },\n {\n name: \"write_file\",\n description: \"Write or append UTF-8 text. Remote Arc creates a local-only Undo snapshot first.\",\n inputSchema: {\n type: \"object\",\n properties: {\n path: { type: \"string\" },\n content: { type: \"string\" },\n mode: { type: \"string\", enum: [\"rewrite\", \"append\"], default: \"rewrite\" },\n },\n required: [\"path\", \"content\"],\n additionalProperties: false,\n },\n },\n {\n name: \"edit_block\",\n description: \"Apply an exact text replacement with conflict-safe Local Undo.\",\n inputSchema: {\n type: \"object\",\n properties: {\n file_path: { type: \"string\" },\n old_string: { type: \"string\" },\n new_string: { type: \"string\" },\n expected_replacements: { type: \"integer\", minimum: 1, default: 1 },\n },\n required: [\"file_path\", \"old_string\", \"new_string\"],\n additionalProperties: false,\n },\n },\n {\n name: \"undo_last_change\",\n description: \"Undo the newest reversible Remote Arc file edit stored only on this device.\",\n inputSchema: { type: \"object\", properties: {}, additionalProperties: false },\n },\n {\n name: \"start_process\",\n description: \"Run a shell command with timeout and output capture. Catastrophic command patterns are blocked locally.\",\n inputSchema: {\n type: \"object\",\n properties: {\n command: { type: \"string\" },\n timeout_ms: { type: \"integer\", minimum: 100, maximum: 120000, default: 5000 },\n },\n required: [\"command\"],\n additionalProperties: false,\n },\n },\n];\n\nconst textResult = (value: unknown): ToolResult => ({\n content: [\n {\n type: \"text\",\n text: typeof value === \"string\" ? value : JSON.stringify(value, null, 2),\n },\n ],\n});\n\nfunction requiredString(args: ToolArguments, key: string) {\n const value = args[key];\n if (typeof value !== \"string\") throw new Error(`${key} must be a string.`);\n return value;\n}\n\nfunction optionalNumber(args: ToolArguments, key: string) {\n const value = args[key];\n return typeof value === \"number\" && Number.isFinite(value) ? value : undefined;\n}\n\nexport class RemoteArcExecutionCore {\n constructor(private readonly mode: ExecutionMode = \"managed\") {}\n\n private allowedTools() {\n if (this.mode === \"safe\") return SAFE_TOOLS;\n if (this.mode === \"developer\") return DEVELOPER_TOOLS;\n return FULL_TOOLS;\n }\n\n listTools() {\n const allowed = this.allowedTools();\n return DEFINITIONS.filter((tool) => allowed.has(tool.name));\n }\n\n async callTool(name: string, args: ToolArguments = {}): Promise<ToolResult> {\n const toolName = name as ToolName;\n if (!this.allowedTools().has(toolName)) {\n throw new Error(`Tool blocked by local permission mode: ${name}`);\n }\n\n switch (toolName) {\n case \"list_directory\":\n return textResult(\n await listDirectory(\n requiredString(args, \"path\"),\n optionalNumber(args, \"depth\") ?? 2,\n ),\n );\n case \"read_file\":\n return textResult(\n await readTextFile(\n requiredString(args, \"path\"),\n optionalNumber(args, \"offset\"),\n optionalNumber(args, \"length\"),\n ),\n );\n case \"get_file_info\":\n return textResult(await getFileInfo(requiredString(args, \"path\")));\n case \"list_processes\":\n return textResult(await listProcesses());\n case \"undo_last_change\":\n return textResult(await undoLastChange());\n case \"start_process\": {\n const command = requiredString(args, \"command\");\n assertCommandAllowed(command);\n return textResult(\n await runShellCommand(\n command,\n optionalNumber(args, \"timeout_ms\") ?? 5000,\n ),\n );\n }\n case \"write_file\":\n case \"edit_block\": {\n const snapshot = await createUndoSnapshot(toolName, args);\n try {\n const result =\n toolName === \"write_file\"\n ? await writeTextFile(\n requiredString(args, \"path\"),\n requiredString(args, \"content\"),\n args.mode === \"append\" ? \"append\" : \"rewrite\",\n )\n : await editTextBlock(\n requiredString(args, \"file_path\"),\n requiredString(args, \"old_string\"),\n requiredString(args, \"new_string\"),\n optionalNumber(args, \"expected_replacements\") ?? 1,\n );\n\n const undoAvailable = await finalizeUndoSnapshot(snapshot);\n return textResult({\n ...result,\n undo_available: undoAvailable,\n undo_storage: undoAvailable ? \"local-device-only\" : null,\n });\n } catch (error) {\n await discardUndoSnapshot(snapshot);\n throw error;\n }\n }\n default:\n throw new Error(\"Unknown Remote Arc tool: \" + name);\n }\n }\n\n async close() {\n // Native execution has no persistent child process to close.\n }\n}\n\nexport const toolDefinitions = DEFINITIONS;\n"],"mappings":"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","names":["os","path","fs","spawn","process","process","fs","path","path","os","process","fs","spawn"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "remotelink",
3
- "version": "0.3.6",
3
+ "version": "0.3.8",
4
4
  "description": "Connect a computer to Remote Arc with one command.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -17,15 +17,15 @@
17
17
  "node": ">=20"
18
18
  },
19
19
  "scripts": {
20
- "build": "tsup src/index.ts --format esm --platform node --target node20 --sourcemap",
20
+ "build": "tsup",
21
21
  "typecheck": "tsc --noEmit",
22
22
  "prepublishOnly": "pnpm build"
23
23
  },
24
24
  "dependencies": {
25
- "@modelcontextprotocol/client": "^2.1.0",
26
25
  "ws": "^8.18.3"
27
26
  },
28
27
  "devDependencies": {
28
+ "@remotearc/execution-core": "workspace:*",
29
29
  "@types/node": "^24.13.6",
30
30
  "@types/ws": "^8.18.1",
31
31
  "tsup": "^8.5.0",