@pentoshi/clai 0.8.2 → 0.9.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/agent/loop-guard.d.ts +43 -0
- package/dist/agent/loop-guard.js +75 -0
- package/dist/agent/loop-guard.js.map +1 -0
- package/dist/agent/progress.d.ts +14 -0
- package/dist/agent/progress.js +112 -0
- package/dist/agent/progress.js.map +1 -0
- package/dist/agent/runner.js +57 -9
- package/dist/agent/runner.js.map +1 -1
- package/dist/agent/task-analyzer.d.ts +13 -0
- package/dist/agent/task-analyzer.js +158 -0
- package/dist/agent/task-analyzer.js.map +1 -0
- package/dist/agent/task-plan.d.ts +37 -0
- package/dist/agent/task-plan.js +98 -0
- package/dist/agent/task-plan.js.map +1 -0
- package/dist/prompts/index.d.ts +1 -1
- package/dist/prompts/index.js +20 -1
- package/dist/prompts/index.js.map +1 -1
- package/dist/safety/classifier.js +64 -0
- package/dist/safety/classifier.js.map +1 -1
- package/dist/safety/path-permissions.d.ts +14 -0
- package/dist/safety/path-permissions.js +43 -0
- package/dist/safety/path-permissions.js.map +1 -0
- package/dist/tools/capabilities.d.ts +11 -0
- package/dist/tools/capabilities.js +136 -0
- package/dist/tools/capabilities.js.map +1 -0
- package/dist/tools/command-intent.d.ts +11 -0
- package/dist/tools/command-intent.js +61 -0
- package/dist/tools/command-intent.js.map +1 -0
- package/dist/tools/fs.d.ts +10 -0
- package/dist/tools/fs.js +73 -2
- package/dist/tools/fs.js.map +1 -1
- package/dist/tools/jobs.d.ts +28 -0
- package/dist/tools/jobs.js +161 -0
- package/dist/tools/jobs.js.map +1 -0
- package/dist/tools/net-ping-sweep.d.ts +24 -0
- package/dist/tools/net-ping-sweep.js +205 -0
- package/dist/tools/net-ping-sweep.js.map +1 -0
- package/dist/tools/network-context.d.ts +26 -0
- package/dist/tools/network-context.js +138 -0
- package/dist/tools/network-context.js.map +1 -0
- package/dist/tools/registry.js +43 -1
- package/dist/tools/registry.js.map +1 -1
- package/dist/tools/shell.js +3 -3
- package/dist/tools/shell.js.map +1 -1
- package/dist/ui/task-pane.d.ts +17 -0
- package/dist/ui/task-pane.js +80 -0
- package/dist/ui/task-pane.js.map +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { ToolResult } from "../types.js";
|
|
2
|
+
export interface ToolAvailability {
|
|
3
|
+
name: string;
|
|
4
|
+
available: boolean;
|
|
5
|
+
path?: string | undefined;
|
|
6
|
+
version?: string | undefined;
|
|
7
|
+
installHint?: string | undefined;
|
|
8
|
+
}
|
|
9
|
+
export declare function checkTool(name: string): Promise<ToolAvailability>;
|
|
10
|
+
export declare function checkTools(names: string[]): Promise<ToolAvailability[]>;
|
|
11
|
+
export declare function toolCheckHandler(args: Record<string, unknown>): Promise<ToolResult>;
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
import { execSync } from "node:child_process";
|
|
2
|
+
import { platform } from "node:os";
|
|
3
|
+
const VERSION_COMMANDS = {
|
|
4
|
+
nmap: ["nmap", "--version"],
|
|
5
|
+
ffuf: ["ffuf", "-V"],
|
|
6
|
+
curl: ["curl", "--version"],
|
|
7
|
+
python3: ["python3", "--version"],
|
|
8
|
+
python: ["python", "--version"],
|
|
9
|
+
node: ["node", "--version"],
|
|
10
|
+
go: ["go", "version"],
|
|
11
|
+
dig: ["dig", "-v"],
|
|
12
|
+
whois: ["whois", "--version"],
|
|
13
|
+
gobuster: ["gobuster", "version"],
|
|
14
|
+
nikto: ["nikto", "-Version"],
|
|
15
|
+
sqlmap: ["sqlmap", "--version"],
|
|
16
|
+
hydra: ["hydra", "-h"],
|
|
17
|
+
rg: ["rg", "--version"],
|
|
18
|
+
jq: ["jq", "--version"],
|
|
19
|
+
git: ["git", "--version"],
|
|
20
|
+
docker: ["docker", "--version"],
|
|
21
|
+
kubectl: ["kubectl", "version", "--client", "--short"],
|
|
22
|
+
};
|
|
23
|
+
const INSTALL_HINTS = {
|
|
24
|
+
nmap: "pkg.install nmap",
|
|
25
|
+
ffuf: "go install github.com/ffuf/ffuf/v2@latest",
|
|
26
|
+
gobuster: "go install github.com/OJ/gobuster/v3@latest",
|
|
27
|
+
nikto: "pkg.install nikto",
|
|
28
|
+
sqlmap: "pkg.install sqlmap",
|
|
29
|
+
hydra: "pkg.install hydra",
|
|
30
|
+
rg: "pkg.install ripgrep",
|
|
31
|
+
jq: "pkg.install jq",
|
|
32
|
+
dig: "pkg.install dnsutils (or bind-utils)",
|
|
33
|
+
subfinder: "go install github.com/projectdiscovery/subfinder/v2/cmd/subfinder@latest",
|
|
34
|
+
httpx: "go install github.com/projectdiscovery/httpx/cmd/httpx@latest",
|
|
35
|
+
nuclei: "go install github.com/projectdiscovery/nuclei/v3/cmd/nuclei@latest",
|
|
36
|
+
};
|
|
37
|
+
function findCommand(name) {
|
|
38
|
+
try {
|
|
39
|
+
const cmd = platform() === "win32" ? `where.exe ${name}` : `command -v ${name}`;
|
|
40
|
+
const result = execSync(cmd, {
|
|
41
|
+
timeout: 3_000,
|
|
42
|
+
encoding: "utf8",
|
|
43
|
+
stdio: ["ignore", "pipe", "ignore"],
|
|
44
|
+
});
|
|
45
|
+
return result.trim().split("\n")[0]?.trim();
|
|
46
|
+
}
|
|
47
|
+
catch {
|
|
48
|
+
return undefined;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
function getVersion(name) {
|
|
52
|
+
const spec = VERSION_COMMANDS[name];
|
|
53
|
+
if (!spec)
|
|
54
|
+
return undefined;
|
|
55
|
+
try {
|
|
56
|
+
const result = execSync(spec.join(" "), {
|
|
57
|
+
timeout: 5_000,
|
|
58
|
+
encoding: "utf8",
|
|
59
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
60
|
+
});
|
|
61
|
+
// Take the first non-empty line containing a version-like pattern
|
|
62
|
+
const lines = result.split("\n").filter(Boolean);
|
|
63
|
+
for (const line of lines) {
|
|
64
|
+
const ver = /(\d+\.\d+[.\w-]*)/.exec(line);
|
|
65
|
+
if (ver?.[1])
|
|
66
|
+
return ver[1];
|
|
67
|
+
}
|
|
68
|
+
return lines[0]?.trim().slice(0, 60);
|
|
69
|
+
}
|
|
70
|
+
catch {
|
|
71
|
+
return undefined;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
export async function checkTool(name) {
|
|
75
|
+
const path = findCommand(name);
|
|
76
|
+
if (!path) {
|
|
77
|
+
return {
|
|
78
|
+
name,
|
|
79
|
+
available: false,
|
|
80
|
+
installHint: INSTALL_HINTS[name],
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
const version = getVersion(name);
|
|
84
|
+
return {
|
|
85
|
+
name,
|
|
86
|
+
available: true,
|
|
87
|
+
path,
|
|
88
|
+
version,
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
export async function checkTools(names) {
|
|
92
|
+
return Promise.all(names.map((name) => checkTool(name)));
|
|
93
|
+
}
|
|
94
|
+
export async function toolCheckHandler(args) {
|
|
95
|
+
const toolsRaw = args.tools;
|
|
96
|
+
let names;
|
|
97
|
+
if (Array.isArray(toolsRaw)) {
|
|
98
|
+
names = toolsRaw.filter((t) => typeof t === "string");
|
|
99
|
+
}
|
|
100
|
+
else if (typeof toolsRaw === "string") {
|
|
101
|
+
names = toolsRaw.split(",").map((t) => t.trim()).filter(Boolean);
|
|
102
|
+
}
|
|
103
|
+
else {
|
|
104
|
+
return {
|
|
105
|
+
ok: false,
|
|
106
|
+
output: 'tool.check expects { "tools": ["nmap", "ffuf", ...] } or { "tools": "nmap,ffuf" }',
|
|
107
|
+
exitCode: 1,
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
if (names.length === 0) {
|
|
111
|
+
return { ok: false, output: "No tool names provided.", exitCode: 1 };
|
|
112
|
+
}
|
|
113
|
+
if (names.length > 20) {
|
|
114
|
+
return {
|
|
115
|
+
ok: false,
|
|
116
|
+
output: "tool.check accepts at most 20 tools per call.",
|
|
117
|
+
exitCode: 1,
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
const results = await checkTools(names);
|
|
121
|
+
const lines = results.map((r) => {
|
|
122
|
+
if (r.available) {
|
|
123
|
+
const ver = r.version ? ` (${r.version})` : "";
|
|
124
|
+
return `✓ ${r.name}${ver} — ${r.path}`;
|
|
125
|
+
}
|
|
126
|
+
const hint = r.installHint ? ` — install: ${r.installHint}` : "";
|
|
127
|
+
return `✗ ${r.name} — not found${hint}`;
|
|
128
|
+
});
|
|
129
|
+
const allAvailable = results.every((r) => r.available);
|
|
130
|
+
return {
|
|
131
|
+
ok: allAvailable,
|
|
132
|
+
output: lines.join("\n"),
|
|
133
|
+
exitCode: allAvailable ? 0 : 1,
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
//# sourceMappingURL=capabilities.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"capabilities.js","sourceRoot":"","sources":["../../src/tools/capabilities.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Detect commands that are likely long-running servers, listeners, or
|
|
3
|
+
* watch processes. These should be started as background jobs rather
|
|
4
|
+
* than blocking the REPL.
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* Returns true if the command appears to be a long-running process that
|
|
8
|
+
* should not block the foreground shell. This is a heuristic — false
|
|
9
|
+
* negatives are safer than false positives.
|
|
10
|
+
*/
|
|
11
|
+
export declare function looksLongRunning(command: string): boolean;
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Detect commands that are likely long-running servers, listeners, or
|
|
3
|
+
* watch processes. These should be started as background jobs rather
|
|
4
|
+
* than blocking the REPL.
|
|
5
|
+
*/
|
|
6
|
+
const LONG_RUNNING_PATTERNS = [
|
|
7
|
+
// Listeners / bind shells
|
|
8
|
+
/\bnc\s+.*-l\b/i,
|
|
9
|
+
/\bncat\s+.*-l\b/i,
|
|
10
|
+
/\bsocat\b.*\bLISTEN\b/i,
|
|
11
|
+
// Python HTTP servers
|
|
12
|
+
/\bpython3?\s+(-m\s+)?http\.server\b/i,
|
|
13
|
+
/\bpython3?\s+(-m\s+)?SimpleHTTPServer\b/i,
|
|
14
|
+
// Node/JS dev servers
|
|
15
|
+
/\bnpm\s+run\s+dev\b/i,
|
|
16
|
+
/\byarn\s+dev\b/i,
|
|
17
|
+
/\bpnpm\s+dev\b/i,
|
|
18
|
+
/\bbun\s+dev\b/i,
|
|
19
|
+
/\bnpm\s+start\s*$/i,
|
|
20
|
+
/\bnode\s+server\b/i,
|
|
21
|
+
/\bnodemon\b/i,
|
|
22
|
+
/\bvite\b(?!\s+build)/i,
|
|
23
|
+
/\bnext\s+dev\b/i,
|
|
24
|
+
/\bnuxt\s+dev\b/i,
|
|
25
|
+
// Log followers / watchers
|
|
26
|
+
/\btail\s+.*-[fF]\b/i,
|
|
27
|
+
/\bjournalctl\s+.*-f\b/i,
|
|
28
|
+
/\bwatch\s+/i,
|
|
29
|
+
/\bcargo\s+watch\b/i,
|
|
30
|
+
// Docker
|
|
31
|
+
/\bdocker\s+logs\s+.*-f\b/i,
|
|
32
|
+
/\bdocker\s+compose\s+up\b/i,
|
|
33
|
+
/\bdocker-compose\s+up\b/i,
|
|
34
|
+
// Python/Ruby/Go servers
|
|
35
|
+
/\buvicorn\b/i,
|
|
36
|
+
/\bgunicorn\b/i,
|
|
37
|
+
/\bflask\s+run\b/i,
|
|
38
|
+
/\brails\s+(?:server|s)\b/i,
|
|
39
|
+
/\bsinatra\b/i,
|
|
40
|
+
// Other dev servers
|
|
41
|
+
/\bphp\s+-S\b/i,
|
|
42
|
+
/\bnginx\s*$/i,
|
|
43
|
+
/\bapache2?\s*$/i,
|
|
44
|
+
// Tunnel / proxy
|
|
45
|
+
/\bngrok\s+http\b/i,
|
|
46
|
+
/\bssh\s+.*-[DLRN]\b/i,
|
|
47
|
+
/\bchisel\s+(server|client)\b/i,
|
|
48
|
+
// Network listeners
|
|
49
|
+
/\btcpdump\b/i,
|
|
50
|
+
/\bwireshark\b/i,
|
|
51
|
+
/\btshark\b.*-i\b/i,
|
|
52
|
+
];
|
|
53
|
+
/**
|
|
54
|
+
* Returns true if the command appears to be a long-running process that
|
|
55
|
+
* should not block the foreground shell. This is a heuristic — false
|
|
56
|
+
* negatives are safer than false positives.
|
|
57
|
+
*/
|
|
58
|
+
export function looksLongRunning(command) {
|
|
59
|
+
return LONG_RUNNING_PATTERNS.some((pattern) => pattern.test(command));
|
|
60
|
+
}
|
|
61
|
+
//# sourceMappingURL=command-intent.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"command-intent.js","sourceRoot":"","sources":["../../src/tools/command-intent.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,MAAM,qBAAqB,GAAa;IACtC,0BAA0B;IAC1B,gBAAgB;IAChB,kBAAkB;IAClB,wBAAwB;IAExB,sBAAsB;IACtB,sCAAsC;IACtC,0CAA0C;IAE1C,sBAAsB;IACtB,sBAAsB;IACtB,iBAAiB;IACjB,iBAAiB;IACjB,gBAAgB;IAChB,oBAAoB;IACpB,oBAAoB;IACpB,cAAc;IACd,uBAAuB;IACvB,iBAAiB;IACjB,iBAAiB;IAEjB,2BAA2B;IAC3B,qBAAqB;IACrB,wBAAwB;IACxB,aAAa;IACb,oBAAoB;IAEpB,SAAS;IACT,2BAA2B;IAC3B,4BAA4B;IAC5B,0BAA0B;IAE1B,yBAAyB;IACzB,cAAc;IACd,eAAe;IACf,kBAAkB;IAClB,2BAA2B;IAC3B,cAAc;IAEd,oBAAoB;IACpB,eAAe;IACf,cAAc;IACd,iBAAiB;IAEjB,iBAAiB;IACjB,mBAAmB;IACnB,sBAAsB;IACtB,+BAA+B;IAE/B,oBAAoB;IACpB,cAAc;IACd,gBAAgB;IAChB,mBAAmB;CACpB,CAAC;AAEF;;;;GAIG;AACH,MAAM,UAAU,gBAAgB,CAAC,OAAe;IAC9C,OAAO,qBAAqB,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC;AACxE,CAAC"}
|
package/dist/tools/fs.d.ts
CHANGED
|
@@ -7,3 +7,13 @@ export declare function fsList(path: string, options?: {
|
|
|
7
7
|
maxEntries?: number | undefined;
|
|
8
8
|
}): Promise<ToolResult>;
|
|
9
9
|
export declare function fsSearch(pattern: string, path?: string): Promise<ToolResult>;
|
|
10
|
+
/**
|
|
11
|
+
* Atomic search-and-replace edit. Reads the file, validates the match
|
|
12
|
+
* count, performs replacement, and writes back.
|
|
13
|
+
*/
|
|
14
|
+
export declare function fsEdit(path: string, oldText: string, newText: string, expectedReplacements?: number | undefined): Promise<ToolResult>;
|
|
15
|
+
/**
|
|
16
|
+
* Delete a file or directory. Requires the path to be inside the
|
|
17
|
+
* write sandbox and not a secret path.
|
|
18
|
+
*/
|
|
19
|
+
export declare function fsDelete(path: string, recursive?: boolean | undefined): Promise<ToolResult>;
|
package/dist/tools/fs.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { open, readdir, writeFile } from "node:fs/promises";
|
|
2
|
-
import { relative, resolve } from "node:path";
|
|
1
|
+
import { open, readdir, readFile, writeFile, unlink, rm, rename } from "node:fs/promises";
|
|
2
|
+
import { join, dirname, basename, relative, resolve } from "node:path";
|
|
3
3
|
import { homedir, tmpdir } from "node:os";
|
|
4
4
|
import { execa } from "execa";
|
|
5
5
|
import { getConfig } from "../store/config.js";
|
|
@@ -157,4 +157,75 @@ export async function fsSearch(pattern, path = process.cwd()) {
|
|
|
157
157
|
};
|
|
158
158
|
}
|
|
159
159
|
}
|
|
160
|
+
/**
|
|
161
|
+
* Atomic search-and-replace edit. Reads the file, validates the match
|
|
162
|
+
* count, performs replacement, and writes back.
|
|
163
|
+
*/
|
|
164
|
+
export async function fsEdit(path, oldText, newText, expectedReplacements) {
|
|
165
|
+
const resolved = ensureWriteAllowed(path);
|
|
166
|
+
const content = await readFile(resolved, "utf8");
|
|
167
|
+
const expected = expectedReplacements ?? 1;
|
|
168
|
+
// Count occurrences
|
|
169
|
+
let count = 0;
|
|
170
|
+
let searchPos = 0;
|
|
171
|
+
while (true) {
|
|
172
|
+
const idx = content.indexOf(oldText, searchPos);
|
|
173
|
+
if (idx === -1)
|
|
174
|
+
break;
|
|
175
|
+
count += 1;
|
|
176
|
+
searchPos = idx + oldText.length;
|
|
177
|
+
}
|
|
178
|
+
if (count === 0) {
|
|
179
|
+
return {
|
|
180
|
+
ok: false,
|
|
181
|
+
output: `No matches found for the search text in ${resolved}. The text to replace was not found.`,
|
|
182
|
+
exitCode: 1,
|
|
183
|
+
};
|
|
184
|
+
}
|
|
185
|
+
if (count !== expected) {
|
|
186
|
+
return {
|
|
187
|
+
ok: false,
|
|
188
|
+
output: `Found ${count} occurrence(s) of the search text, but expected exactly ${expected}. Aborting to avoid unintended changes. Use expectedReplacements=${count} if you want to replace all.`,
|
|
189
|
+
exitCode: 1,
|
|
190
|
+
};
|
|
191
|
+
}
|
|
192
|
+
const updated = content.replaceAll(oldText, newText);
|
|
193
|
+
// Atomic write: write to temp file in same directory, then rename
|
|
194
|
+
const tempPath = join(dirname(resolved), `.${basename(resolved)}.clai-tmp`);
|
|
195
|
+
try {
|
|
196
|
+
await writeFile(tempPath, updated, "utf8");
|
|
197
|
+
await rename(tempPath, resolved);
|
|
198
|
+
}
|
|
199
|
+
catch (error) {
|
|
200
|
+
// Cleanup temp file on failure
|
|
201
|
+
try {
|
|
202
|
+
await unlink(tempPath);
|
|
203
|
+
}
|
|
204
|
+
catch { /* ignore */ }
|
|
205
|
+
throw error;
|
|
206
|
+
}
|
|
207
|
+
return {
|
|
208
|
+
ok: true,
|
|
209
|
+
output: `Replaced ${count} occurrence(s) in ${resolved}.`,
|
|
210
|
+
};
|
|
211
|
+
}
|
|
212
|
+
/**
|
|
213
|
+
* Delete a file or directory. Requires the path to be inside the
|
|
214
|
+
* write sandbox and not a secret path.
|
|
215
|
+
*/
|
|
216
|
+
export async function fsDelete(path, recursive) {
|
|
217
|
+
const resolved = ensureWriteAllowed(path);
|
|
218
|
+
try {
|
|
219
|
+
if (recursive) {
|
|
220
|
+
await rm(resolved, { recursive: true, force: false });
|
|
221
|
+
return { ok: true, output: `Deleted (recursive): ${resolved}` };
|
|
222
|
+
}
|
|
223
|
+
await unlink(resolved);
|
|
224
|
+
return { ok: true, output: `Deleted: ${resolved}` };
|
|
225
|
+
}
|
|
226
|
+
catch (error) {
|
|
227
|
+
const msg = error instanceof Error ? error.message : String(error);
|
|
228
|
+
return { ok: false, output: `Delete failed: ${msg}`, exitCode: 1 };
|
|
229
|
+
}
|
|
230
|
+
}
|
|
160
231
|
//# sourceMappingURL=fs.js.map
|
package/dist/tools/fs.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fs.js","sourceRoot":"","sources":["../../src/tools/fs.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"fs.js","sourceRoot":"","sources":["../../src/tools/fs.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { ToolResult } from "../types.js";
|
|
2
|
+
export type JobStatus = "running" | "exited" | "killed" | "failed";
|
|
3
|
+
export interface BackgroundJob {
|
|
4
|
+
id: string;
|
|
5
|
+
command: string;
|
|
6
|
+
cwd: string;
|
|
7
|
+
pid?: number | undefined;
|
|
8
|
+
status: JobStatus;
|
|
9
|
+
startedAt: string;
|
|
10
|
+
endedAt?: string | undefined;
|
|
11
|
+
exitCode?: number | undefined;
|
|
12
|
+
artifactPath: string;
|
|
13
|
+
}
|
|
14
|
+
export declare class JobManager {
|
|
15
|
+
private jobs;
|
|
16
|
+
private processes;
|
|
17
|
+
private streams;
|
|
18
|
+
startJob(command: string, options?: {
|
|
19
|
+
cwd?: string | undefined;
|
|
20
|
+
name?: string | undefined;
|
|
21
|
+
} | undefined): Promise<ToolResult>;
|
|
22
|
+
listJobs(): ToolResult;
|
|
23
|
+
getJob(id: string): BackgroundJob | undefined;
|
|
24
|
+
tailJob(id: string, bytes?: number | undefined): Promise<ToolResult>;
|
|
25
|
+
stopJob(id: string, signal?: NodeJS.Signals | undefined): ToolResult;
|
|
26
|
+
getRunningJobs(): BackgroundJob[];
|
|
27
|
+
}
|
|
28
|
+
export declare const jobManager: JobManager;
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
import { spawn } from "node:child_process";
|
|
2
|
+
import { createWriteStream } from "node:fs";
|
|
3
|
+
import { readFile, mkdir } from "node:fs/promises";
|
|
4
|
+
import { join } from "node:path";
|
|
5
|
+
import { homedir } from "node:os";
|
|
6
|
+
import { randomUUID } from "node:crypto";
|
|
7
|
+
export class JobManager {
|
|
8
|
+
jobs = new Map();
|
|
9
|
+
processes = new Map();
|
|
10
|
+
streams = new Map();
|
|
11
|
+
async startJob(command, options) {
|
|
12
|
+
const id = randomUUID().slice(0, 8);
|
|
13
|
+
const cwd = options?.cwd ?? process.cwd();
|
|
14
|
+
const dir = join(homedir(), ".clai", "jobs");
|
|
15
|
+
await mkdir(dir, { recursive: true });
|
|
16
|
+
const artifactPath = join(dir, `${new Date().toISOString().replace(/[:.]/g, "-")}-${id}.txt`);
|
|
17
|
+
const stream = createWriteStream(artifactPath, { flags: "w" });
|
|
18
|
+
stream.write(`$ ${command}\n\n`);
|
|
19
|
+
try {
|
|
20
|
+
const detached = process.platform !== "win32";
|
|
21
|
+
const child = spawn(command, {
|
|
22
|
+
cwd,
|
|
23
|
+
detached,
|
|
24
|
+
shell: true,
|
|
25
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
26
|
+
});
|
|
27
|
+
const job = {
|
|
28
|
+
id,
|
|
29
|
+
command,
|
|
30
|
+
cwd,
|
|
31
|
+
pid: child.pid,
|
|
32
|
+
status: "running",
|
|
33
|
+
startedAt: new Date().toISOString(),
|
|
34
|
+
artifactPath,
|
|
35
|
+
};
|
|
36
|
+
this.jobs.set(id, job);
|
|
37
|
+
this.processes.set(id, child);
|
|
38
|
+
this.streams.set(id, stream);
|
|
39
|
+
child.stdout?.on("data", (chunk) => {
|
|
40
|
+
stream.write(chunk);
|
|
41
|
+
});
|
|
42
|
+
child.stderr?.on("data", (chunk) => {
|
|
43
|
+
stream.write(chunk);
|
|
44
|
+
});
|
|
45
|
+
child.on("close", (code) => {
|
|
46
|
+
job.status = "exited";
|
|
47
|
+
job.exitCode = code ?? undefined;
|
|
48
|
+
job.endedAt = new Date().toISOString();
|
|
49
|
+
stream.end();
|
|
50
|
+
this.processes.delete(id);
|
|
51
|
+
this.streams.delete(id);
|
|
52
|
+
});
|
|
53
|
+
child.on("error", () => {
|
|
54
|
+
job.status = "failed";
|
|
55
|
+
job.endedAt = new Date().toISOString();
|
|
56
|
+
stream.end();
|
|
57
|
+
this.processes.delete(id);
|
|
58
|
+
this.streams.delete(id);
|
|
59
|
+
});
|
|
60
|
+
// Detach so the child outlives the parent if needed
|
|
61
|
+
child.unref();
|
|
62
|
+
return {
|
|
63
|
+
ok: true,
|
|
64
|
+
output: `Background job started: id=${id} pid=${child.pid ?? "?"}\nCommand: ${command}\nOutput: ${artifactPath}`,
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
catch (error) {
|
|
68
|
+
stream.end();
|
|
69
|
+
return {
|
|
70
|
+
ok: false,
|
|
71
|
+
output: `Failed to start job: ${error instanceof Error ? error.message : String(error)}`,
|
|
72
|
+
exitCode: 1,
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
listJobs() {
|
|
77
|
+
if (this.jobs.size === 0) {
|
|
78
|
+
return { ok: true, output: "No background jobs." };
|
|
79
|
+
}
|
|
80
|
+
const lines = [];
|
|
81
|
+
for (const job of this.jobs.values()) {
|
|
82
|
+
const status = job.status === "running" ? "▶ running" : `${job.status} (exit=${job.exitCode ?? "?"})`;
|
|
83
|
+
const elapsed = job.endedAt
|
|
84
|
+
? `${Math.round((new Date(job.endedAt).getTime() - new Date(job.startedAt).getTime()) / 1000)}s`
|
|
85
|
+
: `${Math.round((Date.now() - new Date(job.startedAt).getTime()) / 1000)}s ago`;
|
|
86
|
+
lines.push(`[${job.id}] ${status} ${elapsed} ${job.command.slice(0, 60)}`);
|
|
87
|
+
}
|
|
88
|
+
return { ok: true, output: lines.join("\n") };
|
|
89
|
+
}
|
|
90
|
+
getJob(id) {
|
|
91
|
+
return this.jobs.get(id);
|
|
92
|
+
}
|
|
93
|
+
async tailJob(id, bytes) {
|
|
94
|
+
const job = this.jobs.get(id);
|
|
95
|
+
if (!job) {
|
|
96
|
+
return { ok: false, output: `Job "${id}" not found.`, exitCode: 1 };
|
|
97
|
+
}
|
|
98
|
+
const tailBytes = bytes ?? 8_000;
|
|
99
|
+
try {
|
|
100
|
+
const content = await readFile(job.artifactPath, "utf8");
|
|
101
|
+
const tail = content.length > tailBytes
|
|
102
|
+
? `... (showing last ${tailBytes.toLocaleString()} bytes)\n${content.slice(-tailBytes)}`
|
|
103
|
+
: content;
|
|
104
|
+
return {
|
|
105
|
+
ok: true,
|
|
106
|
+
output: `[${job.id}] ${job.status}:\n${tail}`,
|
|
107
|
+
outputPath: job.artifactPath,
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
catch (error) {
|
|
111
|
+
return {
|
|
112
|
+
ok: false,
|
|
113
|
+
output: `Failed to read job output: ${error instanceof Error ? error.message : String(error)}`,
|
|
114
|
+
exitCode: 1,
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
stopJob(id, signal) {
|
|
119
|
+
const job = this.jobs.get(id);
|
|
120
|
+
if (!job) {
|
|
121
|
+
return { ok: false, output: `Job "${id}" not found.`, exitCode: 1 };
|
|
122
|
+
}
|
|
123
|
+
if (job.status !== "running") {
|
|
124
|
+
return {
|
|
125
|
+
ok: false,
|
|
126
|
+
output: `Job "${id}" is already ${job.status}.`,
|
|
127
|
+
exitCode: 1,
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
const child = this.processes.get(id);
|
|
131
|
+
if (!child?.pid) {
|
|
132
|
+
job.status = "killed";
|
|
133
|
+
job.endedAt = new Date().toISOString();
|
|
134
|
+
return { ok: true, output: `Job "${id}" marked as killed (no pid).` };
|
|
135
|
+
}
|
|
136
|
+
try {
|
|
137
|
+
const sig = signal ?? "SIGTERM";
|
|
138
|
+
if (process.platform !== "win32") {
|
|
139
|
+
process.kill(-child.pid, sig);
|
|
140
|
+
}
|
|
141
|
+
else {
|
|
142
|
+
child.kill(sig);
|
|
143
|
+
}
|
|
144
|
+
job.status = "killed";
|
|
145
|
+
job.endedAt = new Date().toISOString();
|
|
146
|
+
return { ok: true, output: `Job "${id}" sent ${sig}.` };
|
|
147
|
+
}
|
|
148
|
+
catch {
|
|
149
|
+
return {
|
|
150
|
+
ok: false,
|
|
151
|
+
output: `Failed to stop job "${id}".`,
|
|
152
|
+
exitCode: 1,
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
getRunningJobs() {
|
|
157
|
+
return [...this.jobs.values()].filter((j) => j.status === "running");
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
export const jobManager = new JobManager();
|
|
161
|
+
//# sourceMappingURL=jobs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"jobs.js","sourceRoot":"","sources":["../../src/tools/jobs.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAqB,MAAM,oBAAoB,CAAC;AAC9D,OAAO,EAAE,iBAAiB,EAAoB,MAAM,SAAS,CAAC;AAC9D,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AACnD,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAiBzC,MAAM,OAAO,UAAU;IACb,IAAI,GAAG,IAAI,GAAG,EAAyB,CAAC;IACxC,SAAS,GAAG,IAAI,GAAG,EAAwB,CAAC;IAC5C,OAAO,GAAG,IAAI,GAAG,EAAuB,CAAC;IAEjD,KAAK,CAAC,QAAQ,CACZ,OAAe,EACf,OAA6E;QAE7E,MAAM,EAAE,GAAG,UAAU,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;QACpC,MAAM,GAAG,GAAG,OAAO,EAAE,GAAG,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC;QAC1C,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,EAAE,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC;QAC7C,MAAM,KAAK,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACtC,MAAM,YAAY,GAAG,IAAI,CACvB,GAAG,EACH,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,OAAO,EAAE,GAAG,CAAC,IAAI,EAAE,MAAM,CAC9D,CAAC;QAEF,MAAM,MAAM,GAAG,iBAAiB,CAAC,YAAY,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,CAAC;QAC/D,MAAM,CAAC,KAAK,CAAC,KAAK,OAAO,MAAM,CAAC,CAAC;QAEjC,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,KAAK,OAAO,CAAC;YAC9C,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,EAAE;gBAC3B,GAAG;gBACH,QAAQ;gBACR,KAAK,EAAE,IAAI;gBACX,KAAK,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,CAAC;aAClC,CAAC,CAAC;YAEH,MAAM,GAAG,GAAkB;gBACzB,EAAE;gBACF,OAAO;gBACP,GAAG;gBACH,GAAG,EAAE,KAAK,CAAC,GAAG;gBACd,MAAM,EAAE,SAAS;gBACjB,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;gBACnC,YAAY;aACb,CAAC;YAEF,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC;YACvB,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,EAAE,KAAK,CAAC,CAAC;YAC9B,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,EAAE,MAAM,CAAC,CAAC;YAE7B,KAAK,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,EAAE,CAAC,KAAa,EAAE,EAAE;gBACzC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;YACtB,CAAC,CAAC,CAAC;YACH,KAAK,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,EAAE,CAAC,KAAa,EAAE,EAAE;gBACzC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;YACtB,CAAC,CAAC,CAAC;YAEH,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,IAAI,EAAE,EAAE;gBACzB,GAAG,CAAC,MAAM,GAAG,QAAQ,CAAC;gBACtB,GAAG,CAAC,QAAQ,GAAG,IAAI,IAAI,SAAS,CAAC;gBACjC,GAAG,CAAC,OAAO,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;gBACvC,MAAM,CAAC,GAAG,EAAE,CAAC;gBACb,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;gBAC1B,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;YAC1B,CAAC,CAAC,CAAC;YACH,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE;gBACrB,GAAG,CAAC,MAAM,GAAG,QAAQ,CAAC;gBACtB,GAAG,CAAC,OAAO,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;gBACvC,MAAM,CAAC,GAAG,EAAE,CAAC;gBACb,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;gBAC1B,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;YAC1B,CAAC,CAAC,CAAC;YAEH,oDAAoD;YACpD,KAAK,CAAC,KAAK,EAAE,CAAC;YAEd,OAAO;gBACL,EAAE,EAAE,IAAI;gBACR,MAAM,EAAE,8BAA8B,EAAE,QAAQ,KAAK,CAAC,GAAG,IAAI,GAAG,cAAc,OAAO,aAAa,YAAY,EAAE;aACjH,CAAC;QACJ,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,CAAC,GAAG,EAAE,CAAC;YACb,OAAO;gBACL,EAAE,EAAE,KAAK;gBACT,MAAM,EAAE,wBAAwB,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE;gBACxF,QAAQ,EAAE,CAAC;aACZ,CAAC;QACJ,CAAC;IACH,CAAC;IAED,QAAQ;QACN,IAAI,IAAI,CAAC,IAAI,CAAC,IAAI,KAAK,CAAC,EAAE,CAAC;YACzB,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,qBAAqB,EAAE,CAAC;QACrD,CAAC;QACD,MAAM,KAAK,GAAa,EAAE,CAAC;QAC3B,KAAK,MAAM,GAAG,IAAI,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,CAAC;YACrC,MAAM,MAAM,GAAG,GAAG,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,MAAM,UAAU,GAAG,CAAC,QAAQ,IAAI,GAAG,GAAG,CAAC;YACtG,MAAM,OAAO,GAAG,GAAG,CAAC,OAAO;gBACzB,CAAC,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,IAAI,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,OAAO,EAAE,GAAG,IAAI,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,OAAO,EAAE,CAAC,GAAG,IAAI,CAAC,GAAG;gBAChG,CAAC,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,OAAO,EAAE,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC;YAClF,KAAK,CAAC,IAAI,CAAC,IAAI,GAAG,CAAC,EAAE,KAAK,MAAM,IAAI,OAAO,KAAK,GAAG,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC,CAAC;QAC9E,CAAC;QACD,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;IAChD,CAAC;IAED,MAAM,CAAC,EAAU;QACf,OAAO,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAC3B,CAAC;IAED,KAAK,CAAC,OAAO,CAAC,EAAU,EAAE,KAA0B;QAClD,MAAM,GAAG,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAC9B,IAAI,CAAC,GAAG,EAAE,CAAC;YACT,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,cAAc,EAAE,QAAQ,EAAE,CAAC,EAAE,CAAC;QACtE,CAAC;QACD,MAAM,SAAS,GAAG,KAAK,IAAI,KAAK,CAAC;QACjC,IAAI,CAAC;YACH,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,GAAG,CAAC,YAAY,EAAE,MAAM,CAAC,CAAC;YACzD,MAAM,IAAI,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS;gBACrC,CAAC,CAAC,qBAAqB,SAAS,CAAC,cAAc,EAAE,YAAY,OAAO,CAAC,KAAK,CAAC,CAAC,SAAS,CAAC,EAAE;gBACxF,CAAC,CAAC,OAAO,CAAC;YACZ,OAAO;gBACL,EAAE,EAAE,IAAI;gBACR,MAAM,EAAE,IAAI,GAAG,CAAC,EAAE,KAAK,GAAG,CAAC,MAAM,MAAM,IAAI,EAAE;gBAC7C,UAAU,EAAE,GAAG,CAAC,YAAY;aAC7B,CAAC;QACJ,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO;gBACL,EAAE,EAAE,KAAK;gBACT,MAAM,EAAE,8BAA8B,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE;gBAC9F,QAAQ,EAAE,CAAC;aACZ,CAAC;QACJ,CAAC;IACH,CAAC;IAED,OAAO,CAAC,EAAU,EAAE,MAAmC;QACrD,MAAM,GAAG,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAC9B,IAAI,CAAC,GAAG,EAAE,CAAC;YACT,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,cAAc,EAAE,QAAQ,EAAE,CAAC,EAAE,CAAC;QACtE,CAAC;QACD,IAAI,GAAG,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;YAC7B,OAAO;gBACL,EAAE,EAAE,KAAK;gBACT,MAAM,EAAE,QAAQ,EAAE,gBAAgB,GAAG,CAAC,MAAM,GAAG;gBAC/C,QAAQ,EAAE,CAAC;aACZ,CAAC;QACJ,CAAC;QACD,MAAM,KAAK,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QACrC,IAAI,CAAC,KAAK,EAAE,GAAG,EAAE,CAAC;YAChB,GAAG,CAAC,MAAM,GAAG,QAAQ,CAAC;YACtB,GAAG,CAAC,OAAO,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;YACvC,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,8BAA8B,EAAE,CAAC;QACxE,CAAC;QACD,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,MAAM,IAAI,SAAS,CAAC;YAChC,IAAI,OAAO,CAAC,QAAQ,KAAK,OAAO,EAAE,CAAC;gBACjC,OAAO,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;YAChC,CAAC;iBAAM,CAAC;gBACN,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;YAClB,CAAC;YACD,GAAG,CAAC,MAAM,GAAG,QAAQ,CAAC;YACtB,GAAG,CAAC,OAAO,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;YACvC,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,UAAU,GAAG,GAAG,EAAE,CAAC;QAC1D,CAAC;QAAC,MAAM,CAAC;YACP,OAAO;gBACL,EAAE,EAAE,KAAK;gBACT,MAAM,EAAE,uBAAuB,EAAE,IAAI;gBACrC,QAAQ,EAAE,CAAC;aACZ,CAAC;QACJ,CAAC;IACH,CAAC;IAED,cAAc;QACZ,OAAO,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC;IACvE,CAAC;CACF;AAED,MAAM,CAAC,MAAM,UAAU,GAAG,IAAI,UAAU,EAAE,CAAC"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { ToolResult } from "../types.js";
|
|
2
|
+
export interface PingSweepArgs {
|
|
3
|
+
target: string;
|
|
4
|
+
method?: "auto" | "nmap" | "arp" | "native" | undefined;
|
|
5
|
+
timeoutMs?: number | undefined;
|
|
6
|
+
}
|
|
7
|
+
export interface ActiveDevice {
|
|
8
|
+
ip: string;
|
|
9
|
+
hostname?: string | undefined;
|
|
10
|
+
mac?: string | undefined;
|
|
11
|
+
vendor?: string | undefined;
|
|
12
|
+
source: "nmap" | "arp-scan" | "arp" | "ip-neigh";
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Parse nmap -sn output to extract active devices.
|
|
16
|
+
* Exported for testing.
|
|
17
|
+
*/
|
|
18
|
+
export declare function parseNmapPingSweep(output: string): ActiveDevice[];
|
|
19
|
+
/**
|
|
20
|
+
* Parse arp -a output to extract devices from the ARP table.
|
|
21
|
+
* Exported for testing.
|
|
22
|
+
*/
|
|
23
|
+
export declare function parseArpTable(output: string): ActiveDevice[];
|
|
24
|
+
export declare function pingSweep(args: PingSweepArgs): Promise<ToolResult>;
|