@hasna/hooks 0.10.8 → 0.11.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 +48 -0
- package/bin/hooks-mcp.js +352 -182
- package/bin/index.js +2314 -1607
- package/bin/native-readiness-entry.js +355 -0
- package/bin/native-safety-entry.js +13 -4
- package/dist/index.js +502 -284
- package/dist/lib/codex-safety-check.d.ts +2 -1
- package/dist/lib/codex-safety-trust.d.ts +40 -8
- package/dist/lib/installer.d.ts +11 -0
- package/dist/lib/native-readiness-command.d.ts +14 -0
- package/dist/lib/native-safety-registration.d.ts +38 -7
- package/dist/lib/readiness-process.d.ts +20 -0
- package/dist/native-readiness.d.ts +68 -0
- package/dist/native-readiness.js +328 -0
- package/hooks/hook-workspace-repos-guard/README.md +5 -2
- package/hooks/hook-workspace-repos-guard/src/hook.ts +13 -4
- package/hooks/native-readiness-entry.ts +31 -0
- package/package.json +7 -2
|
@@ -365,13 +365,13 @@ function segmentOperation(segment: string): Operation {
|
|
|
365
365
|
const trimmed = segment.trim();
|
|
366
366
|
if (!trimmed) return "read";
|
|
367
367
|
|
|
368
|
-
if (/(?:^|\s)(?:rm|rmdir|unlink|shred|trash|rmtree|del)(?:\s|$)/.test(trimmed)) return "delete";
|
|
368
|
+
if (/(?:^|\s)\\?(?:[^\s;&|<>()]*\/)?(?:rm|rmdir|unlink|shred|trash|rmtree|del)(?:\s|$)/.test(trimmed)) return "delete";
|
|
369
369
|
if (/\bgit\b/.test(trimmed)) {
|
|
370
370
|
if (/\bgit\b[^;&|]*\b(?:clean|rm)\b/.test(trimmed)) return "delete";
|
|
371
371
|
if (/\bgit\b[^;&|]*\b(?:clone|init)\b/.test(trimmed)) return "write";
|
|
372
372
|
return "read";
|
|
373
373
|
}
|
|
374
|
-
if (/(?:^|\s)(?:mkdir|mkfile|touch|mv|cp|ln|tee|install|dd)(?:\s|$)/.test(trimmed)) return "write";
|
|
374
|
+
if (/(?:^|\s)\\?(?:[^\s;&|<>()]*\/)?(?:mkdir|mkfile|touch|mv|cp|ln|tee|install|dd)(?:\s|$)/.test(trimmed)) return "write";
|
|
375
375
|
if (/\b(?:curl|wget)\b/.test(trimmed)) {
|
|
376
376
|
if (WRITE_FLAGS.test(trimmed)) return "write";
|
|
377
377
|
return "read";
|
|
@@ -586,8 +586,17 @@ export function bashTargets(command: string, home: string, cwd: string): PathTar
|
|
|
586
586
|
// Operands after the command word. Options end at `--` or, as BSD
|
|
587
587
|
// getopt does, at the first operand: every later word is an operand
|
|
588
588
|
// even when it starts with `-`.
|
|
589
|
+
// A delete tool's subcommand word is not an operand: `trash put <path>`
|
|
590
|
+
// and `git [-C dir] rm|clean ...` act on the words after it.
|
|
591
|
+
let operandStart = 1;
|
|
592
|
+
const tool = (words[0]?.text ?? "").split("/").pop();
|
|
593
|
+
if (tool === "trash" && ["put", "rm", "delete", "remove"].includes(words[1]?.text ?? "")) operandStart = 2;
|
|
594
|
+
if (tool === "git") {
|
|
595
|
+
const sub = words.findIndex((word, index) => index > 0 && (word.text === "rm" || word.text === "clean"));
|
|
596
|
+
if (sub > 0) operandStart = sub + 1;
|
|
597
|
+
}
|
|
589
598
|
let endOfOptions = false;
|
|
590
|
-
const nonFlag = words.slice(
|
|
599
|
+
const nonFlag = words.slice(operandStart).flatMap((word) => {
|
|
591
600
|
if (!endOfOptions && word.text === "--") {
|
|
592
601
|
endOfOptions = true;
|
|
593
602
|
return [];
|
|
@@ -599,7 +608,7 @@ export function bashTargets(command: string, home: string, cwd: string): PathTar
|
|
|
599
608
|
// mv changes its sources too, so every mv operand counts as a write.
|
|
600
609
|
const everyOperand =
|
|
601
610
|
stage.op === "delete" ||
|
|
602
|
-
/(?:^|\s)(?:mkdir|mkfile|touch|tee|truncate|install|mv)(?:\s|$)/.test(stage.commandPart) ||
|
|
611
|
+
/(?:^|\s)\\?(?:[^\s;&|<>()]*\/)?(?:mkdir|mkfile|touch|tee|truncate|install|mv)(?:\s|$)/.test(stage.commandPart) ||
|
|
603
612
|
(/(?:^|\s)sed(?:\s|$)/.test(stage.commandPart) && /(?:^|\s)(?:-i\S*|--in-place\S*)(?:\s|$)/.test(stage.commandPart));
|
|
604
613
|
const operandTargets: Array<{ operand: string; op: Operation }> = [];
|
|
605
614
|
if (everyOperand) {
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { handleReadinessSessionStart, isReadinessProvider, readinessSessionStartOutput } from "../src/native-readiness";
|
|
2
|
+
|
|
3
|
+
// This dedicated bundle never loads the generic Hooks registry or credentials.
|
|
4
|
+
// The native command verifies its bytes before evaluating this CommonJS entry.
|
|
5
|
+
async function main() {
|
|
6
|
+
const provider = process.argv[2];
|
|
7
|
+
if (!isReadinessProvider(provider)) {
|
|
8
|
+
process.stderr.write("Trash readiness needs attention (unsupported provider).\n");
|
|
9
|
+
process.exitCode = 1; return;
|
|
10
|
+
}
|
|
11
|
+
const invalid = () => readinessSessionStartOutput({ schema: "hasna.hooks.trash-readiness-result/v1",
|
|
12
|
+
provider, ready: false, code: "input_invalid", nativeAdoptionVerified: false });
|
|
13
|
+
try {
|
|
14
|
+
const input = await new Promise<Buffer>((accept, reject) => {
|
|
15
|
+
const chunks: Buffer[] = []; let size = 0;
|
|
16
|
+
const finish = (error?: Error) => {
|
|
17
|
+
clearTimeout(timer); process.stdin.pause(); process.stdin.removeAllListeners("data");
|
|
18
|
+
process.stdin.removeAllListeners("end"); process.stdin.removeAllListeners("error");
|
|
19
|
+
error ? reject(error) : accept(Buffer.concat(chunks));
|
|
20
|
+
};
|
|
21
|
+
const timer = setTimeout(() => finish(new Error()), 1000);
|
|
22
|
+
process.stdin.on("data", chunk => {
|
|
23
|
+
const bytes = Buffer.from(chunk); size += bytes.length;
|
|
24
|
+
if (size > 65_536) finish(new Error()); else chunks.push(bytes);
|
|
25
|
+
});
|
|
26
|
+
process.stdin.once("end", () => finish()); process.stdin.once("error", () => finish(new Error()));
|
|
27
|
+
});
|
|
28
|
+
process.stdout.write(JSON.stringify(await handleReadinessSessionStart(provider, JSON.parse(input.toString("utf8")))) + "\n");
|
|
29
|
+
} catch { process.stdout.write(JSON.stringify(invalid()) + "\n"); }
|
|
30
|
+
}
|
|
31
|
+
void main();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hasna/hooks",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.11.0",
|
|
4
4
|
"description": "Open source hooks library for AI coding agents - Install safety, quality, and automation hooks with a single command",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -24,6 +24,10 @@
|
|
|
24
24
|
"./native-safety": {
|
|
25
25
|
"types": "./dist/native-safety.d.ts",
|
|
26
26
|
"import": "./dist/native-safety.js"
|
|
27
|
+
},
|
|
28
|
+
"./native-readiness": {
|
|
29
|
+
"types": "./dist/native-readiness.d.ts",
|
|
30
|
+
"import": "./dist/native-readiness.js"
|
|
27
31
|
}
|
|
28
32
|
},
|
|
29
33
|
"main": "./dist/index.js",
|
|
@@ -41,7 +45,8 @@
|
|
|
41
45
|
"postinstall": "node scripts/ensure-profiles-dir.mjs",
|
|
42
46
|
"scan:artifact": "bun scripts/artifact-scan.ts",
|
|
43
47
|
"prepack": "bun run build && bun run scan:artifact",
|
|
44
|
-
"build:native-safety": "bun build ./hooks/native-safety-entry.ts --outdir ./bin --target bun --define import.meta.main=false && bun build ./src/native-safety.ts --outdir ./dist --target bun"
|
|
48
|
+
"build:native-safety": "bun build ./hooks/native-safety-entry.ts --outdir ./bin --target bun --define import.meta.main=false && bun build ./src/native-safety.ts --outdir ./dist --target bun && bun run build:native-readiness",
|
|
49
|
+
"build:native-readiness": "bun build ./hooks/native-readiness-entry.ts --outdir ./bin --target node --format=cjs && bun build ./src/native-readiness.ts --outdir ./dist --target bun"
|
|
45
50
|
},
|
|
46
51
|
"keywords": [
|
|
47
52
|
"claude-code",
|