averecion-lite 1.3.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/README.md +161 -0
- package/dashboard/dash.css +1085 -0
- package/dashboard/dash.js +898 -0
- package/dashboard/index.html +312 -0
- package/dashboard/landing.html +360 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +409 -0
- package/dist/hooks.d.ts +25 -0
- package/dist/hooks.d.ts.map +1 -0
- package/dist/hooks.js +68 -0
- package/dist/index.d.ts +34 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +64 -0
- package/dist/injectionGuard.d.ts +9 -0
- package/dist/injectionGuard.d.ts.map +1 -0
- package/dist/injectionGuard.js +16 -0
- package/dist/log-watcher.d.ts +26 -0
- package/dist/log-watcher.d.ts.map +1 -0
- package/dist/log-watcher.js +397 -0
- package/dist/metrics.d.ts +53 -0
- package/dist/metrics.d.ts.map +1 -0
- package/dist/metrics.js +58 -0
- package/dist/policy.d.ts +11 -0
- package/dist/policy.d.ts.map +1 -0
- package/dist/policy.js +60 -0
- package/dist/server.d.ts +3 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +226 -0
- package/dist/src/capability-manifest.d.ts +16 -0
- package/dist/src/capability-manifest.d.ts.map +1 -0
- package/dist/src/capability-manifest.js +228 -0
- package/dist/src/http-proxy.d.ts +4 -0
- package/dist/src/http-proxy.d.ts.map +1 -0
- package/dist/src/http-proxy.js +266 -0
- package/dist/src/risk-engine.d.ts +43 -0
- package/dist/src/risk-engine.d.ts.map +1 -0
- package/dist/src/risk-engine.js +258 -0
- package/dist/src/shell-wrapper.d.ts +3 -0
- package/dist/src/shell-wrapper.d.ts.map +1 -0
- package/dist/src/shell-wrapper.js +264 -0
- package/dist/storage.d.ts +28 -0
- package/dist/storage.d.ts.map +1 -0
- package/dist/storage.js +144 -0
- package/examples/INTEGRATION.md +162 -0
- package/examples/claude-desktop-agent.json +32 -0
- package/examples/clawdbot-agent.json +44 -0
- package/examples/custom-agent.json +20 -0
- package/lite-policy.json +5 -0
- package/package.json +56 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../cli.ts"],"names":[],"mappings":""}
|
package/dist/cli.js
ADDED
|
@@ -0,0 +1,409 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
4
|
+
if (k2 === undefined) k2 = k;
|
|
5
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
6
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
7
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
8
|
+
}
|
|
9
|
+
Object.defineProperty(o, k2, desc);
|
|
10
|
+
}) : (function(o, m, k, k2) {
|
|
11
|
+
if (k2 === undefined) k2 = k;
|
|
12
|
+
o[k2] = m[k];
|
|
13
|
+
}));
|
|
14
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
15
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
16
|
+
}) : function(o, v) {
|
|
17
|
+
o["default"] = v;
|
|
18
|
+
});
|
|
19
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
20
|
+
var ownKeys = function(o) {
|
|
21
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
22
|
+
var ar = [];
|
|
23
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
24
|
+
return ar;
|
|
25
|
+
};
|
|
26
|
+
return ownKeys(o);
|
|
27
|
+
};
|
|
28
|
+
return function (mod) {
|
|
29
|
+
if (mod && mod.__esModule) return mod;
|
|
30
|
+
var result = {};
|
|
31
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
32
|
+
__setModuleDefault(result, mod);
|
|
33
|
+
return result;
|
|
34
|
+
};
|
|
35
|
+
})();
|
|
36
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
37
|
+
const fs = __importStar(require("fs"));
|
|
38
|
+
const path = __importStar(require("path"));
|
|
39
|
+
const os = __importStar(require("os"));
|
|
40
|
+
const crypto = __importStar(require("crypto"));
|
|
41
|
+
const readline = __importStar(require("readline"));
|
|
42
|
+
const CLAWGUARD_DIR = path.join(os.homedir(), ".clawguard");
|
|
43
|
+
const LITE_DIR = path.join(os.homedir(), ".averecion-lite");
|
|
44
|
+
const CONFIG_FILE = path.join(CLAWGUARD_DIR, "config.json");
|
|
45
|
+
const POLICY_FILE = path.join(CLAWGUARD_DIR, "policy.json");
|
|
46
|
+
const AGENTS_DIR = path.join(CLAWGUARD_DIR, "agents");
|
|
47
|
+
const PENDING_DIR = path.join(CLAWGUARD_DIR, "pending");
|
|
48
|
+
const OPENCLAW_PATHS = [
|
|
49
|
+
"openclaw.config.ts",
|
|
50
|
+
"openclaw.config.js",
|
|
51
|
+
".openclaw/config.ts",
|
|
52
|
+
".openclaw/config.js",
|
|
53
|
+
"config/openclaw.ts",
|
|
54
|
+
"config/openclaw.js",
|
|
55
|
+
];
|
|
56
|
+
const HOOK_CODE = `
|
|
57
|
+
// Averecion Lite - AI Safety for OpenClaw
|
|
58
|
+
import { createOpenClawHook, initLiteAdapter } from "averecion-lite";
|
|
59
|
+
await initLiteAdapter();
|
|
60
|
+
openclaw.registerHook(await createOpenClawHook());
|
|
61
|
+
`;
|
|
62
|
+
function log(msg) { console.log(`🦞 ${msg}`); }
|
|
63
|
+
function success(msg) { console.log(`✅ ${msg}`); }
|
|
64
|
+
function warn(msg) { console.log(`⚠️ ${msg}`); }
|
|
65
|
+
async function prompt(question) {
|
|
66
|
+
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
67
|
+
return new Promise(resolve => {
|
|
68
|
+
rl.question(question, answer => { rl.close(); resolve(answer.trim()); });
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
function ensureDir() {
|
|
72
|
+
if (!fs.existsSync(CLAWGUARD_DIR)) {
|
|
73
|
+
fs.mkdirSync(CLAWGUARD_DIR, { recursive: true });
|
|
74
|
+
}
|
|
75
|
+
if (!fs.existsSync(AGENTS_DIR)) {
|
|
76
|
+
fs.mkdirSync(AGENTS_DIR, { recursive: true });
|
|
77
|
+
}
|
|
78
|
+
if (!fs.existsSync(PENDING_DIR)) {
|
|
79
|
+
fs.mkdirSync(PENDING_DIR, { recursive: true });
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
function generateSecret() {
|
|
83
|
+
return crypto.randomBytes(32).toString("hex");
|
|
84
|
+
}
|
|
85
|
+
function findOpenClawConfig() {
|
|
86
|
+
for (const p of OPENCLAW_PATHS) {
|
|
87
|
+
if (fs.existsSync(p))
|
|
88
|
+
return p;
|
|
89
|
+
}
|
|
90
|
+
return null;
|
|
91
|
+
}
|
|
92
|
+
function createDefaultPolicy() {
|
|
93
|
+
const policy = {
|
|
94
|
+
allowedSkills: ["email.send", "calendar.create", "web.get", "file.read"],
|
|
95
|
+
highRiskActions: ["shell.exec", "file.write", "network.post", "delete.*", "wallet.tx"],
|
|
96
|
+
blockUnknownSkills: true
|
|
97
|
+
};
|
|
98
|
+
fs.writeFileSync(POLICY_FILE, JSON.stringify(policy, null, 2));
|
|
99
|
+
}
|
|
100
|
+
async function init() {
|
|
101
|
+
console.log("");
|
|
102
|
+
console.log("╔════════════════════════════════════════╗");
|
|
103
|
+
console.log("║ 🛡️ Clawguard v1.1.0 ║");
|
|
104
|
+
console.log("║ AI Safety for ClawdBot ║");
|
|
105
|
+
console.log("╚════════════════════════════════════════╝");
|
|
106
|
+
console.log("");
|
|
107
|
+
ensureDir();
|
|
108
|
+
// Step 1: Generate secret
|
|
109
|
+
log("Generating your secret key...");
|
|
110
|
+
const secret = generateSecret();
|
|
111
|
+
const config = { secret, createdAt: new Date().toISOString() };
|
|
112
|
+
fs.writeFileSync(CONFIG_FILE, JSON.stringify(config, null, 2));
|
|
113
|
+
success("Secret key created and saved!");
|
|
114
|
+
console.log("");
|
|
115
|
+
// Step 2: Create default policy
|
|
116
|
+
if (!fs.existsSync(POLICY_FILE)) {
|
|
117
|
+
log("Creating default safety policy...");
|
|
118
|
+
createDefaultPolicy();
|
|
119
|
+
success("Safety policy created!");
|
|
120
|
+
}
|
|
121
|
+
else {
|
|
122
|
+
log("Using existing safety policy");
|
|
123
|
+
}
|
|
124
|
+
console.log("");
|
|
125
|
+
// Step 3: Show ClawdBot integration options
|
|
126
|
+
log("Clawguard works with all ClawdBot extension types:");
|
|
127
|
+
console.log("");
|
|
128
|
+
console.log(" • Skills - Monitors skill executions");
|
|
129
|
+
console.log(" • Tools - Governs MCP tool calls");
|
|
130
|
+
console.log(" • Plugins - Tracks plugin actions");
|
|
131
|
+
console.log(" • Bash/Shell - Intercepts command execution");
|
|
132
|
+
console.log("");
|
|
133
|
+
// Step 4: Set environment variable
|
|
134
|
+
console.log("");
|
|
135
|
+
log("Add this to your shell profile (~/.bashrc or ~/.zshrc):");
|
|
136
|
+
console.log("");
|
|
137
|
+
console.log(` export CLAWGUARD_SECRET="${secret}"`);
|
|
138
|
+
console.log("");
|
|
139
|
+
// Step 5: Done!
|
|
140
|
+
console.log("╔════════════════════════════════════════╗");
|
|
141
|
+
console.log("║ 🎉 Setup complete! ║");
|
|
142
|
+
console.log("╚════════════════════════════════════════╝");
|
|
143
|
+
console.log("");
|
|
144
|
+
console.log("Next steps:");
|
|
145
|
+
console.log(" 1. Start the dashboard: clawguard start");
|
|
146
|
+
console.log(" 2. Configure your ClawdBot extensions in the dashboard");
|
|
147
|
+
console.log(" 3. Open http://127.0.0.1:4321/clawguard");
|
|
148
|
+
console.log("");
|
|
149
|
+
console.log("Need help? Visit https://averecion.com/docs/clawguard");
|
|
150
|
+
console.log("");
|
|
151
|
+
}
|
|
152
|
+
async function start() {
|
|
153
|
+
ensureDir();
|
|
154
|
+
if (!fs.existsSync(CONFIG_FILE)) {
|
|
155
|
+
warn("Not set up yet. Running setup first...");
|
|
156
|
+
await init();
|
|
157
|
+
}
|
|
158
|
+
const config = JSON.parse(fs.readFileSync(CONFIG_FILE, "utf-8"));
|
|
159
|
+
process.env.LITE_ADAPTER_SECRET = config.secret;
|
|
160
|
+
log("Starting Averecion Lite...");
|
|
161
|
+
const { initLiteAdapter } = await Promise.resolve().then(() => __importStar(require("./index")));
|
|
162
|
+
await initLiteAdapter({ enableCLIConfirm: true });
|
|
163
|
+
console.log("");
|
|
164
|
+
success("Dashboard ready at http://127.0.0.1:4321/clawguard");
|
|
165
|
+
console.log("");
|
|
166
|
+
}
|
|
167
|
+
async function status() {
|
|
168
|
+
ensureDir();
|
|
169
|
+
if (!fs.existsSync(CONFIG_FILE)) {
|
|
170
|
+
warn("Not set up yet. Run: npx averecion-lite init");
|
|
171
|
+
return;
|
|
172
|
+
}
|
|
173
|
+
const config = JSON.parse(fs.readFileSync(CONFIG_FILE, "utf-8"));
|
|
174
|
+
console.log("");
|
|
175
|
+
console.log("🦞 Averecion Lite Status");
|
|
176
|
+
console.log("────────────────────────");
|
|
177
|
+
console.log(` Config: ${CONFIG_FILE}`);
|
|
178
|
+
console.log(` Created: ${config.createdAt}`);
|
|
179
|
+
console.log(` Secret: ${config.secret.slice(0, 8)}...`);
|
|
180
|
+
console.log("");
|
|
181
|
+
}
|
|
182
|
+
async function agents() {
|
|
183
|
+
if (!fs.existsSync(AGENTS_DIR)) {
|
|
184
|
+
warn("No agents registered yet.");
|
|
185
|
+
console.log("Register an agent with: clawguard agent register <manifest.json>");
|
|
186
|
+
return;
|
|
187
|
+
}
|
|
188
|
+
const files = fs.readdirSync(AGENTS_DIR).filter(f => f.endsWith(".json"));
|
|
189
|
+
if (files.length === 0) {
|
|
190
|
+
warn("No agents registered yet.");
|
|
191
|
+
return;
|
|
192
|
+
}
|
|
193
|
+
console.log("");
|
|
194
|
+
console.log("🤖 Registered Agents");
|
|
195
|
+
console.log("────────────────────");
|
|
196
|
+
for (const file of files) {
|
|
197
|
+
try {
|
|
198
|
+
const agent = JSON.parse(fs.readFileSync(path.join(AGENTS_DIR, file), "utf-8"));
|
|
199
|
+
const capCount = agent.capabilities?.length || 0;
|
|
200
|
+
const riskIndicator = capCount > 5 ? "🔴" : capCount > 3 ? "🟡" : "🟢";
|
|
201
|
+
console.log(` ${riskIndicator} ${agent.name} (${agent.id})`);
|
|
202
|
+
console.log(` Capabilities: ${capCount}`);
|
|
203
|
+
console.log(` Framework: ${agent.framework || "custom"}`);
|
|
204
|
+
console.log(` Registered: ${agent.registeredAt}`);
|
|
205
|
+
console.log("");
|
|
206
|
+
}
|
|
207
|
+
catch { }
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
async function registerAgentFromFile(manifestPath) {
|
|
211
|
+
if (!fs.existsSync(manifestPath)) {
|
|
212
|
+
warn(`File not found: ${manifestPath}`);
|
|
213
|
+
return;
|
|
214
|
+
}
|
|
215
|
+
const { registerAgentFromManifest } = await Promise.resolve().then(() => __importStar(require("./src/capability-manifest")));
|
|
216
|
+
const result = registerAgentFromManifest(manifestPath);
|
|
217
|
+
if (!result.success) {
|
|
218
|
+
warn(`Failed to register agent: ${result.error}`);
|
|
219
|
+
return;
|
|
220
|
+
}
|
|
221
|
+
success(`Registered agent: ${result.manifest?.name}`);
|
|
222
|
+
console.log("");
|
|
223
|
+
console.log("Risk Assessment:");
|
|
224
|
+
console.log(` Overall Score: ${result.risk?.overallScore}/100`);
|
|
225
|
+
console.log(` Risk Level: ${result.risk?.riskLevel?.toUpperCase()}`);
|
|
226
|
+
if (result.risk?.recommendations?.length) {
|
|
227
|
+
console.log("");
|
|
228
|
+
console.log("Recommendations:");
|
|
229
|
+
for (const rec of result.risk.recommendations) {
|
|
230
|
+
console.log(` • ${rec}`);
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
console.log("");
|
|
234
|
+
}
|
|
235
|
+
async function installShellWrapper() {
|
|
236
|
+
const wrapperScript = `#!/bin/bash
|
|
237
|
+
# Clawguard Shell Wrapper
|
|
238
|
+
# Intercepts commands and applies governance policies
|
|
239
|
+
|
|
240
|
+
CLAWGUARD_REAL_SHELL="\${CLAWGUARD_REAL_SHELL:-/bin/bash}"
|
|
241
|
+
|
|
242
|
+
if [ -z "$1" ]; then
|
|
243
|
+
exec "$CLAWGUARD_REAL_SHELL"
|
|
244
|
+
else
|
|
245
|
+
node "${path.join(__dirname, "src", "shell-wrapper.js")}" "$@"
|
|
246
|
+
fi
|
|
247
|
+
`;
|
|
248
|
+
const binDir = path.join(os.homedir(), ".local", "bin");
|
|
249
|
+
const wrapperPath = path.join(binDir, "clawguard-sh");
|
|
250
|
+
if (!fs.existsSync(binDir)) {
|
|
251
|
+
fs.mkdirSync(binDir, { recursive: true });
|
|
252
|
+
}
|
|
253
|
+
fs.writeFileSync(wrapperPath, wrapperScript);
|
|
254
|
+
fs.chmodSync(wrapperPath, "755");
|
|
255
|
+
success(`Shell wrapper installed: ${wrapperPath}`);
|
|
256
|
+
console.log("");
|
|
257
|
+
console.log("To enable for an agent, set:");
|
|
258
|
+
console.log(` SHELL=${wrapperPath}`);
|
|
259
|
+
console.log("");
|
|
260
|
+
console.log("Or add to your profile (~/.bashrc):");
|
|
261
|
+
console.log(` export PATH="$HOME/.local/bin:$PATH"`);
|
|
262
|
+
console.log("");
|
|
263
|
+
}
|
|
264
|
+
async function pending() {
|
|
265
|
+
if (!fs.existsSync(PENDING_DIR)) {
|
|
266
|
+
log("No pending approvals.");
|
|
267
|
+
return;
|
|
268
|
+
}
|
|
269
|
+
const files = fs.readdirSync(PENDING_DIR).filter(f => f.endsWith(".json"));
|
|
270
|
+
const pendingItems = files.map(f => {
|
|
271
|
+
try {
|
|
272
|
+
return JSON.parse(fs.readFileSync(path.join(PENDING_DIR, f), "utf-8"));
|
|
273
|
+
}
|
|
274
|
+
catch {
|
|
275
|
+
return null;
|
|
276
|
+
}
|
|
277
|
+
}).filter(p => p && p.status === "pending");
|
|
278
|
+
if (pendingItems.length === 0) {
|
|
279
|
+
log("No pending approvals.");
|
|
280
|
+
return;
|
|
281
|
+
}
|
|
282
|
+
console.log("");
|
|
283
|
+
console.log("⏳ Pending Approvals");
|
|
284
|
+
console.log("────────────────────");
|
|
285
|
+
for (const item of pendingItems) {
|
|
286
|
+
console.log(` ID: ${item.id}`);
|
|
287
|
+
console.log(` Type: ${item.type}`);
|
|
288
|
+
if (item.command)
|
|
289
|
+
console.log(` Command: ${item.command.substring(0, 60)}${item.command.length > 60 ? "..." : ""}`);
|
|
290
|
+
if (item.url)
|
|
291
|
+
console.log(` URL: ${item.url.substring(0, 60)}${item.url.length > 60 ? "..." : ""}`);
|
|
292
|
+
console.log(` Risk: ${item.riskScore}/100`);
|
|
293
|
+
console.log(` Created: ${item.createdAt}`);
|
|
294
|
+
console.log("");
|
|
295
|
+
}
|
|
296
|
+
console.log("To approve: clawguard approve <id>");
|
|
297
|
+
console.log("To deny: clawguard deny <id>");
|
|
298
|
+
console.log("");
|
|
299
|
+
}
|
|
300
|
+
async function approve(id) {
|
|
301
|
+
const filePath = path.join(PENDING_DIR, `${id}.json`);
|
|
302
|
+
if (!fs.existsSync(filePath)) {
|
|
303
|
+
warn(`Approval not found: ${id}`);
|
|
304
|
+
return;
|
|
305
|
+
}
|
|
306
|
+
const approval = JSON.parse(fs.readFileSync(filePath, "utf-8"));
|
|
307
|
+
approval.status = "approved";
|
|
308
|
+
approval.resolvedAt = new Date().toISOString();
|
|
309
|
+
fs.writeFileSync(filePath, JSON.stringify(approval, null, 2));
|
|
310
|
+
success(`Approved: ${id}`);
|
|
311
|
+
}
|
|
312
|
+
async function deny(id) {
|
|
313
|
+
const filePath = path.join(PENDING_DIR, `${id}.json`);
|
|
314
|
+
if (!fs.existsSync(filePath)) {
|
|
315
|
+
warn(`Approval not found: ${id}`);
|
|
316
|
+
return;
|
|
317
|
+
}
|
|
318
|
+
const approval = JSON.parse(fs.readFileSync(filePath, "utf-8"));
|
|
319
|
+
approval.status = "denied";
|
|
320
|
+
approval.resolvedAt = new Date().toISOString();
|
|
321
|
+
fs.writeFileSync(filePath, JSON.stringify(approval, null, 2));
|
|
322
|
+
success(`Denied: ${id}`);
|
|
323
|
+
}
|
|
324
|
+
function showHelp() {
|
|
325
|
+
console.log("");
|
|
326
|
+
console.log("🛡️ Clawguard - Agent-Agnostic AI Governance");
|
|
327
|
+
console.log("");
|
|
328
|
+
console.log("Usage: clawguard <command> [options]");
|
|
329
|
+
console.log("");
|
|
330
|
+
console.log("Commands:");
|
|
331
|
+
console.log(" start Start the dashboard server (default)");
|
|
332
|
+
console.log(" init Set up Clawguard for the first time");
|
|
333
|
+
console.log(" status Check current configuration");
|
|
334
|
+
console.log("");
|
|
335
|
+
console.log("Agent Management:");
|
|
336
|
+
console.log(" agents List registered agents");
|
|
337
|
+
console.log(" agent register <manifest.json> Register an agent from manifest");
|
|
338
|
+
console.log("");
|
|
339
|
+
console.log("Approval Workflow:");
|
|
340
|
+
console.log(" pending Show pending approvals");
|
|
341
|
+
console.log(" approve <id> Approve a pending action");
|
|
342
|
+
console.log(" deny <id> Deny a pending action");
|
|
343
|
+
console.log("");
|
|
344
|
+
console.log("Shell Interception:");
|
|
345
|
+
console.log(" install-shell Install the shell wrapper");
|
|
346
|
+
console.log("");
|
|
347
|
+
console.log("Examples:");
|
|
348
|
+
console.log(" clawguard start");
|
|
349
|
+
console.log(" clawguard agent register ./my-agent.json");
|
|
350
|
+
console.log(" clawguard approve 1234567890-abc123");
|
|
351
|
+
console.log("");
|
|
352
|
+
}
|
|
353
|
+
// CLI entry point
|
|
354
|
+
const command = process.argv[2] || "start";
|
|
355
|
+
const subcommand = process.argv[3];
|
|
356
|
+
const arg = process.argv[4];
|
|
357
|
+
switch (command) {
|
|
358
|
+
case "init":
|
|
359
|
+
case "setup":
|
|
360
|
+
init().catch(console.error);
|
|
361
|
+
break;
|
|
362
|
+
case "start":
|
|
363
|
+
case "run":
|
|
364
|
+
start().catch(console.error);
|
|
365
|
+
break;
|
|
366
|
+
case "status":
|
|
367
|
+
status().catch(console.error);
|
|
368
|
+
break;
|
|
369
|
+
case "agents":
|
|
370
|
+
agents().catch(console.error);
|
|
371
|
+
break;
|
|
372
|
+
case "agent":
|
|
373
|
+
if (subcommand === "register" && arg) {
|
|
374
|
+
registerAgentFromFile(arg).catch(console.error);
|
|
375
|
+
}
|
|
376
|
+
else {
|
|
377
|
+
console.log("Usage: clawguard agent register <manifest.json>");
|
|
378
|
+
}
|
|
379
|
+
break;
|
|
380
|
+
case "pending":
|
|
381
|
+
pending().catch(console.error);
|
|
382
|
+
break;
|
|
383
|
+
case "approve":
|
|
384
|
+
if (subcommand) {
|
|
385
|
+
approve(subcommand).catch(console.error);
|
|
386
|
+
}
|
|
387
|
+
else {
|
|
388
|
+
console.log("Usage: clawguard approve <id>");
|
|
389
|
+
}
|
|
390
|
+
break;
|
|
391
|
+
case "deny":
|
|
392
|
+
if (subcommand) {
|
|
393
|
+
deny(subcommand).catch(console.error);
|
|
394
|
+
}
|
|
395
|
+
else {
|
|
396
|
+
console.log("Usage: clawguard deny <id>");
|
|
397
|
+
}
|
|
398
|
+
break;
|
|
399
|
+
case "install-shell":
|
|
400
|
+
installShellWrapper().catch(console.error);
|
|
401
|
+
break;
|
|
402
|
+
case "help":
|
|
403
|
+
case "--help":
|
|
404
|
+
case "-h":
|
|
405
|
+
showHelp();
|
|
406
|
+
break;
|
|
407
|
+
default:
|
|
408
|
+
showHelp();
|
|
409
|
+
}
|
package/dist/hooks.d.ts
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
export interface ActionPayload {
|
|
2
|
+
tool: string;
|
|
3
|
+
plan?: string;
|
|
4
|
+
args: Record<string, unknown>;
|
|
5
|
+
egress?: string[];
|
|
6
|
+
inputTokens?: number;
|
|
7
|
+
outputTokens?: number;
|
|
8
|
+
estimatedUSD?: number;
|
|
9
|
+
}
|
|
10
|
+
export interface BeforeActionResult {
|
|
11
|
+
allowed: boolean;
|
|
12
|
+
decision: "approved" | "blocked";
|
|
13
|
+
reason: string;
|
|
14
|
+
injectionDetected?: boolean;
|
|
15
|
+
}
|
|
16
|
+
type ConfirmHandler = (req: {
|
|
17
|
+
tool: string;
|
|
18
|
+
reason: string;
|
|
19
|
+
payload: Record<string, unknown>;
|
|
20
|
+
}) => Promise<boolean>;
|
|
21
|
+
export declare function setConfirmHandler(h: ConfirmHandler): void;
|
|
22
|
+
export declare function beforeAction(payload: ActionPayload): Promise<BeforeActionResult>;
|
|
23
|
+
export declare function afterAction(payload: ActionPayload, result: BeforeActionResult): Promise<void>;
|
|
24
|
+
export {};
|
|
25
|
+
//# sourceMappingURL=hooks.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hooks.d.ts","sourceRoot":"","sources":["../hooks.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,aAAa;IAAG,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAAC,YAAY,CAAC,EAAE,MAAM,CAAC;IAAC,YAAY,CAAC,EAAE,MAAM,CAAC;CAAE;AACrL,MAAM,WAAW,kBAAkB;IAAG,OAAO,EAAE,OAAO,CAAC;IAAC,QAAQ,EAAE,UAAU,GAAG,SAAS,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,iBAAiB,CAAC,EAAE,OAAO,CAAC;CAAE;AAExI,KAAK,cAAc,GAAG,CAAC,GAAG,EAAE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAAE,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;AAEpH,wBAAgB,iBAAiB,CAAC,CAAC,EAAE,cAAc,QAAyB;AAe5E,wBAAsB,YAAY,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,kBAAkB,CAAC,CA8BtF;AAED,wBAAsB,WAAW,CAAC,OAAO,EAAE,aAAa,EAAE,MAAM,EAAE,kBAAkB,iBAKnF"}
|
package/dist/hooks.js
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.setConfirmHandler = setConfirmHandler;
|
|
4
|
+
exports.beforeAction = beforeAction;
|
|
5
|
+
exports.afterAction = afterAction;
|
|
6
|
+
const policy_1 = require("./policy");
|
|
7
|
+
const injectionGuard_1 = require("./injectionGuard");
|
|
8
|
+
const storage_1 = require("./storage");
|
|
9
|
+
const metrics_1 = require("./metrics");
|
|
10
|
+
let confirmHandler = null;
|
|
11
|
+
function setConfirmHandler(h) { confirmHandler = h; }
|
|
12
|
+
async function confirm(tool, reason, args) {
|
|
13
|
+
if (!confirmHandler) {
|
|
14
|
+
console.log(`[Averecion Lite] Confirmation required for ${tool}: ${reason}. Auto-denying.`);
|
|
15
|
+
return false;
|
|
16
|
+
}
|
|
17
|
+
try {
|
|
18
|
+
return await Promise.race([confirmHandler({ tool, reason, payload: args }), new Promise((_, rej) => setTimeout(() => rej(), 30000))]);
|
|
19
|
+
}
|
|
20
|
+
catch {
|
|
21
|
+
return false;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
function extractEgress(payload) {
|
|
25
|
+
const hosts = [...(payload.egress || [])];
|
|
26
|
+
const match = JSON.stringify(payload.args).matchAll(/https?:\/\/([^\/\s"']+)/g);
|
|
27
|
+
for (const m of match)
|
|
28
|
+
if (!hosts.includes(m[1]))
|
|
29
|
+
hosts.push(m[1]);
|
|
30
|
+
return hosts;
|
|
31
|
+
}
|
|
32
|
+
async function beforeAction(payload) {
|
|
33
|
+
const { tool, plan = "", args } = payload;
|
|
34
|
+
const egress = extractEgress(payload);
|
|
35
|
+
const inj = (0, injectionGuard_1.scanPlanAndArgs)(plan, args);
|
|
36
|
+
if (inj.detected) {
|
|
37
|
+
(0, metrics_1.incrementMetric)("promptInjectionDetected");
|
|
38
|
+
(0, metrics_1.incrementMetric)("highRiskIntercepts");
|
|
39
|
+
if (!await confirm(tool, `Prompt injection: ${inj.matches.join(", ")}`, args)) {
|
|
40
|
+
(0, metrics_1.incrementMetric)("blocked");
|
|
41
|
+
(0, storage_1.appendEvent)({ ts: new Date().toISOString(), tool, decision: "blocked", reason: `promptInjection: ${inj.matches.join(", ")}`, egress, inputTokens: payload.inputTokens, outputTokens: payload.outputTokens, estimatedUSD: payload.estimatedUSD });
|
|
42
|
+
return { allowed: false, decision: "blocked", reason: "promptInjection", injectionDetected: true };
|
|
43
|
+
}
|
|
44
|
+
(0, metrics_1.incrementMetric)("manualApproved");
|
|
45
|
+
}
|
|
46
|
+
const cls = (0, policy_1.classifyAction)(tool);
|
|
47
|
+
if (cls.decision === "approved")
|
|
48
|
+
return { allowed: true, decision: "approved", reason: cls.reason };
|
|
49
|
+
if (cls.decision === "blocked") {
|
|
50
|
+
(0, metrics_1.incrementMetric)("blocked");
|
|
51
|
+
(0, storage_1.appendEvent)({ ts: new Date().toISOString(), tool, decision: "blocked", reason: cls.reason, egress, inputTokens: payload.inputTokens, outputTokens: payload.outputTokens, estimatedUSD: payload.estimatedUSD });
|
|
52
|
+
return { allowed: false, decision: "blocked", reason: cls.reason };
|
|
53
|
+
}
|
|
54
|
+
(0, metrics_1.incrementMetric)("highRiskIntercepts");
|
|
55
|
+
if (!await confirm(tool, cls.reason, args)) {
|
|
56
|
+
(0, metrics_1.incrementMetric)("blocked");
|
|
57
|
+
(0, storage_1.appendEvent)({ ts: new Date().toISOString(), tool, decision: "blocked", reason: "manualDenied", egress, inputTokens: payload.inputTokens, outputTokens: payload.outputTokens, estimatedUSD: payload.estimatedUSD });
|
|
58
|
+
return { allowed: false, decision: "blocked", reason: "manualDenied" };
|
|
59
|
+
}
|
|
60
|
+
(0, metrics_1.incrementMetric)("manualApproved");
|
|
61
|
+
return { allowed: true, decision: "approved", reason: "manualApproval" };
|
|
62
|
+
}
|
|
63
|
+
async function afterAction(payload, result) {
|
|
64
|
+
if (result.allowed) {
|
|
65
|
+
(0, metrics_1.incrementMetric)("approved");
|
|
66
|
+
(0, storage_1.appendEvent)({ ts: new Date().toISOString(), tool: payload.tool, decision: result.reason === "manualApproval" ? "manual" : "approved", reason: result.reason, egress: extractEgress(payload), inputTokens: payload.inputTokens, outputTokens: payload.outputTokens, estimatedUSD: payload.estimatedUSD });
|
|
67
|
+
}
|
|
68
|
+
}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { ActionPayload, BeforeActionResult } from "./hooks";
|
|
2
|
+
export { beforeAction, afterAction, setConfirmHandler } from "./hooks";
|
|
3
|
+
export { loadPolicy, classifyAction } from "./policy";
|
|
4
|
+
export { scanForInjection, scanPlanAndArgs } from "./injectionGuard";
|
|
5
|
+
export { appendEvent, getEvents, getLastEvents } from "./storage";
|
|
6
|
+
export { getMetrics, incrementMetric } from "./metrics";
|
|
7
|
+
export { startServer, stopServer } from "./server";
|
|
8
|
+
export type { ActionPayload, BeforeActionResult } from "./hooks";
|
|
9
|
+
export type { LitePolicy } from "./policy";
|
|
10
|
+
export type { LiteMetrics } from "./metrics";
|
|
11
|
+
export type { ActionEvent } from "./storage";
|
|
12
|
+
export interface LiteAdapterConfig {
|
|
13
|
+
port?: number;
|
|
14
|
+
host?: string;
|
|
15
|
+
enableCLIConfirm?: boolean;
|
|
16
|
+
policyPath?: string;
|
|
17
|
+
}
|
|
18
|
+
export declare function initLiteAdapter(config?: LiteAdapterConfig): Promise<void>;
|
|
19
|
+
export declare function createOpenClawHook(hookSecret?: string): Promise<{
|
|
20
|
+
name: string;
|
|
21
|
+
beforeToolCall(tool: string, args: Record<string, unknown>, ctx?: {
|
|
22
|
+
plan?: string;
|
|
23
|
+
secret?: string;
|
|
24
|
+
}): Promise<{
|
|
25
|
+
proceed: boolean;
|
|
26
|
+
payload: ActionPayload;
|
|
27
|
+
result: BeforeActionResult;
|
|
28
|
+
}>;
|
|
29
|
+
afterToolCall(data: {
|
|
30
|
+
payload: ActionPayload;
|
|
31
|
+
result: BeforeActionResult;
|
|
32
|
+
}): Promise<void>;
|
|
33
|
+
}>;
|
|
34
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AAAA,OAAO,EAA6B,aAAa,EAAE,kBAAkB,EAAqB,MAAM,SAAS,CAAC;AAI1G,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAC;AACvE,OAAO,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AACtD,OAAO,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AACrE,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAClE,OAAO,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AACxD,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AACnD,YAAY,EAAE,aAAa,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAC;AACjE,YAAY,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAC3C,YAAY,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAC7C,YAAY,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAE7C,MAAM,WAAW,iBAAiB;IAAG,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAAC,UAAU,CAAC,EAAE,MAAM,CAAC;CAAE;AAGrH,wBAAsB,eAAe,CAAC,MAAM,GAAE,iBAAsB,iBAgBnE;AAED,wBAAsB,kBAAkB,CAAC,UAAU,CAAC,EAAE,MAAM;;yBAI7B,MAAM,QAAQ,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,QAAQ;QAAE,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE;;;;;wBAOhF;QAAE,OAAO,EAAE,aAAa,CAAC;QAAC,MAAM,EAAE,kBAAkB,CAAA;KAAE;GAEnF"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.stopServer = exports.startServer = exports.incrementMetric = exports.getMetrics = exports.getLastEvents = exports.getEvents = exports.appendEvent = exports.scanPlanAndArgs = exports.scanForInjection = exports.classifyAction = exports.loadPolicy = exports.setConfirmHandler = exports.afterAction = exports.beforeAction = void 0;
|
|
4
|
+
exports.initLiteAdapter = initLiteAdapter;
|
|
5
|
+
exports.createOpenClawHook = createOpenClawHook;
|
|
6
|
+
const hooks_1 = require("./hooks");
|
|
7
|
+
const policy_1 = require("./policy");
|
|
8
|
+
const server_1 = require("./server");
|
|
9
|
+
var hooks_2 = require("./hooks");
|
|
10
|
+
Object.defineProperty(exports, "beforeAction", { enumerable: true, get: function () { return hooks_2.beforeAction; } });
|
|
11
|
+
Object.defineProperty(exports, "afterAction", { enumerable: true, get: function () { return hooks_2.afterAction; } });
|
|
12
|
+
Object.defineProperty(exports, "setConfirmHandler", { enumerable: true, get: function () { return hooks_2.setConfirmHandler; } });
|
|
13
|
+
var policy_2 = require("./policy");
|
|
14
|
+
Object.defineProperty(exports, "loadPolicy", { enumerable: true, get: function () { return policy_2.loadPolicy; } });
|
|
15
|
+
Object.defineProperty(exports, "classifyAction", { enumerable: true, get: function () { return policy_2.classifyAction; } });
|
|
16
|
+
var injectionGuard_1 = require("./injectionGuard");
|
|
17
|
+
Object.defineProperty(exports, "scanForInjection", { enumerable: true, get: function () { return injectionGuard_1.scanForInjection; } });
|
|
18
|
+
Object.defineProperty(exports, "scanPlanAndArgs", { enumerable: true, get: function () { return injectionGuard_1.scanPlanAndArgs; } });
|
|
19
|
+
var storage_1 = require("./storage");
|
|
20
|
+
Object.defineProperty(exports, "appendEvent", { enumerable: true, get: function () { return storage_1.appendEvent; } });
|
|
21
|
+
Object.defineProperty(exports, "getEvents", { enumerable: true, get: function () { return storage_1.getEvents; } });
|
|
22
|
+
Object.defineProperty(exports, "getLastEvents", { enumerable: true, get: function () { return storage_1.getLastEvents; } });
|
|
23
|
+
var metrics_1 = require("./metrics");
|
|
24
|
+
Object.defineProperty(exports, "getMetrics", { enumerable: true, get: function () { return metrics_1.getMetrics; } });
|
|
25
|
+
Object.defineProperty(exports, "incrementMetric", { enumerable: true, get: function () { return metrics_1.incrementMetric; } });
|
|
26
|
+
var server_2 = require("./server");
|
|
27
|
+
Object.defineProperty(exports, "startServer", { enumerable: true, get: function () { return server_2.startServer; } });
|
|
28
|
+
Object.defineProperty(exports, "stopServer", { enumerable: true, get: function () { return server_2.stopServer; } });
|
|
29
|
+
let initialized = false;
|
|
30
|
+
async function initLiteAdapter(config = {}) {
|
|
31
|
+
if (initialized)
|
|
32
|
+
return;
|
|
33
|
+
if (!process.env.LITE_ADAPTER_SECRET)
|
|
34
|
+
console.error("[Averecion Lite] WARNING: LITE_ADAPTER_SECRET not set");
|
|
35
|
+
(0, policy_1.loadPolicy)(config.policyPath);
|
|
36
|
+
if (config.enableCLIConfirm) {
|
|
37
|
+
const readline = require("readline");
|
|
38
|
+
(0, hooks_1.setConfirmHandler)(async (req) => {
|
|
39
|
+
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
40
|
+
return new Promise(resolve => {
|
|
41
|
+
console.log(`\n[Confirm] ${req.tool}: ${req.reason}`);
|
|
42
|
+
rl.question("Approve? (y/n): ", (a) => { rl.close(); resolve(a.toLowerCase() === "y"); });
|
|
43
|
+
});
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
await (0, server_1.startServer)(config.port || 4321, config.host || "127.0.0.1");
|
|
47
|
+
initialized = true;
|
|
48
|
+
}
|
|
49
|
+
async function createOpenClawHook(hookSecret) {
|
|
50
|
+
const expected = hookSecret || process.env.LITE_ADAPTER_SECRET;
|
|
51
|
+
return {
|
|
52
|
+
name: "averecion-lite",
|
|
53
|
+
async beforeToolCall(tool, args, ctx) {
|
|
54
|
+
if (expected && ctx?.secret !== expected)
|
|
55
|
+
throw new Error("[Averecion Lite] Invalid hook secret");
|
|
56
|
+
const payload = { tool, plan: ctx?.plan || "", args };
|
|
57
|
+
const result = await (0, hooks_1.beforeAction)(payload);
|
|
58
|
+
if (!result.allowed)
|
|
59
|
+
throw new Error(`[Averecion Lite] Blocked: ${result.reason}`);
|
|
60
|
+
return { proceed: true, payload, result };
|
|
61
|
+
},
|
|
62
|
+
async afterToolCall(data) { await (0, hooks_1.afterAction)(data.payload, data.result); }
|
|
63
|
+
};
|
|
64
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export declare function scanForInjection(text: string): {
|
|
2
|
+
detected: boolean;
|
|
3
|
+
matches: string[];
|
|
4
|
+
};
|
|
5
|
+
export declare function scanPlanAndArgs(plan: string, args: Record<string, unknown>): {
|
|
6
|
+
detected: boolean;
|
|
7
|
+
matches: string[];
|
|
8
|
+
};
|
|
9
|
+
//# sourceMappingURL=injectionGuard.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"injectionGuard.d.ts","sourceRoot":"","sources":["../injectionGuard.ts"],"names":[],"mappings":"AAMA,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG;IAAE,QAAQ,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,MAAM,EAAE,CAAA;CAAE,CAGvF;AAED,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;cALf,OAAO;aAAW,MAAM,EAAE;EAOrF"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.scanForInjection = scanForInjection;
|
|
4
|
+
exports.scanPlanAndArgs = scanPlanAndArgs;
|
|
5
|
+
const PATTERNS = [
|
|
6
|
+
/ignore\s+(previous|prior|all)\s+instructions/i, /exfiltrate/i, /upload\s+(secrets?|keys?|credentials?)/i,
|
|
7
|
+
/send\s+(all\s+)?(api\s*keys?|secrets?)\s+to/i, /curl\s+http/i, /wget\s+http/i, /rm\s+-rf/i,
|
|
8
|
+
/drop\s+(table|database)/i, /reverse\s*shell/i, /nc\s+-e/i, /bash\s+-i/i
|
|
9
|
+
];
|
|
10
|
+
function scanForInjection(text) {
|
|
11
|
+
const matches = PATTERNS.map(p => text.match(p)?.[0]).filter(Boolean);
|
|
12
|
+
return { detected: matches.length > 0, matches };
|
|
13
|
+
}
|
|
14
|
+
function scanPlanAndArgs(plan, args) {
|
|
15
|
+
return scanForInjection(plan + " " + JSON.stringify(args));
|
|
16
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { EventEmitter } from "events";
|
|
2
|
+
export declare class LogWatcher extends EventEmitter {
|
|
3
|
+
private watchedFile;
|
|
4
|
+
private watcher;
|
|
5
|
+
private filePosition;
|
|
6
|
+
private activeRuns;
|
|
7
|
+
private pollInterval;
|
|
8
|
+
constructor();
|
|
9
|
+
start(): void;
|
|
10
|
+
stop(): void;
|
|
11
|
+
private getCurrentLogFile;
|
|
12
|
+
private checkForLogFile;
|
|
13
|
+
private watchFile;
|
|
14
|
+
private scheduleRewatch;
|
|
15
|
+
private readNewLines;
|
|
16
|
+
private processLine;
|
|
17
|
+
private parseLogLine;
|
|
18
|
+
private extractToolArgs;
|
|
19
|
+
private handleToolEvent;
|
|
20
|
+
private analyzeDanger;
|
|
21
|
+
private analyzeInjection;
|
|
22
|
+
}
|
|
23
|
+
export declare function startLogWatcher(): LogWatcher;
|
|
24
|
+
export declare function stopLogWatcher(): void;
|
|
25
|
+
export declare function getLogWatcher(): LogWatcher | null;
|
|
26
|
+
//# sourceMappingURL=log-watcher.d.ts.map
|