@instaclaw/dispatch 0.1.1 → 0.2.0
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/index.js +17 -4
- package/dist/supervisor.d.ts +1 -0
- package/dist/supervisor.js +51 -5
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
import { loadConfig, saveConfig, getConfigPath } from "./config.js";
|
|
10
10
|
import { checkPermissions, printPermissionGuide, runPermissionTest } from "./permissions.js";
|
|
11
11
|
import { connect, disconnect } from "./connection.js";
|
|
12
|
-
import { closeSupervisor } from "./supervisor.js";
|
|
12
|
+
import { closeSupervisor, setMode } from "./supervisor.js";
|
|
13
13
|
import readline from "readline";
|
|
14
14
|
import os from "os";
|
|
15
15
|
async function main() {
|
|
@@ -55,7 +55,7 @@ async function main() {
|
|
|
55
55
|
gatewayToken: args.token,
|
|
56
56
|
vmAddress: args.vm,
|
|
57
57
|
port: args.port || 8765,
|
|
58
|
-
mode: "supervised",
|
|
58
|
+
mode: args.autonomous ? "autonomous" : "supervised",
|
|
59
59
|
};
|
|
60
60
|
saveConfig(config);
|
|
61
61
|
}
|
|
@@ -65,6 +65,10 @@ async function main() {
|
|
|
65
65
|
saveConfig(config);
|
|
66
66
|
console.log(` Config saved to ${getConfigPath()}\n`);
|
|
67
67
|
}
|
|
68
|
+
// Set supervisor mode
|
|
69
|
+
if (config.mode === "autonomous") {
|
|
70
|
+
setMode("autonomous");
|
|
71
|
+
}
|
|
68
72
|
console.log(` VM: ${config.vmAddress}:${config.port}`);
|
|
69
73
|
console.log(` Mode: ${config.mode}`);
|
|
70
74
|
console.log(` Token: ${config.gatewayToken.substring(0, 8)}...\n`);
|
|
@@ -77,8 +81,14 @@ async function main() {
|
|
|
77
81
|
rejectUnauthorized: false, // Accept self-signed (TOFU)
|
|
78
82
|
certFingerprint: config.certFingerprint,
|
|
79
83
|
onConnect: () => {
|
|
80
|
-
|
|
81
|
-
|
|
84
|
+
if (config.mode === "autonomous") {
|
|
85
|
+
console.log(`\n Dispatch mode: AUTONOMOUS`);
|
|
86
|
+
console.log(` All actions auto-approved (dangerous actions still require confirmation).`);
|
|
87
|
+
}
|
|
88
|
+
else {
|
|
89
|
+
console.log(`\n Dispatch mode: SUPERVISED`);
|
|
90
|
+
console.log(` Screenshots auto-approved. Actions require [Enter] to confirm.`);
|
|
91
|
+
}
|
|
82
92
|
console.log(` Press Ctrl+C to disconnect.\n`);
|
|
83
93
|
},
|
|
84
94
|
onDisconnect: () => {
|
|
@@ -133,6 +143,9 @@ function parseArgs() {
|
|
|
133
143
|
else if ((args[i] === "--port" || args[i] === "-p") && args[i + 1]) {
|
|
134
144
|
result.port = parseInt(args[++i], 10);
|
|
135
145
|
}
|
|
146
|
+
else if (args[i] === "--autonomous" || args[i] === "--auto") {
|
|
147
|
+
result.autonomous = true;
|
|
148
|
+
}
|
|
136
149
|
}
|
|
137
150
|
return result;
|
|
138
151
|
}
|
package/dist/supervisor.d.ts
CHANGED
package/dist/supervisor.js
CHANGED
|
@@ -1,9 +1,25 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Supervisor —
|
|
3
|
-
*
|
|
2
|
+
* Supervisor — controls whether commands need user approval.
|
|
3
|
+
*
|
|
4
|
+
* Modes:
|
|
5
|
+
* supervised (default) — all non-passive commands require Enter to approve
|
|
6
|
+
* autonomous — auto-approves most commands, but ALWAYS prompts for dangerous ones
|
|
4
7
|
*/
|
|
5
8
|
import readline from "readline";
|
|
6
9
|
const AUTO_APPROVE_TYPES = new Set(["screenshot", "windows", "status"]);
|
|
10
|
+
// Patterns that indicate dangerous actions — always require confirmation even in autonomous mode
|
|
11
|
+
const DANGEROUS_TEXT_PATTERNS = [
|
|
12
|
+
/password/i, /passwd/i, /secret/i, /credential/i,
|
|
13
|
+
/delete/i, /remove/i, /destroy/i, /format/i, /erase/i,
|
|
14
|
+
/purchase/i, /submit.*order/i, /confirm.*payment/i, /buy\s/i,
|
|
15
|
+
/transfer.*fund/i, /send.*money/i, /withdraw/i,
|
|
16
|
+
/sudo\s/i, /rm\s+-rf/i, /shutdown/i, /reboot/i,
|
|
17
|
+
];
|
|
18
|
+
const DANGEROUS_KEY_COMBOS = new Set([
|
|
19
|
+
"cmd+delete", "cmd+shift+delete", "ctrl+delete",
|
|
20
|
+
"cmd+q", "alt+f4",
|
|
21
|
+
]);
|
|
22
|
+
let mode = "supervised";
|
|
7
23
|
const isTTY = process.stdin.isTTY ?? false;
|
|
8
24
|
let rl = null;
|
|
9
25
|
if (isTTY) {
|
|
@@ -12,18 +28,36 @@ if (isTTY) {
|
|
|
12
28
|
output: process.stdout,
|
|
13
29
|
});
|
|
14
30
|
}
|
|
31
|
+
export function setMode(m) {
|
|
32
|
+
mode = m;
|
|
33
|
+
}
|
|
15
34
|
export async function requestApproval(command) {
|
|
16
|
-
//
|
|
35
|
+
// Always auto-approve passive commands
|
|
17
36
|
if (AUTO_APPROVE_TYPES.has(command.type)) {
|
|
18
37
|
return true;
|
|
19
38
|
}
|
|
20
39
|
const desc = formatCommand(command);
|
|
21
|
-
|
|
22
|
-
// Non-interactive
|
|
40
|
+
const dangerous = isDangerous(command);
|
|
41
|
+
// Non-interactive (no TTY) — auto-approve everything (can't prompt)
|
|
23
42
|
if (!rl) {
|
|
43
|
+
if (dangerous) {
|
|
44
|
+
console.log(`\n BLOCKED (dangerous, no TTY): ${desc}`);
|
|
45
|
+
return false;
|
|
46
|
+
}
|
|
47
|
+
console.log(`\n Agent wants to: ${desc}`);
|
|
24
48
|
console.log(" Auto-approved (non-interactive mode)");
|
|
25
49
|
return true;
|
|
26
50
|
}
|
|
51
|
+
// Autonomous mode — auto-approve non-dangerous actions
|
|
52
|
+
if (mode === "autonomous" && !dangerous) {
|
|
53
|
+
console.log(`\n Agent: ${desc}`);
|
|
54
|
+
return true;
|
|
55
|
+
}
|
|
56
|
+
// Supervised mode OR dangerous action in autonomous mode — prompt user
|
|
57
|
+
console.log(`\n Agent wants to: ${desc}`);
|
|
58
|
+
if (dangerous) {
|
|
59
|
+
console.log(" ⚠️ DANGEROUS ACTION — requires confirmation");
|
|
60
|
+
}
|
|
27
61
|
return new Promise((resolve) => {
|
|
28
62
|
rl.question(" [Enter] to approve, [n] to deny: ", (answer) => {
|
|
29
63
|
const denied = answer.trim().toLowerCase() === "n";
|
|
@@ -34,6 +68,18 @@ export async function requestApproval(command) {
|
|
|
34
68
|
});
|
|
35
69
|
});
|
|
36
70
|
}
|
|
71
|
+
function isDangerous(cmd) {
|
|
72
|
+
const p = cmd.params;
|
|
73
|
+
if (cmd.type === "type") {
|
|
74
|
+
const text = String(p.text || "");
|
|
75
|
+
return DANGEROUS_TEXT_PATTERNS.some((pat) => pat.test(text));
|
|
76
|
+
}
|
|
77
|
+
if (cmd.type === "press") {
|
|
78
|
+
const key = String(p.key || "").toLowerCase();
|
|
79
|
+
return DANGEROUS_KEY_COMBOS.has(key);
|
|
80
|
+
}
|
|
81
|
+
return false;
|
|
82
|
+
}
|
|
37
83
|
function formatCommand(cmd) {
|
|
38
84
|
const p = cmd.params;
|
|
39
85
|
switch (cmd.type) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@instaclaw/dispatch",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "Let your InstaClaw AI agent control your computer — screenshots, clicks, typing, and more via a secure WebSocket relay",
|
|
5
5
|
"bin": {
|
|
6
6
|
"instaclaw-dispatch": "./dist/index.js"
|