fastgrc-openclaw 1.0.23 → 1.0.24
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/bin.js +98 -139
- package/dist/bin.mjs +98 -145
- package/package.json +1 -1
package/dist/bin.js
CHANGED
|
@@ -91,64 +91,6 @@ function readConfig() {
|
|
|
91
91
|
function writeConfig(data) {
|
|
92
92
|
fs.writeFileSync(CONFIG_PATH, JSON.stringify(data, null, 2), { mode: 384 });
|
|
93
93
|
}
|
|
94
|
-
var [, , cmd, arg] = process.argv;
|
|
95
|
-
if (cmd === "set-key") {
|
|
96
|
-
if (!arg) {
|
|
97
|
-
process.stderr.write("Usage: fastgrc-hook set-key fgrc_k1_...\n");
|
|
98
|
-
process.exit(1);
|
|
99
|
-
}
|
|
100
|
-
writeConfig({ ...readConfig(), apiKey: arg });
|
|
101
|
-
process.stdout.write(`\u2713 FastGRC API key saved to ${CONFIG_PATH}
|
|
102
|
-
`);
|
|
103
|
-
process.stdout.write(' Run "fastgrc-hook get-key" to verify.\n');
|
|
104
|
-
process.exit(0);
|
|
105
|
-
}
|
|
106
|
-
if (cmd === "get-key") {
|
|
107
|
-
const key = readConfig().apiKey;
|
|
108
|
-
if (!key) {
|
|
109
|
-
process.stdout.write("No key stored. Run: fastgrc-hook set-key fgrc_k1_...\n");
|
|
110
|
-
} else {
|
|
111
|
-
process.stdout.write(`${key.slice(0, 12)}${"*".repeat(Math.max(0, key.length - 12))}
|
|
112
|
-
`);
|
|
113
|
-
}
|
|
114
|
-
process.exit(0);
|
|
115
|
-
}
|
|
116
|
-
if (cmd === "unset-key") {
|
|
117
|
-
const cfg = readConfig();
|
|
118
|
-
delete cfg.apiKey;
|
|
119
|
-
writeConfig(cfg);
|
|
120
|
-
process.stdout.write("FastGRC API key removed.\n");
|
|
121
|
-
process.exit(0);
|
|
122
|
-
}
|
|
123
|
-
if (cmd === "set-policy") {
|
|
124
|
-
if (!arg) {
|
|
125
|
-
process.stderr.write("Usage: fastgrc-hook set-policy <policy-id>\n");
|
|
126
|
-
process.exit(1);
|
|
127
|
-
}
|
|
128
|
-
writeConfig({ ...readConfig(), policyId: arg });
|
|
129
|
-
process.stdout.write(`\u2713 FastGRC policy ID saved to ${CONFIG_PATH}
|
|
130
|
-
`);
|
|
131
|
-
process.stdout.write(' Run "fastgrc-hook get-policy" to verify.\n');
|
|
132
|
-
process.exit(0);
|
|
133
|
-
}
|
|
134
|
-
if (cmd === "get-policy") {
|
|
135
|
-
const id = readConfig().policyId;
|
|
136
|
-
if (!id) {
|
|
137
|
-
process.stdout.write("No policy ID stored \u2014 org-wide default will be used.\n");
|
|
138
|
-
process.stdout.write("Run: fastgrc-hook set-policy <policy-id>\n");
|
|
139
|
-
} else {
|
|
140
|
-
process.stdout.write(`${id}
|
|
141
|
-
`);
|
|
142
|
-
}
|
|
143
|
-
process.exit(0);
|
|
144
|
-
}
|
|
145
|
-
if (cmd === "unset-policy") {
|
|
146
|
-
const cfg = readConfig();
|
|
147
|
-
delete cfg.policyId;
|
|
148
|
-
writeConfig(cfg);
|
|
149
|
-
process.stdout.write("FastGRC policy ID removed \u2014 org-wide default will be used.\n");
|
|
150
|
-
process.exit(0);
|
|
151
|
-
}
|
|
152
94
|
function computeHandler() {
|
|
153
95
|
const binPath = process.argv[1];
|
|
154
96
|
const homeDir = os.homedir();
|
|
@@ -164,30 +106,7 @@ Test it directly (bypasses OpenClaw):
|
|
|
164
106
|
`
|
|
165
107
|
);
|
|
166
108
|
}
|
|
167
|
-
|
|
168
|
-
const { spawn, execSync } = require("child_process");
|
|
169
|
-
try {
|
|
170
|
-
execSync("pkill -x openclaw", { stdio: "ignore" });
|
|
171
|
-
process.stdout.write("Stopped existing openclaw process(es).\n");
|
|
172
|
-
} catch {
|
|
173
|
-
process.stdout.write("No openclaw process was running.\n");
|
|
174
|
-
}
|
|
175
|
-
const logPath = process.env.OPENCLAW_LOG ?? "/tmp/openclaw.log";
|
|
176
|
-
const workDir = arg || process.cwd();
|
|
177
|
-
const out = fs.openSync(logPath, "a");
|
|
178
|
-
const child = spawn("openclaw", [], {
|
|
179
|
-
detached: true,
|
|
180
|
-
stdio: ["ignore", out, out],
|
|
181
|
-
cwd: workDir
|
|
182
|
-
});
|
|
183
|
-
child.unref();
|
|
184
|
-
process.stdout.write(`\u2713 OpenClaw started (PID: ${child.pid}, cwd: ${workDir})
|
|
185
|
-
Logs: tail -f ${logPath}
|
|
186
|
-
`);
|
|
187
|
-
process.exit(0);
|
|
188
|
-
}
|
|
189
|
-
if (cmd === "install-hook") {
|
|
190
|
-
const targetDir = arg || process.cwd();
|
|
109
|
+
function doInstallHook(targetDir) {
|
|
191
110
|
const hookMdPath = path.join(targetDir, "HOOK.md");
|
|
192
111
|
const { handlerStr } = computeHandler();
|
|
193
112
|
const HOOK_ENTRY = ` - matcher: PreToolUse
|
|
@@ -206,7 +125,7 @@ if (cmd === "install-hook") {
|
|
|
206
125
|
Restart OpenClaw \u2014 FastGRC will evaluate every tool call.
|
|
207
126
|
`);
|
|
208
127
|
printTestSnippet(handlerStr);
|
|
209
|
-
|
|
128
|
+
return;
|
|
210
129
|
}
|
|
211
130
|
const existing = fs.readFileSync(hookMdPath, "utf8");
|
|
212
131
|
if (existing.includes(handlerStr)) {
|
|
@@ -214,7 +133,7 @@ Restart OpenClaw \u2014 FastGRC will evaluate every tool call.
|
|
|
214
133
|
Handler: ${handlerStr}
|
|
215
134
|
`);
|
|
216
135
|
printTestSnippet(handlerStr);
|
|
217
|
-
|
|
136
|
+
return;
|
|
218
137
|
}
|
|
219
138
|
if (existing.includes("fastgrc-hook") || existing.includes("fastgrc-openclaw")) {
|
|
220
139
|
const patched = existing.replace(
|
|
@@ -228,7 +147,7 @@ Restart OpenClaw \u2014 FastGRC will evaluate every tool call.
|
|
|
228
147
|
Restart OpenClaw to activate.
|
|
229
148
|
`);
|
|
230
149
|
printTestSnippet(handlerStr);
|
|
231
|
-
|
|
150
|
+
return;
|
|
232
151
|
}
|
|
233
152
|
const fmEnd = existing.indexOf("\n---", 3);
|
|
234
153
|
let updated;
|
|
@@ -247,10 +166,93 @@ ${HOOK_ENTRY}`;
|
|
|
247
166
|
Restart OpenClaw to activate.
|
|
248
167
|
`);
|
|
249
168
|
printTestSnippet(handlerStr);
|
|
169
|
+
}
|
|
170
|
+
function doUninstallHook(targetDir) {
|
|
171
|
+
const hookMdPath = path.join(targetDir, "HOOK.md");
|
|
172
|
+
if (!fs.existsSync(hookMdPath)) {
|
|
173
|
+
process.stdout.write("No HOOK.md found \u2014 nothing to remove.\n");
|
|
174
|
+
return;
|
|
175
|
+
}
|
|
176
|
+
const existing = fs.readFileSync(hookMdPath, "utf8");
|
|
177
|
+
const patched = existing.replace(
|
|
178
|
+
/[ \t]*-[ \t]*matcher:[ \t]*PreToolUse\n[ \t]*handler:[ \t]*"[^"]*(?:fastgrc-hook|fastgrc-openclaw)[^"]*"\n?/,
|
|
179
|
+
""
|
|
180
|
+
);
|
|
181
|
+
if (patched === existing) {
|
|
182
|
+
process.stdout.write("FastGRC hook not found in HOOK.md \u2014 nothing to remove.\n");
|
|
183
|
+
} else {
|
|
184
|
+
fs.writeFileSync(hookMdPath, patched, "utf8");
|
|
185
|
+
process.stdout.write(`\u2713 FastGRC hook removed from ${hookMdPath}
|
|
186
|
+
`);
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
var [, , cmd, arg] = process.argv;
|
|
190
|
+
if (cmd === "set-key") {
|
|
191
|
+
if (!arg) {
|
|
192
|
+
process.stderr.write("Usage: fastgrc-hook set-key fgrc_k1_...\n");
|
|
193
|
+
process.exit(1);
|
|
194
|
+
}
|
|
195
|
+
writeConfig({ ...readConfig(), apiKey: arg });
|
|
196
|
+
process.stdout.write(`\u2713 FastGRC API key saved to ${CONFIG_PATH}
|
|
197
|
+
`);
|
|
198
|
+
process.stdout.write(' Run "fastgrc-hook get-key" to verify.\n');
|
|
199
|
+
process.exit(0);
|
|
200
|
+
}
|
|
201
|
+
if (cmd === "get-key") {
|
|
202
|
+
const key = readConfig().apiKey;
|
|
203
|
+
if (!key) {
|
|
204
|
+
process.stdout.write("No key stored. Run: fastgrc-hook set-key fgrc_k1_...\n");
|
|
205
|
+
} else {
|
|
206
|
+
process.stdout.write(`${key.slice(0, 12)}${"*".repeat(Math.max(0, key.length - 12))}
|
|
207
|
+
`);
|
|
208
|
+
}
|
|
209
|
+
process.exit(0);
|
|
210
|
+
}
|
|
211
|
+
if (cmd === "unset-key") {
|
|
212
|
+
const cfg = readConfig();
|
|
213
|
+
delete cfg.apiKey;
|
|
214
|
+
writeConfig(cfg);
|
|
215
|
+
process.stdout.write("FastGRC API key removed.\n");
|
|
216
|
+
process.exit(0);
|
|
217
|
+
}
|
|
218
|
+
if (cmd === "set-policy") {
|
|
219
|
+
if (!arg) {
|
|
220
|
+
process.stderr.write("Usage: fastgrc-hook set-policy <policy-id>\n");
|
|
221
|
+
process.exit(1);
|
|
222
|
+
}
|
|
223
|
+
writeConfig({ ...readConfig(), policyId: arg });
|
|
224
|
+
process.stdout.write(`\u2713 FastGRC policy ID saved to ${CONFIG_PATH}
|
|
225
|
+
`);
|
|
226
|
+
process.stdout.write(' Run "fastgrc-hook get-policy" to verify.\n');
|
|
227
|
+
process.exit(0);
|
|
228
|
+
}
|
|
229
|
+
if (cmd === "get-policy") {
|
|
230
|
+
const id = readConfig().policyId;
|
|
231
|
+
if (!id) {
|
|
232
|
+
process.stdout.write("No policy ID stored \u2014 org-wide default will be used.\n");
|
|
233
|
+
process.stdout.write("Run: fastgrc-hook set-policy <policy-id>\n");
|
|
234
|
+
} else {
|
|
235
|
+
process.stdout.write(`${id}
|
|
236
|
+
`);
|
|
237
|
+
}
|
|
238
|
+
process.exit(0);
|
|
239
|
+
}
|
|
240
|
+
if (cmd === "unset-policy") {
|
|
241
|
+
const cfg = readConfig();
|
|
242
|
+
delete cfg.policyId;
|
|
243
|
+
writeConfig(cfg);
|
|
244
|
+
process.stdout.write("FastGRC policy ID removed \u2014 org-wide default will be used.\n");
|
|
245
|
+
process.exit(0);
|
|
246
|
+
}
|
|
247
|
+
if (cmd === "install-hook") {
|
|
248
|
+
doInstallHook(arg || process.cwd());
|
|
249
|
+
process.exit(0);
|
|
250
|
+
}
|
|
251
|
+
if (cmd === "uninstall-hook") {
|
|
252
|
+
doUninstallHook(arg || process.cwd());
|
|
250
253
|
process.exit(0);
|
|
251
254
|
}
|
|
252
255
|
if (cmd === "setup") {
|
|
253
|
-
const { execSync } = require("child_process");
|
|
254
256
|
const rest = process.argv.slice(3);
|
|
255
257
|
let apiKeyArg;
|
|
256
258
|
let policyIdArg;
|
|
@@ -269,71 +271,29 @@ if (cmd === "setup") {
|
|
|
269
271
|
process.stderr.write("Usage: fastgrc-hook setup --api-key <key> [--policy-id <id>]\n");
|
|
270
272
|
process.exit(1);
|
|
271
273
|
}
|
|
272
|
-
const selfBin = process.argv[1];
|
|
273
|
-
process.stdout.write("Step 1/4: Installing OpenClaw plugin as root...\n");
|
|
274
|
-
try {
|
|
275
|
-
execSync("sudo openclaw plugins remove fastgrc-openclaw", { stdio: "ignore" });
|
|
276
|
-
} catch {
|
|
277
|
-
}
|
|
278
|
-
execSync("sudo openclaw plugins install fastgrc-openclaw", { stdio: "inherit" });
|
|
279
274
|
writeConfig({ ...readConfig(), apiKey: apiKeyArg });
|
|
280
|
-
process.stdout.write("
|
|
275
|
+
process.stdout.write("\u2713 API key saved to ~/.fastgrc.json\n");
|
|
281
276
|
if (policyIdArg) {
|
|
282
277
|
writeConfig({ ...readConfig(), policyId: policyIdArg });
|
|
283
|
-
process.stdout.write("
|
|
284
|
-
} else {
|
|
285
|
-
process.stdout.write("Step 3/4: No policy ID provided \u2014 org-wide default will be used.\n");
|
|
286
|
-
}
|
|
287
|
-
process.stdout.write("Step 4/4: Wiring up HOOK.md and restarting OpenClaw...\n");
|
|
288
|
-
execSync(`node "${selfBin}" install-hook`, { stdio: "inherit" });
|
|
289
|
-
execSync(`node "${selfBin}" restart-openclaw`, { stdio: "inherit" });
|
|
290
|
-
process.stdout.write('\n\u2713 FastGRC setup complete. Run "fastgrc-hook test" to verify.\n');
|
|
291
|
-
process.exit(0);
|
|
292
|
-
}
|
|
293
|
-
if (cmd === "uninstall-hook") {
|
|
294
|
-
const targetDir = arg || process.cwd();
|
|
295
|
-
const hookMdPath = path.join(targetDir, "HOOK.md");
|
|
296
|
-
if (!fs.existsSync(hookMdPath)) {
|
|
297
|
-
process.stdout.write("No HOOK.md found \u2014 nothing to remove.\n");
|
|
298
|
-
process.exit(0);
|
|
299
|
-
}
|
|
300
|
-
const existing = fs.readFileSync(hookMdPath, "utf8");
|
|
301
|
-
const patched = existing.replace(
|
|
302
|
-
/[ \t]*-[ \t]*matcher:[ \t]*PreToolUse\n[ \t]*handler:[ \t]*"[^"]*(?:fastgrc-hook|fastgrc-openclaw)[^"]*"\n?/,
|
|
303
|
-
""
|
|
304
|
-
);
|
|
305
|
-
if (patched === existing) {
|
|
306
|
-
process.stdout.write("FastGRC hook not found in HOOK.md \u2014 nothing to remove.\n");
|
|
278
|
+
process.stdout.write("\u2713 Policy ID saved to ~/.fastgrc.json\n");
|
|
307
279
|
} else {
|
|
308
|
-
|
|
309
|
-
process.stdout.write(`\u2713 FastGRC hook removed from ${hookMdPath}
|
|
310
|
-
`);
|
|
280
|
+
process.stdout.write(" (no policy ID \u2014 org-wide default will be used)\n");
|
|
311
281
|
}
|
|
282
|
+
doInstallHook(process.cwd());
|
|
283
|
+
process.stdout.write("\n\u2713 Config and HOOK.md done.\n");
|
|
284
|
+
process.stdout.write('Run "fastgrc-hook test" to verify the hook.\n');
|
|
312
285
|
process.exit(0);
|
|
313
286
|
}
|
|
314
287
|
if (cmd === "uninstall") {
|
|
315
|
-
const { execSync } = require("child_process");
|
|
316
|
-
const selfBin = process.argv[1];
|
|
317
288
|
const targetDir = arg || process.cwd();
|
|
318
|
-
process.stdout.write("Removing FastGRC from this OpenClaw deployment...\n\n");
|
|
319
|
-
process.stdout.write("1. Removing OpenClaw plugin...\n");
|
|
320
|
-
try {
|
|
321
|
-
execSync("sudo openclaw plugins remove fastgrc-openclaw", { stdio: "inherit" });
|
|
322
|
-
} catch {
|
|
323
|
-
process.stdout.write(" (plugin was not installed \u2014 skipped)\n");
|
|
324
|
-
}
|
|
325
|
-
process.stdout.write("2. Clearing config...\n");
|
|
326
289
|
const cfg = readConfig();
|
|
327
290
|
delete cfg.apiKey;
|
|
328
291
|
delete cfg.policyId;
|
|
329
292
|
writeConfig(cfg);
|
|
330
|
-
process.stdout.write("
|
|
331
|
-
|
|
332
|
-
execSync(`node "${selfBin}" uninstall-hook "${targetDir}"`, { stdio: "inherit" });
|
|
333
|
-
process.stdout.write("4. Restarting OpenClaw...\n");
|
|
334
|
-
execSync(`node "${selfBin}" restart-openclaw`, { stdio: "inherit" });
|
|
293
|
+
process.stdout.write("\u2713 API key and policy ID removed from ~/.fastgrc.json\n");
|
|
294
|
+
doUninstallHook(targetDir);
|
|
335
295
|
process.stdout.write(
|
|
336
|
-
"\n\u2713
|
|
296
|
+
"\n\u2713 Config and HOOK.md cleaned up.\nComplete removal \u2014 run these two commands:\n sudo openclaw plugins remove fastgrc-openclaw\n npm uninstall -g fastgrc-openclaw\n"
|
|
337
297
|
);
|
|
338
298
|
process.exit(0);
|
|
339
299
|
}
|
|
@@ -390,7 +350,7 @@ if (cmd === "test") {
|
|
|
390
350
|
`);
|
|
391
351
|
process.exit(0);
|
|
392
352
|
}
|
|
393
|
-
if (cmd === "test" || cmd === "where" || cmd === "which-hook" || cmd === "
|
|
353
|
+
if (cmd === "test" || cmd === "where" || cmd === "which-hook" || cmd === "setup" || cmd === "uninstall" || cmd === "install-hook" || cmd === "uninstall-hook") {
|
|
394
354
|
} else {
|
|
395
355
|
const apiKey = process.env.FASTGRC_API_KEY ?? readConfig().apiKey;
|
|
396
356
|
if (!apiKey) {
|
|
@@ -431,7 +391,6 @@ if (cmd === "test" || cmd === "where" || cmd === "which-hook" || cmd === "restar
|
|
|
431
391
|
args,
|
|
432
392
|
agentId,
|
|
433
393
|
apiKey,
|
|
434
|
-
// narrowed at module level via early-exit guard above
|
|
435
394
|
policyId,
|
|
436
395
|
baseUrl
|
|
437
396
|
});
|
package/dist/bin.mjs
CHANGED
|
@@ -1,10 +1,4 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
|
|
3
|
-
get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
|
|
4
|
-
}) : x)(function(x) {
|
|
5
|
-
if (typeof require !== "undefined") return require.apply(this, arguments);
|
|
6
|
-
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
7
|
-
});
|
|
8
2
|
|
|
9
3
|
// src/bin.ts
|
|
10
4
|
import * as fs from "fs";
|
|
@@ -74,64 +68,6 @@ function readConfig() {
|
|
|
74
68
|
function writeConfig(data) {
|
|
75
69
|
fs.writeFileSync(CONFIG_PATH, JSON.stringify(data, null, 2), { mode: 384 });
|
|
76
70
|
}
|
|
77
|
-
var [, , cmd, arg] = process.argv;
|
|
78
|
-
if (cmd === "set-key") {
|
|
79
|
-
if (!arg) {
|
|
80
|
-
process.stderr.write("Usage: fastgrc-hook set-key fgrc_k1_...\n");
|
|
81
|
-
process.exit(1);
|
|
82
|
-
}
|
|
83
|
-
writeConfig({ ...readConfig(), apiKey: arg });
|
|
84
|
-
process.stdout.write(`\u2713 FastGRC API key saved to ${CONFIG_PATH}
|
|
85
|
-
`);
|
|
86
|
-
process.stdout.write(' Run "fastgrc-hook get-key" to verify.\n');
|
|
87
|
-
process.exit(0);
|
|
88
|
-
}
|
|
89
|
-
if (cmd === "get-key") {
|
|
90
|
-
const key = readConfig().apiKey;
|
|
91
|
-
if (!key) {
|
|
92
|
-
process.stdout.write("No key stored. Run: fastgrc-hook set-key fgrc_k1_...\n");
|
|
93
|
-
} else {
|
|
94
|
-
process.stdout.write(`${key.slice(0, 12)}${"*".repeat(Math.max(0, key.length - 12))}
|
|
95
|
-
`);
|
|
96
|
-
}
|
|
97
|
-
process.exit(0);
|
|
98
|
-
}
|
|
99
|
-
if (cmd === "unset-key") {
|
|
100
|
-
const cfg = readConfig();
|
|
101
|
-
delete cfg.apiKey;
|
|
102
|
-
writeConfig(cfg);
|
|
103
|
-
process.stdout.write("FastGRC API key removed.\n");
|
|
104
|
-
process.exit(0);
|
|
105
|
-
}
|
|
106
|
-
if (cmd === "set-policy") {
|
|
107
|
-
if (!arg) {
|
|
108
|
-
process.stderr.write("Usage: fastgrc-hook set-policy <policy-id>\n");
|
|
109
|
-
process.exit(1);
|
|
110
|
-
}
|
|
111
|
-
writeConfig({ ...readConfig(), policyId: arg });
|
|
112
|
-
process.stdout.write(`\u2713 FastGRC policy ID saved to ${CONFIG_PATH}
|
|
113
|
-
`);
|
|
114
|
-
process.stdout.write(' Run "fastgrc-hook get-policy" to verify.\n');
|
|
115
|
-
process.exit(0);
|
|
116
|
-
}
|
|
117
|
-
if (cmd === "get-policy") {
|
|
118
|
-
const id = readConfig().policyId;
|
|
119
|
-
if (!id) {
|
|
120
|
-
process.stdout.write("No policy ID stored \u2014 org-wide default will be used.\n");
|
|
121
|
-
process.stdout.write("Run: fastgrc-hook set-policy <policy-id>\n");
|
|
122
|
-
} else {
|
|
123
|
-
process.stdout.write(`${id}
|
|
124
|
-
`);
|
|
125
|
-
}
|
|
126
|
-
process.exit(0);
|
|
127
|
-
}
|
|
128
|
-
if (cmd === "unset-policy") {
|
|
129
|
-
const cfg = readConfig();
|
|
130
|
-
delete cfg.policyId;
|
|
131
|
-
writeConfig(cfg);
|
|
132
|
-
process.stdout.write("FastGRC policy ID removed \u2014 org-wide default will be used.\n");
|
|
133
|
-
process.exit(0);
|
|
134
|
-
}
|
|
135
71
|
function computeHandler() {
|
|
136
72
|
const binPath = process.argv[1];
|
|
137
73
|
const homeDir = os.homedir();
|
|
@@ -147,30 +83,7 @@ Test it directly (bypasses OpenClaw):
|
|
|
147
83
|
`
|
|
148
84
|
);
|
|
149
85
|
}
|
|
150
|
-
|
|
151
|
-
const { spawn, execSync } = __require("child_process");
|
|
152
|
-
try {
|
|
153
|
-
execSync("pkill -x openclaw", { stdio: "ignore" });
|
|
154
|
-
process.stdout.write("Stopped existing openclaw process(es).\n");
|
|
155
|
-
} catch {
|
|
156
|
-
process.stdout.write("No openclaw process was running.\n");
|
|
157
|
-
}
|
|
158
|
-
const logPath = process.env.OPENCLAW_LOG ?? "/tmp/openclaw.log";
|
|
159
|
-
const workDir = arg || process.cwd();
|
|
160
|
-
const out = fs.openSync(logPath, "a");
|
|
161
|
-
const child = spawn("openclaw", [], {
|
|
162
|
-
detached: true,
|
|
163
|
-
stdio: ["ignore", out, out],
|
|
164
|
-
cwd: workDir
|
|
165
|
-
});
|
|
166
|
-
child.unref();
|
|
167
|
-
process.stdout.write(`\u2713 OpenClaw started (PID: ${child.pid}, cwd: ${workDir})
|
|
168
|
-
Logs: tail -f ${logPath}
|
|
169
|
-
`);
|
|
170
|
-
process.exit(0);
|
|
171
|
-
}
|
|
172
|
-
if (cmd === "install-hook") {
|
|
173
|
-
const targetDir = arg || process.cwd();
|
|
86
|
+
function doInstallHook(targetDir) {
|
|
174
87
|
const hookMdPath = path.join(targetDir, "HOOK.md");
|
|
175
88
|
const { handlerStr } = computeHandler();
|
|
176
89
|
const HOOK_ENTRY = ` - matcher: PreToolUse
|
|
@@ -189,7 +102,7 @@ if (cmd === "install-hook") {
|
|
|
189
102
|
Restart OpenClaw \u2014 FastGRC will evaluate every tool call.
|
|
190
103
|
`);
|
|
191
104
|
printTestSnippet(handlerStr);
|
|
192
|
-
|
|
105
|
+
return;
|
|
193
106
|
}
|
|
194
107
|
const existing = fs.readFileSync(hookMdPath, "utf8");
|
|
195
108
|
if (existing.includes(handlerStr)) {
|
|
@@ -197,7 +110,7 @@ Restart OpenClaw \u2014 FastGRC will evaluate every tool call.
|
|
|
197
110
|
Handler: ${handlerStr}
|
|
198
111
|
`);
|
|
199
112
|
printTestSnippet(handlerStr);
|
|
200
|
-
|
|
113
|
+
return;
|
|
201
114
|
}
|
|
202
115
|
if (existing.includes("fastgrc-hook") || existing.includes("fastgrc-openclaw")) {
|
|
203
116
|
const patched = existing.replace(
|
|
@@ -211,7 +124,7 @@ Restart OpenClaw \u2014 FastGRC will evaluate every tool call.
|
|
|
211
124
|
Restart OpenClaw to activate.
|
|
212
125
|
`);
|
|
213
126
|
printTestSnippet(handlerStr);
|
|
214
|
-
|
|
127
|
+
return;
|
|
215
128
|
}
|
|
216
129
|
const fmEnd = existing.indexOf("\n---", 3);
|
|
217
130
|
let updated;
|
|
@@ -230,10 +143,93 @@ ${HOOK_ENTRY}`;
|
|
|
230
143
|
Restart OpenClaw to activate.
|
|
231
144
|
`);
|
|
232
145
|
printTestSnippet(handlerStr);
|
|
146
|
+
}
|
|
147
|
+
function doUninstallHook(targetDir) {
|
|
148
|
+
const hookMdPath = path.join(targetDir, "HOOK.md");
|
|
149
|
+
if (!fs.existsSync(hookMdPath)) {
|
|
150
|
+
process.stdout.write("No HOOK.md found \u2014 nothing to remove.\n");
|
|
151
|
+
return;
|
|
152
|
+
}
|
|
153
|
+
const existing = fs.readFileSync(hookMdPath, "utf8");
|
|
154
|
+
const patched = existing.replace(
|
|
155
|
+
/[ \t]*-[ \t]*matcher:[ \t]*PreToolUse\n[ \t]*handler:[ \t]*"[^"]*(?:fastgrc-hook|fastgrc-openclaw)[^"]*"\n?/,
|
|
156
|
+
""
|
|
157
|
+
);
|
|
158
|
+
if (patched === existing) {
|
|
159
|
+
process.stdout.write("FastGRC hook not found in HOOK.md \u2014 nothing to remove.\n");
|
|
160
|
+
} else {
|
|
161
|
+
fs.writeFileSync(hookMdPath, patched, "utf8");
|
|
162
|
+
process.stdout.write(`\u2713 FastGRC hook removed from ${hookMdPath}
|
|
163
|
+
`);
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
var [, , cmd, arg] = process.argv;
|
|
167
|
+
if (cmd === "set-key") {
|
|
168
|
+
if (!arg) {
|
|
169
|
+
process.stderr.write("Usage: fastgrc-hook set-key fgrc_k1_...\n");
|
|
170
|
+
process.exit(1);
|
|
171
|
+
}
|
|
172
|
+
writeConfig({ ...readConfig(), apiKey: arg });
|
|
173
|
+
process.stdout.write(`\u2713 FastGRC API key saved to ${CONFIG_PATH}
|
|
174
|
+
`);
|
|
175
|
+
process.stdout.write(' Run "fastgrc-hook get-key" to verify.\n');
|
|
176
|
+
process.exit(0);
|
|
177
|
+
}
|
|
178
|
+
if (cmd === "get-key") {
|
|
179
|
+
const key = readConfig().apiKey;
|
|
180
|
+
if (!key) {
|
|
181
|
+
process.stdout.write("No key stored. Run: fastgrc-hook set-key fgrc_k1_...\n");
|
|
182
|
+
} else {
|
|
183
|
+
process.stdout.write(`${key.slice(0, 12)}${"*".repeat(Math.max(0, key.length - 12))}
|
|
184
|
+
`);
|
|
185
|
+
}
|
|
186
|
+
process.exit(0);
|
|
187
|
+
}
|
|
188
|
+
if (cmd === "unset-key") {
|
|
189
|
+
const cfg = readConfig();
|
|
190
|
+
delete cfg.apiKey;
|
|
191
|
+
writeConfig(cfg);
|
|
192
|
+
process.stdout.write("FastGRC API key removed.\n");
|
|
193
|
+
process.exit(0);
|
|
194
|
+
}
|
|
195
|
+
if (cmd === "set-policy") {
|
|
196
|
+
if (!arg) {
|
|
197
|
+
process.stderr.write("Usage: fastgrc-hook set-policy <policy-id>\n");
|
|
198
|
+
process.exit(1);
|
|
199
|
+
}
|
|
200
|
+
writeConfig({ ...readConfig(), policyId: arg });
|
|
201
|
+
process.stdout.write(`\u2713 FastGRC policy ID saved to ${CONFIG_PATH}
|
|
202
|
+
`);
|
|
203
|
+
process.stdout.write(' Run "fastgrc-hook get-policy" to verify.\n');
|
|
204
|
+
process.exit(0);
|
|
205
|
+
}
|
|
206
|
+
if (cmd === "get-policy") {
|
|
207
|
+
const id = readConfig().policyId;
|
|
208
|
+
if (!id) {
|
|
209
|
+
process.stdout.write("No policy ID stored \u2014 org-wide default will be used.\n");
|
|
210
|
+
process.stdout.write("Run: fastgrc-hook set-policy <policy-id>\n");
|
|
211
|
+
} else {
|
|
212
|
+
process.stdout.write(`${id}
|
|
213
|
+
`);
|
|
214
|
+
}
|
|
215
|
+
process.exit(0);
|
|
216
|
+
}
|
|
217
|
+
if (cmd === "unset-policy") {
|
|
218
|
+
const cfg = readConfig();
|
|
219
|
+
delete cfg.policyId;
|
|
220
|
+
writeConfig(cfg);
|
|
221
|
+
process.stdout.write("FastGRC policy ID removed \u2014 org-wide default will be used.\n");
|
|
222
|
+
process.exit(0);
|
|
223
|
+
}
|
|
224
|
+
if (cmd === "install-hook") {
|
|
225
|
+
doInstallHook(arg || process.cwd());
|
|
226
|
+
process.exit(0);
|
|
227
|
+
}
|
|
228
|
+
if (cmd === "uninstall-hook") {
|
|
229
|
+
doUninstallHook(arg || process.cwd());
|
|
233
230
|
process.exit(0);
|
|
234
231
|
}
|
|
235
232
|
if (cmd === "setup") {
|
|
236
|
-
const { execSync } = __require("child_process");
|
|
237
233
|
const rest = process.argv.slice(3);
|
|
238
234
|
let apiKeyArg;
|
|
239
235
|
let policyIdArg;
|
|
@@ -252,71 +248,29 @@ if (cmd === "setup") {
|
|
|
252
248
|
process.stderr.write("Usage: fastgrc-hook setup --api-key <key> [--policy-id <id>]\n");
|
|
253
249
|
process.exit(1);
|
|
254
250
|
}
|
|
255
|
-
const selfBin = process.argv[1];
|
|
256
|
-
process.stdout.write("Step 1/4: Installing OpenClaw plugin as root...\n");
|
|
257
|
-
try {
|
|
258
|
-
execSync("sudo openclaw plugins remove fastgrc-openclaw", { stdio: "ignore" });
|
|
259
|
-
} catch {
|
|
260
|
-
}
|
|
261
|
-
execSync("sudo openclaw plugins install fastgrc-openclaw", { stdio: "inherit" });
|
|
262
251
|
writeConfig({ ...readConfig(), apiKey: apiKeyArg });
|
|
263
|
-
process.stdout.write("
|
|
252
|
+
process.stdout.write("\u2713 API key saved to ~/.fastgrc.json\n");
|
|
264
253
|
if (policyIdArg) {
|
|
265
254
|
writeConfig({ ...readConfig(), policyId: policyIdArg });
|
|
266
|
-
process.stdout.write("
|
|
267
|
-
} else {
|
|
268
|
-
process.stdout.write("Step 3/4: No policy ID provided \u2014 org-wide default will be used.\n");
|
|
269
|
-
}
|
|
270
|
-
process.stdout.write("Step 4/4: Wiring up HOOK.md and restarting OpenClaw...\n");
|
|
271
|
-
execSync(`node "${selfBin}" install-hook`, { stdio: "inherit" });
|
|
272
|
-
execSync(`node "${selfBin}" restart-openclaw`, { stdio: "inherit" });
|
|
273
|
-
process.stdout.write('\n\u2713 FastGRC setup complete. Run "fastgrc-hook test" to verify.\n');
|
|
274
|
-
process.exit(0);
|
|
275
|
-
}
|
|
276
|
-
if (cmd === "uninstall-hook") {
|
|
277
|
-
const targetDir = arg || process.cwd();
|
|
278
|
-
const hookMdPath = path.join(targetDir, "HOOK.md");
|
|
279
|
-
if (!fs.existsSync(hookMdPath)) {
|
|
280
|
-
process.stdout.write("No HOOK.md found \u2014 nothing to remove.\n");
|
|
281
|
-
process.exit(0);
|
|
282
|
-
}
|
|
283
|
-
const existing = fs.readFileSync(hookMdPath, "utf8");
|
|
284
|
-
const patched = existing.replace(
|
|
285
|
-
/[ \t]*-[ \t]*matcher:[ \t]*PreToolUse\n[ \t]*handler:[ \t]*"[^"]*(?:fastgrc-hook|fastgrc-openclaw)[^"]*"\n?/,
|
|
286
|
-
""
|
|
287
|
-
);
|
|
288
|
-
if (patched === existing) {
|
|
289
|
-
process.stdout.write("FastGRC hook not found in HOOK.md \u2014 nothing to remove.\n");
|
|
255
|
+
process.stdout.write("\u2713 Policy ID saved to ~/.fastgrc.json\n");
|
|
290
256
|
} else {
|
|
291
|
-
|
|
292
|
-
process.stdout.write(`\u2713 FastGRC hook removed from ${hookMdPath}
|
|
293
|
-
`);
|
|
257
|
+
process.stdout.write(" (no policy ID \u2014 org-wide default will be used)\n");
|
|
294
258
|
}
|
|
259
|
+
doInstallHook(process.cwd());
|
|
260
|
+
process.stdout.write("\n\u2713 Config and HOOK.md done.\n");
|
|
261
|
+
process.stdout.write('Run "fastgrc-hook test" to verify the hook.\n');
|
|
295
262
|
process.exit(0);
|
|
296
263
|
}
|
|
297
264
|
if (cmd === "uninstall") {
|
|
298
|
-
const { execSync } = __require("child_process");
|
|
299
|
-
const selfBin = process.argv[1];
|
|
300
265
|
const targetDir = arg || process.cwd();
|
|
301
|
-
process.stdout.write("Removing FastGRC from this OpenClaw deployment...\n\n");
|
|
302
|
-
process.stdout.write("1. Removing OpenClaw plugin...\n");
|
|
303
|
-
try {
|
|
304
|
-
execSync("sudo openclaw plugins remove fastgrc-openclaw", { stdio: "inherit" });
|
|
305
|
-
} catch {
|
|
306
|
-
process.stdout.write(" (plugin was not installed \u2014 skipped)\n");
|
|
307
|
-
}
|
|
308
|
-
process.stdout.write("2. Clearing config...\n");
|
|
309
266
|
const cfg = readConfig();
|
|
310
267
|
delete cfg.apiKey;
|
|
311
268
|
delete cfg.policyId;
|
|
312
269
|
writeConfig(cfg);
|
|
313
|
-
process.stdout.write("
|
|
314
|
-
|
|
315
|
-
execSync(`node "${selfBin}" uninstall-hook "${targetDir}"`, { stdio: "inherit" });
|
|
316
|
-
process.stdout.write("4. Restarting OpenClaw...\n");
|
|
317
|
-
execSync(`node "${selfBin}" restart-openclaw`, { stdio: "inherit" });
|
|
270
|
+
process.stdout.write("\u2713 API key and policy ID removed from ~/.fastgrc.json\n");
|
|
271
|
+
doUninstallHook(targetDir);
|
|
318
272
|
process.stdout.write(
|
|
319
|
-
"\n\u2713
|
|
273
|
+
"\n\u2713 Config and HOOK.md cleaned up.\nComplete removal \u2014 run these two commands:\n sudo openclaw plugins remove fastgrc-openclaw\n npm uninstall -g fastgrc-openclaw\n"
|
|
320
274
|
);
|
|
321
275
|
process.exit(0);
|
|
322
276
|
}
|
|
@@ -373,7 +327,7 @@ if (cmd === "test") {
|
|
|
373
327
|
`);
|
|
374
328
|
process.exit(0);
|
|
375
329
|
}
|
|
376
|
-
if (cmd === "test" || cmd === "where" || cmd === "which-hook" || cmd === "
|
|
330
|
+
if (cmd === "test" || cmd === "where" || cmd === "which-hook" || cmd === "setup" || cmd === "uninstall" || cmd === "install-hook" || cmd === "uninstall-hook") {
|
|
377
331
|
} else {
|
|
378
332
|
const apiKey = process.env.FASTGRC_API_KEY ?? readConfig().apiKey;
|
|
379
333
|
if (!apiKey) {
|
|
@@ -414,7 +368,6 @@ if (cmd === "test" || cmd === "where" || cmd === "which-hook" || cmd === "restar
|
|
|
414
368
|
args,
|
|
415
369
|
agentId,
|
|
416
370
|
apiKey,
|
|
417
|
-
// narrowed at module level via early-exit guard above
|
|
418
371
|
policyId,
|
|
419
372
|
baseUrl
|
|
420
373
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "fastgrc-openclaw",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.24",
|
|
4
4
|
"description": "FastGRC agent compliance plugin for OpenClaw — evaluates every tool call against your policy before it executes",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"module": "./dist/index.mjs",
|