@remcp/runtime 0.2.231 → 0.2.232

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@remcp/runtime",
3
- "version": "0.2.231",
3
+ "version": "0.2.232",
4
4
  "description": "First-party ReMCP local device runtime: filesystem, terminal, computer-use, browser, diagnostics and document tools over MCP.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -60,17 +60,17 @@ export async function createArchiveTool(args, extra = {}) {
60
60
  if (format === 'zip') {
61
61
  if (process.platform === 'win32') {
62
62
  if (!tools.tar) fail('Windows archive backend is unavailable: tar.exe is required');
63
- const result = spawnSync(tools.tar, ['-a', '-c', '-f', staging, '--', ...archiveNames], { cwd: snapshotRoot, encoding: 'utf8', timeout: 120_000, maxBuffer: 16 * 1024 * 1024 });
63
+ const result = spawnSync(tools.tar, ['-a', '-c', '-f', staging, '--', ...archiveNames], { cwd: snapshotRoot, encoding: 'utf8', timeout: 120_000, maxBuffer: 16 * 1024 * 1024, windowsHide:true });
64
64
  if (result.status !== 0) fail(`tar.exe ZIP creation failed: ${(result.stderr || result.stdout || '').trim() || `exit ${result.status}`}`);
65
65
  } else {
66
66
  if (!tools.zip) fail('zip is not installed on this device; use format "tar.gz"');
67
- const result = spawnSync(tools.zip, ['-r', '-q', '-y', staging, '--', ...archiveNames], { cwd: snapshotRoot, encoding: 'utf8', timeout: 120_000, maxBuffer: 16 * 1024 * 1024 });
67
+ const result = spawnSync(tools.zip, ['-r', '-q', '-y', staging, '--', ...archiveNames], { cwd: snapshotRoot, encoding: 'utf8', timeout: 120_000, maxBuffer: 16 * 1024 * 1024, windowsHide:true });
68
68
  if (result.status !== 0) fail(`zip failed: ${(result.stderr || result.stdout || '').trim() || `exit ${result.status}`}`);
69
69
  }
70
70
  } else if (format === 'tar' || format === 'tar.gz' || format === 'tgz') {
71
71
  if (!tools.tar) fail('tar is not installed on this device');
72
72
  const flags = format === 'tar' ? '-cf' : '-czf';
73
- const result = spawnSync(tools.tar, [flags, staging, '--', ...archiveNames], { cwd: snapshotRoot, encoding: 'utf8', timeout: 120_000, maxBuffer: 16 * 1024 * 1024 });
73
+ const result = spawnSync(tools.tar, [flags, staging, '--', ...archiveNames], { cwd: snapshotRoot, encoding: 'utf8', timeout: 120_000, maxBuffer: 16 * 1024 * 1024, windowsHide:true });
74
74
  if (result.status !== 0) fail(`tar failed: ${(result.stderr || result.stdout || '').trim() || `exit ${result.status}`}`);
75
75
  } else {
76
76
  fail('format must be tar, tar.gz, or zip');
@@ -124,34 +124,34 @@ export async function extractArchiveTool(args) {
124
124
  if (existingDestination?.isSymbolicLink() || (existingDestination && !existingDestination.isDirectory())) fail('Archive destination is not a safe directory');
125
125
  if (format === 'zip' && process.platform !== 'win32') {
126
126
  if (!tools.unzip) fail('unzip is not installed on this device');
127
- const listing = spawnSync(tools.unzip, ['-Z', '-1', archiveSnapshot], { encoding: 'utf8', timeout: 30_000, maxBuffer: 16 * 1024 * 1024 });
127
+ const listing = spawnSync(tools.unzip, ['-Z', '-1', archiveSnapshot], { encoding: 'utf8', timeout: 30_000, maxBuffer: 16 * 1024 * 1024, windowsHide:true });
128
128
  if (listing.error || listing.status !== 0) fail(`Could not inspect ZIP archive: ${(listing.stderr || listing.error?.message || `exit ${listing.status}`).trim()}`);
129
129
  const names = String(listing.stdout || '').split(/\r?\n/).filter(Boolean);
130
130
  if (names.length > 100_000 || names.some(name => !safeArchiveEntry(name))) fail('ZIP archive contains an unsafe path or too many entries');
131
- const details = spawnSync(tools.unzip, ['-Z', '-v', archiveSnapshot], { encoding: 'utf8', timeout: 30_000, maxBuffer: 16 * 1024 * 1024 });
131
+ const details = spawnSync(tools.unzip, ['-Z', '-v', archiveSnapshot], { encoding: 'utf8', timeout: 30_000, maxBuffer: 16 * 1024 * 1024, windowsHide:true });
132
132
  if (details.error || details.status !== 0) fail(`Could not inspect ZIP sizes: ${(details.stderr || details.error?.message || `exit ${details.status}`).trim()}`);
133
133
  const detailText = String(details.stdout || '');
134
134
  if (/symbolic link|Unix file attributes \([^)]*\b12\d{4}/i.test(detailText)) fail('ZIP archive contains a symbolic link');
135
135
  const expandedBytes = archiveExpandedSize(detailText.split(/\r?\n/), /uncompressed size:\s*(\d+)\s*bytes/i, 'ZIP archive', names.length);
136
136
  assertArchiveExpandedSize(expandedBytes, 'ZIP archive');
137
- const result = spawnSync(tools.unzip, ['-o', '-q', archiveSnapshot, '-d', staging], { encoding: 'utf8', timeout: 120_000, maxBuffer: 16 * 1024 * 1024 });
137
+ const result = spawnSync(tools.unzip, ['-o', '-q', archiveSnapshot, '-d', staging], { encoding: 'utf8', timeout: 120_000, maxBuffer: 16 * 1024 * 1024, windowsHide:true });
138
138
  if (result.status !== 0) fail(`unzip failed: ${(result.stderr || result.stdout || '').trim() || `exit ${result.status}`}`);
139
139
  } else {
140
140
  if (!tools.tar) fail(process.platform === 'win32' ? 'Windows archive backend is unavailable: tar.exe is required' : 'tar is not installed on this device');
141
141
  const listFlags = format === 'tar.gz' ? '-tzf' : format === 'tar.bz2' ? '-tjf' : format === 'tar.xz' ? '-tJf' : '-tf';
142
- const listing = spawnSync(tools.tar, [listFlags, archiveSnapshot], { encoding: 'utf8', timeout: 30_000, maxBuffer: 16 * 1024 * 1024 });
142
+ const listing = spawnSync(tools.tar, [listFlags, archiveSnapshot], { encoding: 'utf8', timeout: 30_000, maxBuffer: 16 * 1024 * 1024, windowsHide:true });
143
143
  if (listing.error || listing.status !== 0) fail(`Could not inspect archive: ${(listing.stderr || listing.error?.message || `exit ${listing.status}`).trim()}`);
144
144
  const names = String(listing.stdout || '').split(/\r?\n/).filter(Boolean);
145
145
  if (names.length > 100_000 || names.some(name => !safeArchiveEntry(name))) fail('Archive contains an unsafe path or too many entries');
146
146
  const verboseFlags = format === 'tar.gz' ? '-tvzf' : format === 'tar.bz2' ? '-tvjf' : format === 'tar.xz' ? '-tvJf' : '-tvf';
147
- const details = spawnSync(tools.tar, [verboseFlags, archiveSnapshot], { encoding: 'utf8', timeout: 30_000, maxBuffer: 16 * 1024 * 1024 });
147
+ const details = spawnSync(tools.tar, [verboseFlags, archiveSnapshot], { encoding: 'utf8', timeout: 30_000, maxBuffer: 16 * 1024 * 1024, windowsHide:true });
148
148
  if (details.error || details.status !== 0) fail(`Could not inspect archive sizes: ${(details.stderr || details.error?.message || `exit ${details.status}`).trim()}`);
149
149
  const detailLines = String(details.stdout || '').split(/\r?\n/);
150
150
  if (detailLines.some(line => /^[bclph]/.test(line))) fail('Archive contains a link or special file; archive destination is unsafe');
151
151
  const expandedBytes = archiveTarExpandedSize(detailLines, 'archive', names.length);
152
152
  assertArchiveExpandedSize(expandedBytes, 'archive');
153
153
  const flags = format === 'tar.gz' ? '-xzf' : format === 'tar.bz2' ? '-xjf' : format === 'tar.xz' ? '-xJf' : '-xf';
154
- const result = spawnSync(tools.tar, [flags, archiveSnapshot, '-C', staging], { encoding: 'utf8', timeout: 120_000, maxBuffer: 16 * 1024 * 1024 });
154
+ const result = spawnSync(tools.tar, [flags, archiveSnapshot, '-C', staging], { encoding: 'utf8', timeout: 120_000, maxBuffer: 16 * 1024 * 1024, windowsHide:true });
155
155
  if (result.status !== 0) fail(`tar failed: ${(result.stderr || result.stdout || '').trim() || `exit ${result.status}`}`);
156
156
  }
157
157
  await assertExtractedTree(staging);
@@ -368,7 +368,7 @@ export async function moveArchiveFile(source, destination) {
368
368
  }
369
369
 
370
370
  export function archiveCommandProbe(name, versionArgs = ['--version']) {
371
- const result = spawnSync(name, versionArgs, { encoding: 'utf8' });
371
+ const result = spawnSync(name, versionArgs, { encoding: 'utf8', windowsHide:true });
372
372
  return !result.error && result.status === 0 ? name : null;
373
373
  }
374
374
 
@@ -135,8 +135,8 @@ export async function takeScreenshotTool(args) {
135
135
  }
136
136
  if (!await pathExists(file)) {
137
137
  for (const candidate of SCREENSHOT_COMMANDS) {
138
- if (spawnSync('which', [candidate.command], { encoding: 'utf8' }).status !== 0) continue;
139
- const result = spawnSync(candidate.command, candidate.args(file), { encoding: 'utf8', timeout: 30000 });
138
+ if (spawnSync('which', [candidate.command], { encoding: 'utf8', windowsHide:true }).status !== 0) continue;
139
+ const result = spawnSync(candidate.command, candidate.args(file), { encoding: 'utf8', timeout: 30000, windowsHide:true });
140
140
  if (result.status === 0 && await pathExists(file)) break;
141
141
  attempts.push(`${candidate.command}: ${(result.stderr || '').trim() || ('exit ' + result.status)}`);
142
142
  }
@@ -27,7 +27,7 @@ function ripgrep() {
27
27
  if (process.env.REMCP_RUNTIME_FORCE_FALLBACK === '1') return null;
28
28
  if (ripgrepPath !== undefined) return ripgrepPath;
29
29
  try {
30
- const result = spawnSync('rg', ['--version'], { encoding: 'utf8' });
30
+ const result = spawnSync('rg', ['--version'], { encoding: 'utf8', windowsHide:true });
31
31
  ripgrepPath = !result.error && result.status === 0 ? 'rg' : null;
32
32
  } catch { ripgrepPath = null; }
33
33
  return ripgrepPath;
@@ -200,7 +200,7 @@ function runRipgrep(session, { target, pattern, searchType, filePattern, ignoreC
200
200
  if (contextLines) args.push('-C', String(contextLines));
201
201
  args.push('--', pattern, searchTarget);
202
202
  }
203
- const child = spawn(ripgrep(), args, { stdio: ['ignore', 'pipe', 'pipe'] });
203
+ const child = spawn(ripgrep(), args, { stdio: ['ignore', 'pipe', 'pipe'], windowsHide:true });
204
204
  session.cancel = () => child.kill('SIGTERM');
205
205
  let buffer = '';
206
206
  let stderr = '';