screenhand 0.4.5 → 0.4.6
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/dist/mcp-desktop.js +42 -0
- package/dist/src/native/bridge-client.js +16 -1
- package/package.json +4 -1
package/dist/mcp-desktop.js
CHANGED
|
@@ -164,6 +164,48 @@ Docs: https://github.com/manushi4/Screenhand
|
|
|
164
164
|
`);
|
|
165
165
|
process.exit(0);
|
|
166
166
|
}
|
|
167
|
+
// ── Startup cleanup: remove corrupt/empty state files ──
|
|
168
|
+
{
|
|
169
|
+
const stateDir = path.join(os.homedir(), ".screenhand", "state");
|
|
170
|
+
if (fs.existsSync(stateDir)) {
|
|
171
|
+
try {
|
|
172
|
+
const files = fs.readdirSync(stateDir).filter(f => f.endsWith(".json"));
|
|
173
|
+
let removed = 0;
|
|
174
|
+
for (const file of files) {
|
|
175
|
+
const filePath = path.join(stateDir, file);
|
|
176
|
+
try {
|
|
177
|
+
const stat = fs.statSync(filePath);
|
|
178
|
+
// Remove empty files
|
|
179
|
+
if (stat.size === 0) {
|
|
180
|
+
fs.unlinkSync(filePath);
|
|
181
|
+
removed++;
|
|
182
|
+
continue;
|
|
183
|
+
}
|
|
184
|
+
// Remove files older than 7 days
|
|
185
|
+
if (Date.now() - stat.mtimeMs > 7 * 24 * 60 * 60 * 1000) {
|
|
186
|
+
fs.unlinkSync(filePath);
|
|
187
|
+
removed++;
|
|
188
|
+
continue;
|
|
189
|
+
}
|
|
190
|
+
// Remove corrupt JSON (can't parse)
|
|
191
|
+
const content = fs.readFileSync(filePath, "utf-8");
|
|
192
|
+
JSON.parse(content);
|
|
193
|
+
}
|
|
194
|
+
catch {
|
|
195
|
+
try {
|
|
196
|
+
fs.unlinkSync(filePath);
|
|
197
|
+
removed++;
|
|
198
|
+
}
|
|
199
|
+
catch { /* ignore */ }
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
if (removed > 0) {
|
|
203
|
+
console.error(`[screenhand] Cleaned up ${removed} stale/corrupt state files from ${stateDir}`);
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
catch { /* ignore if dir can't be read */ }
|
|
207
|
+
}
|
|
208
|
+
}
|
|
167
209
|
// ── Audit logging for dangerous tools ──
|
|
168
210
|
const AUDIT_LOG_PATH = path.resolve(__dirname, ".audit-log.jsonl");
|
|
169
211
|
function auditLog(tool, params) {
|
|
@@ -251,13 +251,28 @@ export class BridgeClient extends EventEmitter {
|
|
|
251
251
|
return [...this.recentStderr];
|
|
252
252
|
}
|
|
253
253
|
async spawn() {
|
|
254
|
+
// Check binary exists before spawning — give actionable error instead of cryptic ENOENT
|
|
255
|
+
if (!fs.existsSync(this.binaryPath)) {
|
|
256
|
+
const platform = process.platform;
|
|
257
|
+
const hint = platform === "darwin"
|
|
258
|
+
? `Run: npm run build:native (requires Xcode + Swift)`
|
|
259
|
+
: platform === "win32"
|
|
260
|
+
? `Run: npm run build:native:windows (requires .NET 8 SDK)`
|
|
261
|
+
: `Native bridge is only available on macOS and Windows.`;
|
|
262
|
+
throw new Error(`ScreenHand native bridge not found at: ${this.binaryPath}\n` +
|
|
263
|
+
`${hint}\n` +
|
|
264
|
+
`If installed via npm, try: npm rebuild screenhand`);
|
|
265
|
+
}
|
|
254
266
|
const child = spawn(this.binaryPath, [], {
|
|
255
267
|
stdio: ["pipe", "pipe", "pipe"],
|
|
256
268
|
});
|
|
257
269
|
// Track which process this is so stale event handlers don't trigger restarts
|
|
258
270
|
const spawnedProcess = child;
|
|
259
271
|
child.on("error", (err) => {
|
|
260
|
-
|
|
272
|
+
const msg = err.code === "ENOENT"
|
|
273
|
+
? new Error(`ScreenHand native bridge binary not found: ${this.binaryPath}. Run: npm run build:native`)
|
|
274
|
+
: err;
|
|
275
|
+
this.emit("error", msg);
|
|
261
276
|
// Only auto-restart if this is still the active process
|
|
262
277
|
if (this.started && this.process === spawnedProcess) {
|
|
263
278
|
this.restart().catch(() => { });
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "screenhand",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.6",
|
|
4
4
|
"mcpName": "io.github.manushi4/screenhand",
|
|
5
5
|
"description": "Give AI eyes and hands on your desktop. ScreenHand is an open-source MCP server that lets Claude and other AI agents see your screen, click buttons, type text, and control any app on macOS and Windows.",
|
|
6
6
|
"homepage": "https://screenhand.com",
|
|
@@ -70,6 +70,9 @@
|
|
|
70
70
|
"ocr",
|
|
71
71
|
"computer-use"
|
|
72
72
|
],
|
|
73
|
+
"engines": {
|
|
74
|
+
"node": ">=18"
|
|
75
|
+
},
|
|
73
76
|
"dependencies": {
|
|
74
77
|
"@anthropic-ai/sdk": "^0.78.0",
|
|
75
78
|
"@modelcontextprotocol/sdk": "^1.27.1",
|