@webpieces/ai-hook-rules 0.0.1 → 0.2.113
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/package.json +4 -3
- package/src/adapters/claude-code-hook.d.ts +1 -0
- package/src/adapters/claude-code-hook.js +112 -0
- package/src/adapters/claude-code-hook.js.map +1 -0
- package/src/adapters/openclaw-plugin.d.ts +14 -0
- package/src/adapters/openclaw-plugin.js +73 -0
- package/src/adapters/openclaw-plugin.js.map +1 -0
- package/src/core/build-context.d.ts +8 -0
- package/src/core/build-context.js +62 -0
- package/src/core/build-context.js.map +1 -0
- package/src/core/configs/default.d.ts +2 -0
- package/src/core/configs/{default.ts → default.js} +6 -3
- package/src/core/configs/default.js.map +1 -0
- package/src/core/disable-directives.d.ts +9 -0
- package/src/core/disable-directives.js +92 -0
- package/src/core/disable-directives.js.map +1 -0
- package/src/core/instruct-ai-writer.d.ts +1 -0
- package/src/core/instruct-ai-writer.js +18 -0
- package/src/core/instruct-ai-writer.js.map +1 -0
- package/src/core/load-config.d.ts +1 -0
- package/src/core/load-config.js +10 -0
- package/src/core/load-config.js.map +1 -0
- package/src/core/load-rules.d.ts +3 -0
- package/src/core/{load-rules.ts → load-rules.js} +33 -32
- package/src/core/load-rules.js.map +1 -0
- package/src/core/rejection-log.d.ts +2 -0
- package/src/core/{rejection-log.ts → rejection-log.js} +34 -51
- package/src/core/rejection-log.js.map +1 -0
- package/src/core/report.d.ts +2 -0
- package/src/core/{report.ts → report.js} +7 -8
- package/src/core/report.js.map +1 -0
- package/src/core/rules/catch-error-pattern.d.ts +3 -0
- package/src/core/rules/{catch-error-pattern.ts → catch-error-pattern.js} +25 -54
- package/src/core/rules/catch-error-pattern.js.map +1 -0
- package/src/core/rules/file-location.d.ts +3 -0
- package/src/core/rules/{file-location.ts → file-location.js} +29 -43
- package/src/core/rules/file-location.js.map +1 -0
- package/src/core/rules/index.d.ts +1 -0
- package/src/core/rules/{index.ts → index.js} +5 -1
- package/src/core/rules/index.js.map +1 -0
- package/src/core/rules/max-file-lines.d.ts +3 -0
- package/src/core/rules/{max-file-lines.ts → max-file-lines.js} +17 -23
- package/src/core/rules/max-file-lines.js.map +1 -0
- package/src/core/rules/no-any-unknown.d.ts +3 -0
- package/src/core/rules/no-any-unknown.js +30 -0
- package/src/core/rules/no-any-unknown.js.map +1 -0
- package/src/core/rules/no-destructure.d.ts +3 -0
- package/src/core/rules/{no-destructure.ts → no-destructure.js} +13 -17
- package/src/core/rules/no-destructure.js.map +1 -0
- package/src/core/rules/no-implicit-any.d.ts +3 -0
- package/src/core/rules/{no-implicit-any.ts → no-implicit-any.js} +32 -30
- package/src/core/rules/no-implicit-any.js.map +1 -0
- package/src/core/rules/no-shell-substitution.d.ts +3 -0
- package/src/core/rules/no-shell-substitution.js +54 -0
- package/src/core/rules/no-shell-substitution.js.map +1 -0
- package/src/core/rules/no-unmanaged-exceptions.d.ts +3 -0
- package/src/core/rules/{no-unmanaged-exceptions.ts → no-unmanaged-exceptions.js} +21 -24
- package/src/core/rules/no-unmanaged-exceptions.js.map +1 -0
- package/src/core/rules/require-return-type.d.ts +3 -0
- package/src/core/rules/{require-return-type.ts → require-return-type.js} +21 -28
- package/src/core/rules/require-return-type.js.map +1 -0
- package/src/core/runner.d.ts +3 -0
- package/src/core/runner.js +181 -0
- package/src/core/runner.js.map +1 -0
- package/src/core/strip-ts-noise.d.ts +1 -0
- package/src/core/strip-ts-noise.js +178 -0
- package/src/core/strip-ts-noise.js.map +1 -0
- package/src/core/to-error.d.ts +5 -0
- package/src/core/{to-error.ts → to-error.js} +7 -4
- package/src/core/to-error.js.map +1 -0
- package/src/core/types.d.ts +93 -0
- package/src/core/types.js +93 -0
- package/src/core/types.js.map +1 -0
- package/src/index.d.ts +5 -0
- package/src/index.js +25 -0
- package/src/index.js.map +1 -0
- package/LICENSE +0 -373
- package/src/adapters/claude-code-hook.ts +0 -117
- package/src/adapters/openclaw-plugin.ts +0 -88
- package/src/core/__tests__/disable-directives.test.ts +0 -114
- package/src/core/__tests__/rules/file-location.test.ts +0 -90
- package/src/core/__tests__/rules/max-file-lines.test.ts +0 -53
- package/src/core/__tests__/rules/no-any.test.ts +0 -68
- package/src/core/__tests__/rules/no-destructure.test.ts +0 -50
- package/src/core/__tests__/rules/no-shell-substitution.test.ts +0 -118
- package/src/core/__tests__/rules/no-unmanaged-exceptions.test.ts +0 -54
- package/src/core/__tests__/rules/require-return-type.test.ts +0 -79
- package/src/core/__tests__/runner.test.ts +0 -288
- package/src/core/__tests__/strip-ts-noise.test.ts +0 -109
- package/src/core/build-context.ts +0 -96
- package/src/core/disable-directives.ts +0 -90
- package/src/core/instruct-ai-writer.ts +0 -15
- package/src/core/load-config.ts +0 -3
- package/src/core/rules/no-any-unknown.ts +0 -35
- package/src/core/rules/no-shell-substitution.ts +0 -71
- package/src/core/runner.ts +0 -205
- package/src/core/strip-ts-noise.ts +0 -103
- package/src/core/types.ts +0 -196
- package/src/index.ts +0 -14
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@webpieces/ai-hook-rules",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.113",
|
|
4
4
|
"description": "Pluggable write-time validation framework for AI coding agents (@webpieces/ai-hook-rules). Claude Code PreToolUse + openclaw before_tool_call adapters share one rule engine.",
|
|
5
5
|
"type": "commonjs",
|
|
6
6
|
"main": "./src/index.js",
|
|
@@ -29,9 +29,10 @@
|
|
|
29
29
|
"directory": "packages/tooling/ai-hook-rules"
|
|
30
30
|
},
|
|
31
31
|
"dependencies": {
|
|
32
|
-
"@webpieces/rules-config": "0.
|
|
32
|
+
"@webpieces/rules-config": "0.2.113"
|
|
33
33
|
},
|
|
34
34
|
"publishConfig": {
|
|
35
35
|
"access": "public"
|
|
36
|
-
}
|
|
36
|
+
},
|
|
37
|
+
"types": "./src/index.d.ts"
|
|
37
38
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function main(): Promise<void>;
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.main = main;
|
|
4
|
+
const runner_1 = require("../core/runner");
|
|
5
|
+
const rejection_log_1 = require("../core/rejection-log");
|
|
6
|
+
const types_1 = require("../core/types");
|
|
7
|
+
const to_error_1 = require("../core/to-error");
|
|
8
|
+
const HANDLED_FILE_TOOLS = new Set(['Write', 'Edit', 'MultiEdit']);
|
|
9
|
+
function readStdin() {
|
|
10
|
+
return new Promise((resolve) => {
|
|
11
|
+
let data = '';
|
|
12
|
+
process.stdin.setEncoding('utf8');
|
|
13
|
+
process.stdin.on('data', (chunk) => { data += chunk; });
|
|
14
|
+
process.stdin.on('end', () => resolve(data));
|
|
15
|
+
process.stdin.on('error', () => resolve(''));
|
|
16
|
+
if (process.stdin.isTTY)
|
|
17
|
+
resolve('');
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
function safeParse(raw) {
|
|
21
|
+
if (!raw || raw.trim() === '')
|
|
22
|
+
return null;
|
|
23
|
+
// eslint-disable-next-line @webpieces/no-unmanaged-exceptions
|
|
24
|
+
try {
|
|
25
|
+
return JSON.parse(raw);
|
|
26
|
+
}
|
|
27
|
+
catch (err) {
|
|
28
|
+
const error = (0, to_error_1.toError)(err);
|
|
29
|
+
void error;
|
|
30
|
+
return null;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
function normalizeToolKind(toolName) {
|
|
34
|
+
if (HANDLED_FILE_TOOLS.has(toolName))
|
|
35
|
+
return toolName;
|
|
36
|
+
return null;
|
|
37
|
+
}
|
|
38
|
+
function normalizeToolInput(toolKind, toolInput) {
|
|
39
|
+
const filePath = toolInput.file_path;
|
|
40
|
+
if (!filePath)
|
|
41
|
+
return null;
|
|
42
|
+
if (toolKind === 'Write') {
|
|
43
|
+
return new types_1.NormalizedToolInput(filePath, [
|
|
44
|
+
new types_1.NormalizedEdit('', toolInput.content || ''),
|
|
45
|
+
]);
|
|
46
|
+
}
|
|
47
|
+
if (toolKind === 'Edit') {
|
|
48
|
+
return new types_1.NormalizedToolInput(filePath, [
|
|
49
|
+
new types_1.NormalizedEdit(toolInput.old_string || '', toolInput.new_string || ''),
|
|
50
|
+
]);
|
|
51
|
+
}
|
|
52
|
+
if (toolKind === 'MultiEdit') {
|
|
53
|
+
const raw = Array.isArray(toolInput.edits) ? toolInput.edits : [];
|
|
54
|
+
const edits = raw.map((e) => new types_1.NormalizedEdit(e.old_string || '', e.new_string || ''));
|
|
55
|
+
return new types_1.NormalizedToolInput(filePath, edits);
|
|
56
|
+
}
|
|
57
|
+
return null;
|
|
58
|
+
}
|
|
59
|
+
async function main() {
|
|
60
|
+
// eslint-disable-next-line @webpieces/no-unmanaged-exceptions
|
|
61
|
+
try {
|
|
62
|
+
const raw = await readStdin();
|
|
63
|
+
const payload = safeParse(raw);
|
|
64
|
+
if (!payload) {
|
|
65
|
+
process.exit(0);
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
const cwd = process.cwd();
|
|
69
|
+
if (payload.tool_name === 'Bash') {
|
|
70
|
+
const command = payload.tool_input.command;
|
|
71
|
+
if (!command || command.trim() === '') {
|
|
72
|
+
process.exit(0);
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
const result = (0, runner_1.runBash)(command, cwd);
|
|
76
|
+
if (!result) {
|
|
77
|
+
process.exit(0);
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
process.stderr.write(result.report);
|
|
81
|
+
process.exit(2);
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
const toolKind = normalizeToolKind(payload.tool_name);
|
|
85
|
+
if (!toolKind) {
|
|
86
|
+
process.exit(0);
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
const input = normalizeToolInput(toolKind, payload.tool_input);
|
|
90
|
+
if (!input) {
|
|
91
|
+
process.exit(0);
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
const result = (0, runner_1.run)(toolKind, input, cwd);
|
|
95
|
+
if (!result) {
|
|
96
|
+
process.exit(0);
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
(0, rejection_log_1.logRejection)(toolKind, input, result, cwd);
|
|
100
|
+
process.stderr.write(result.report);
|
|
101
|
+
process.exit(2);
|
|
102
|
+
}
|
|
103
|
+
catch (err) {
|
|
104
|
+
const error = (0, to_error_1.toError)(err);
|
|
105
|
+
process.stderr.write(`[ai-hooks] claude-code adapter crashed (failing open): ${error.message}\n`);
|
|
106
|
+
process.exit(0);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
if (require.main === module) {
|
|
110
|
+
main();
|
|
111
|
+
}
|
|
112
|
+
//# sourceMappingURL=claude-code-hook.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"claude-code-hook.js","sourceRoot":"","sources":["../../../../../../packages/tooling/ai-hook-rules/src/adapters/claude-code-hook.ts"],"names":[],"mappings":"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","sourcesContent":["import { run, runBash } from '../core/runner';\nimport { logRejection } from '../core/rejection-log';\nimport { NormalizedToolInput, NormalizedEdit, ToolKind } from '../core/types';\nimport { toError } from '../core/to-error';\n\nconst HANDLED_FILE_TOOLS = new Set(['Write', 'Edit', 'MultiEdit']);\n\ninterface ClaudeCodePayload {\n tool_name: string;\n tool_input: ClaudeCodeToolInput;\n}\n\ninterface ClaudeCodeToolInput {\n file_path?: string;\n content?: string;\n old_string?: string;\n new_string?: string;\n edits?: ClaudeCodeEditEntry[];\n command?: string;\n}\n\ninterface ClaudeCodeEditEntry {\n old_string?: string;\n new_string?: string;\n}\n\nfunction readStdin(): Promise<string> {\n return new Promise((resolve) => {\n let data = '';\n process.stdin.setEncoding('utf8');\n process.stdin.on('data', (chunk: string) => { data += chunk; });\n process.stdin.on('end', () => resolve(data));\n process.stdin.on('error', () => resolve(''));\n if (process.stdin.isTTY) resolve('');\n });\n}\n\nfunction safeParse(raw: string): ClaudeCodePayload | null {\n if (!raw || raw.trim() === '') return null;\n // eslint-disable-next-line @webpieces/no-unmanaged-exceptions\n try {\n return JSON.parse(raw) as ClaudeCodePayload;\n } catch (err: unknown) {\n const error = toError(err);\n void error;\n return null;\n }\n}\n\nfunction normalizeToolKind(toolName: string): ToolKind | null {\n if (HANDLED_FILE_TOOLS.has(toolName)) return toolName as ToolKind;\n return null;\n}\n\nfunction normalizeToolInput(toolKind: ToolKind, toolInput: ClaudeCodeToolInput): NormalizedToolInput | null {\n const filePath = toolInput.file_path;\n if (!filePath) return null;\n\n if (toolKind === 'Write') {\n return new NormalizedToolInput(filePath, [\n new NormalizedEdit('', toolInput.content || ''),\n ]);\n }\n if (toolKind === 'Edit') {\n return new NormalizedToolInput(filePath, [\n new NormalizedEdit(toolInput.old_string || '', toolInput.new_string || ''),\n ]);\n }\n if (toolKind === 'MultiEdit') {\n const raw = Array.isArray(toolInput.edits) ? toolInput.edits : [];\n const edits = raw.map((e) => new NormalizedEdit(e.old_string || '', e.new_string || ''));\n return new NormalizedToolInput(filePath, edits);\n }\n return null;\n}\n\nexport async function main(): Promise<void> {\n // eslint-disable-next-line @webpieces/no-unmanaged-exceptions\n try {\n const raw = await readStdin();\n const payload = safeParse(raw);\n if (!payload) { process.exit(0); return; }\n\n const cwd = process.cwd();\n\n if (payload.tool_name === 'Bash') {\n const command = payload.tool_input.command;\n if (!command || command.trim() === '') { process.exit(0); return; }\n const result = runBash(command, cwd);\n if (!result) { process.exit(0); return; }\n process.stderr.write(result.report);\n process.exit(2);\n return;\n }\n\n const toolKind = normalizeToolKind(payload.tool_name);\n if (!toolKind) { process.exit(0); return; }\n\n const input = normalizeToolInput(toolKind, payload.tool_input);\n if (!input) { process.exit(0); return; }\n\n const result = run(toolKind, input, cwd);\n if (!result) { process.exit(0); return; }\n\n logRejection(toolKind, input, result, cwd);\n process.stderr.write(result.report);\n process.exit(2);\n } catch (err: unknown) {\n const error = toError(err);\n process.stderr.write(`[ai-hooks] claude-code adapter crashed (failing open): ${error.message}\\n`);\n process.exit(0);\n }\n}\n\nif (require.main === module) {\n main();\n}\n"]}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
interface ToolCallEvent {
|
|
2
|
+
toolName: string;
|
|
3
|
+
arguments: Record<string, unknown>;
|
|
4
|
+
}
|
|
5
|
+
interface HookContext {
|
|
6
|
+
[key: string]: unknown;
|
|
7
|
+
}
|
|
8
|
+
declare class OpenclawHandlerResult {
|
|
9
|
+
readonly status: 'approved' | 'rejected';
|
|
10
|
+
readonly reason: string | undefined;
|
|
11
|
+
constructor(status: 'approved' | 'rejected', reason?: string);
|
|
12
|
+
}
|
|
13
|
+
export default function handler(event: ToolCallEvent, _context: HookContext): Promise<OpenclawHandlerResult | undefined>;
|
|
14
|
+
export {};
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.default = handler;
|
|
4
|
+
const tslib_1 = require("tslib");
|
|
5
|
+
const path = tslib_1.__importStar(require("path"));
|
|
6
|
+
const fs = tslib_1.__importStar(require("fs"));
|
|
7
|
+
const runner_1 = require("../core/runner");
|
|
8
|
+
const types_1 = require("../core/types");
|
|
9
|
+
const to_error_1 = require("../core/to-error");
|
|
10
|
+
class OpenclawHandlerResult {
|
|
11
|
+
constructor(status, reason) {
|
|
12
|
+
this.status = status;
|
|
13
|
+
this.reason = reason;
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
const TOOL_MAP = {
|
|
17
|
+
'write': 'Write',
|
|
18
|
+
'edit': 'Edit',
|
|
19
|
+
};
|
|
20
|
+
function mapToolName(openclawName) {
|
|
21
|
+
return TOOL_MAP[openclawName] || null;
|
|
22
|
+
}
|
|
23
|
+
// webpieces-disable no-any-unknown -- openclaw SDK passes opaque tool arguments
|
|
24
|
+
function mapToolInput(toolName, args) {
|
|
25
|
+
const filePath = typeof args['path'] === 'string' ? args['path'] : null;
|
|
26
|
+
if (!filePath)
|
|
27
|
+
return null;
|
|
28
|
+
if (toolName === 'write') {
|
|
29
|
+
const content = typeof args['content'] === 'string' ? args['content'] : '';
|
|
30
|
+
return new types_1.NormalizedToolInput(filePath, [new types_1.NormalizedEdit('', content)]);
|
|
31
|
+
}
|
|
32
|
+
if (toolName === 'edit') {
|
|
33
|
+
const oldStr = typeof args['old_string'] === 'string' ? args['old_string'] : '';
|
|
34
|
+
const newStr = typeof args['new_string'] === 'string' ? args['new_string'] : '';
|
|
35
|
+
return new types_1.NormalizedToolInput(filePath, [new types_1.NormalizedEdit(oldStr, newStr)]);
|
|
36
|
+
}
|
|
37
|
+
return null;
|
|
38
|
+
}
|
|
39
|
+
function findWorkspaceRoot(filePath) {
|
|
40
|
+
let dir = path.dirname(filePath);
|
|
41
|
+
while (true) {
|
|
42
|
+
if (fs.existsSync(path.join(dir, 'webpieces.ai-hooks.json')))
|
|
43
|
+
return dir;
|
|
44
|
+
const parent = path.dirname(dir);
|
|
45
|
+
if (parent === dir)
|
|
46
|
+
return null;
|
|
47
|
+
dir = parent;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
async function handler(event, _context) {
|
|
51
|
+
// eslint-disable-next-line @webpieces/no-unmanaged-exceptions
|
|
52
|
+
try {
|
|
53
|
+
const toolKind = mapToolName(event.toolName);
|
|
54
|
+
if (!toolKind)
|
|
55
|
+
return undefined;
|
|
56
|
+
const input = mapToolInput(event.toolName, event.arguments);
|
|
57
|
+
if (!input)
|
|
58
|
+
return undefined;
|
|
59
|
+
const wsRoot = findWorkspaceRoot(input.filePath);
|
|
60
|
+
if (!wsRoot)
|
|
61
|
+
return undefined;
|
|
62
|
+
const result = (0, runner_1.run)(toolKind, input, wsRoot);
|
|
63
|
+
if (!result)
|
|
64
|
+
return new OpenclawHandlerResult('approved');
|
|
65
|
+
return new OpenclawHandlerResult('rejected', result.report);
|
|
66
|
+
}
|
|
67
|
+
catch (err) {
|
|
68
|
+
const error = (0, to_error_1.toError)(err);
|
|
69
|
+
console.error(`[ai-hooks] openclaw adapter crashed (failing open): ${error.message}`);
|
|
70
|
+
return undefined;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
//# sourceMappingURL=openclaw-plugin.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"openclaw-plugin.js","sourceRoot":"","sources":["../../../../../../packages/tooling/ai-hook-rules/src/adapters/openclaw-plugin.ts"],"names":[],"mappings":"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","sourcesContent":["import * as path from 'path';\nimport * as fs from 'fs';\n\nimport { run } from '../core/runner';\nimport { NormalizedToolInput, NormalizedEdit, ToolKind } from '../core/types';\nimport { toError } from '../core/to-error';\n\ninterface ToolCallEvent {\n toolName: string;\n // webpieces-disable no-any-unknown -- openclaw SDK passes opaque tool arguments\n arguments: Record<string, unknown>;\n}\n\ninterface HookContext {\n // webpieces-disable no-any-unknown -- openclaw SDK context shape is opaque\n [key: string]: unknown;\n}\n\nclass OpenclawHandlerResult {\n readonly status: 'approved' | 'rejected';\n readonly reason: string | undefined;\n\n constructor(status: 'approved' | 'rejected', reason?: string) {\n this.status = status;\n this.reason = reason;\n }\n}\n\nconst TOOL_MAP: Record<string, ToolKind> = {\n 'write': 'Write',\n 'edit': 'Edit',\n};\n\nfunction mapToolName(openclawName: string): ToolKind | null {\n return TOOL_MAP[openclawName] || null;\n}\n\n// webpieces-disable no-any-unknown -- openclaw SDK passes opaque tool arguments\nfunction mapToolInput(toolName: string, args: Record<string, unknown>): NormalizedToolInput | null {\n const filePath = typeof args['path'] === 'string' ? args['path'] as string : null;\n if (!filePath) return null;\n\n if (toolName === 'write') {\n const content = typeof args['content'] === 'string' ? args['content'] as string : '';\n return new NormalizedToolInput(filePath, [new NormalizedEdit('', content)]);\n }\n if (toolName === 'edit') {\n const oldStr = typeof args['old_string'] === 'string' ? args['old_string'] as string : '';\n const newStr = typeof args['new_string'] === 'string' ? args['new_string'] as string : '';\n return new NormalizedToolInput(filePath, [new NormalizedEdit(oldStr, newStr)]);\n }\n return null;\n}\n\nfunction findWorkspaceRoot(filePath: string): string | null {\n let dir = path.dirname(filePath);\n while (true) {\n if (fs.existsSync(path.join(dir, 'webpieces.ai-hooks.json'))) return dir;\n const parent = path.dirname(dir);\n if (parent === dir) return null;\n dir = parent;\n }\n}\n\nexport default async function handler(\n event: ToolCallEvent,\n _context: HookContext,\n): Promise<OpenclawHandlerResult | undefined> {\n // eslint-disable-next-line @webpieces/no-unmanaged-exceptions\n try {\n const toolKind = mapToolName(event.toolName);\n if (!toolKind) return undefined;\n\n const input = mapToolInput(event.toolName, event.arguments);\n if (!input) return undefined;\n\n const wsRoot = findWorkspaceRoot(input.filePath);\n if (!wsRoot) return undefined;\n\n const result = run(toolKind, input, wsRoot);\n if (!result) return new OpenclawHandlerResult('approved');\n return new OpenclawHandlerResult('rejected', result.report);\n } catch (err: unknown) {\n const error = toError(err);\n console.error(`[ai-hooks] openclaw adapter crashed (failing open): ${error.message}`);\n return undefined;\n }\n}\n"]}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { ToolKind, NormalizedToolInput, EditContext, FileContext, BashContext } from './types';
|
|
2
|
+
export declare class BuiltContexts {
|
|
3
|
+
readonly fileContext: FileContext;
|
|
4
|
+
readonly editContexts: readonly EditContext[];
|
|
5
|
+
constructor(fileContext: FileContext, editContexts: readonly EditContext[]);
|
|
6
|
+
}
|
|
7
|
+
export declare function buildContexts(toolKind: ToolKind, input: NormalizedToolInput, workspaceRoot: string): BuiltContexts;
|
|
8
|
+
export declare function buildBashContext(command: string, workspaceRoot: string): BashContext;
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.BuiltContexts = void 0;
|
|
4
|
+
exports.buildContexts = buildContexts;
|
|
5
|
+
exports.buildBashContext = buildBashContext;
|
|
6
|
+
const tslib_1 = require("tslib");
|
|
7
|
+
const fs = tslib_1.__importStar(require("fs"));
|
|
8
|
+
const path = tslib_1.__importStar(require("path"));
|
|
9
|
+
const strip_ts_noise_1 = require("./strip-ts-noise");
|
|
10
|
+
const disable_directives_1 = require("./disable-directives");
|
|
11
|
+
const types_1 = require("./types");
|
|
12
|
+
class BuiltContexts {
|
|
13
|
+
constructor(fileContext, editContexts) {
|
|
14
|
+
this.fileContext = fileContext;
|
|
15
|
+
this.editContexts = editContexts;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
exports.BuiltContexts = BuiltContexts;
|
|
19
|
+
function buildContexts(toolKind, input, workspaceRoot) {
|
|
20
|
+
const filePath = input.filePath;
|
|
21
|
+
const relativePath = path.relative(workspaceRoot, filePath);
|
|
22
|
+
const edits = input.edits;
|
|
23
|
+
const currentFileLines = readCurrentFileLines(filePath);
|
|
24
|
+
let linesAdded = 0;
|
|
25
|
+
let linesRemoved = 0;
|
|
26
|
+
for (const e of edits) {
|
|
27
|
+
linesAdded += countLines(e.newString);
|
|
28
|
+
linesRemoved += countLines(e.oldString);
|
|
29
|
+
}
|
|
30
|
+
const projectedFileLines = toolKind === 'Write'
|
|
31
|
+
? countLines(edits.length > 0 ? edits[0].newString : '')
|
|
32
|
+
: currentFileLines + linesAdded - linesRemoved;
|
|
33
|
+
const fileContext = new types_1.FileContext(toolKind, filePath, relativePath, workspaceRoot, currentFileLines, linesAdded, linesRemoved, projectedFileLines);
|
|
34
|
+
const editContexts = edits.map((e, idx) => {
|
|
35
|
+
const addedContent = e.newString;
|
|
36
|
+
const stripped = (0, strip_ts_noise_1.stripTsNoise)(addedContent);
|
|
37
|
+
const isLineDisabled = (0, disable_directives_1.createIsLineDisabled)(addedContent);
|
|
38
|
+
return new types_1.EditContext(toolKind, idx, edits.length, filePath, relativePath, workspaceRoot, addedContent, stripped, addedContent.split('\n'), stripped.split('\n'), e.oldString, isLineDisabled);
|
|
39
|
+
});
|
|
40
|
+
return new BuiltContexts(fileContext, editContexts);
|
|
41
|
+
}
|
|
42
|
+
function buildBashContext(command, workspaceRoot) {
|
|
43
|
+
return new types_1.BashContext(command, workspaceRoot);
|
|
44
|
+
}
|
|
45
|
+
function readCurrentFileLines(filePath) {
|
|
46
|
+
// eslint-disable-next-line @webpieces/no-unmanaged-exceptions
|
|
47
|
+
try {
|
|
48
|
+
const content = fs.readFileSync(filePath, 'utf8');
|
|
49
|
+
return countLines(content);
|
|
50
|
+
}
|
|
51
|
+
catch (err) {
|
|
52
|
+
// eslint-disable-next-line @webpieces/catch-error-pattern -- file-not-found is expected for new Write targets
|
|
53
|
+
void err;
|
|
54
|
+
return 0;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
function countLines(s) {
|
|
58
|
+
if (!s)
|
|
59
|
+
return 0;
|
|
60
|
+
return s.split('\n').length;
|
|
61
|
+
}
|
|
62
|
+
//# sourceMappingURL=build-context.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"build-context.js","sourceRoot":"","sources":["../../../../../../packages/tooling/ai-hook-rules/src/core/build-context.ts"],"names":[],"mappings":"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","sourcesContent":["import * as fs from 'fs';\nimport * as path from 'path';\n\nimport { stripTsNoise } from './strip-ts-noise';\nimport { createIsLineDisabled } from './disable-directives';\nimport {\n ToolKind, NormalizedToolInput, NormalizedEdit,\n EditContext, FileContext, BashContext,\n} from './types';\n\nexport class BuiltContexts {\n readonly fileContext: FileContext;\n readonly editContexts: readonly EditContext[];\n\n constructor(fileContext: FileContext, editContexts: readonly EditContext[]) {\n this.fileContext = fileContext;\n this.editContexts = editContexts;\n }\n}\n\nexport function buildContexts(\n toolKind: ToolKind,\n input: NormalizedToolInput,\n workspaceRoot: string,\n): BuiltContexts {\n const filePath = input.filePath;\n const relativePath = path.relative(workspaceRoot, filePath);\n const edits = input.edits;\n\n const currentFileLines = readCurrentFileLines(filePath);\n let linesAdded = 0;\n let linesRemoved = 0;\n for (const e of edits) {\n linesAdded += countLines(e.newString);\n linesRemoved += countLines(e.oldString);\n }\n\n const projectedFileLines =\n toolKind === 'Write'\n ? countLines(edits.length > 0 ? edits[0].newString : '')\n : currentFileLines + linesAdded - linesRemoved;\n\n const fileContext = new FileContext(\n toolKind,\n filePath,\n relativePath,\n workspaceRoot,\n currentFileLines,\n linesAdded,\n linesRemoved,\n projectedFileLines,\n );\n\n const editContexts = edits.map((e, idx) => {\n const addedContent = e.newString;\n const stripped = stripTsNoise(addedContent);\n const isLineDisabled = createIsLineDisabled(addedContent);\n return new EditContext(\n toolKind,\n idx,\n edits.length,\n filePath,\n relativePath,\n workspaceRoot,\n addedContent,\n stripped,\n addedContent.split('\\n'),\n stripped.split('\\n'),\n e.oldString,\n isLineDisabled,\n );\n });\n\n return new BuiltContexts(fileContext, editContexts);\n}\n\nexport function buildBashContext(command: string, workspaceRoot: string): BashContext {\n return new BashContext(command, workspaceRoot);\n}\n\nfunction readCurrentFileLines(filePath: string): number {\n // eslint-disable-next-line @webpieces/no-unmanaged-exceptions\n try {\n const content = fs.readFileSync(filePath, 'utf8');\n return countLines(content);\n } catch (err: unknown) {\n // eslint-disable-next-line @webpieces/catch-error-pattern -- file-not-found is expected for new Write targets\n void err;\n return 0;\n }\n}\n\nfunction countLines(s: string): number {\n if (!s) return 0;\n return s.split('\\n').length;\n}\n"]}
|
|
@@ -1,5 +1,8 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.defaultRulesDir = exports.defaultRules = void 0;
|
|
1
4
|
// webpieces-disable no-any-unknown -- rule options are opaque at framework level
|
|
2
|
-
|
|
5
|
+
exports.defaultRules = {
|
|
3
6
|
'no-any-unknown': { enabled: true },
|
|
4
7
|
'max-file-lines': { enabled: true, limit: 900 },
|
|
5
8
|
'file-location': {
|
|
@@ -15,5 +18,5 @@ export const defaultRules: Record<string, Record<string, unknown>> = {
|
|
|
15
18
|
'no-unmanaged-exceptions': { enabled: true },
|
|
16
19
|
'catch-error-pattern': { enabled: true },
|
|
17
20
|
};
|
|
18
|
-
|
|
19
|
-
|
|
21
|
+
exports.defaultRulesDir = [];
|
|
22
|
+
//# sourceMappingURL=default.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"default.js","sourceRoot":"","sources":["../../../../../../../packages/tooling/ai-hook-rules/src/core/configs/default.ts"],"names":[],"mappings":";;;AAAA,iFAAiF;AACpE,QAAA,YAAY,GAA4C;IACjE,gBAAgB,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE;IACnC,gBAAgB,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,EAAE;IAC/C,eAAe,EAAE;QACb,OAAO,EAAE,IAAI;QACb,gBAAgB,EAAE,CAAC,eAAe,CAAC;QACnC,YAAY,EAAE;YACV,cAAc,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM;YACrC,cAAc,EAAE,KAAK,EAAE,SAAS;SACnC;KACJ;IACD,gBAAgB,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,aAAa,EAAE,IAAI,EAAE;IACxD,qBAAqB,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE;IACxC,yBAAyB,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE;IAC5C,qBAAqB,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE;CAC3C,CAAC;AAEW,QAAA,eAAe,GAAsB,EAAE,CAAC","sourcesContent":["// webpieces-disable no-any-unknown -- rule options are opaque at framework level\nexport const defaultRules: Record<string, Record<string, unknown>> = {\n 'no-any-unknown': { enabled: true },\n 'max-file-lines': { enabled: true, limit: 900 },\n 'file-location': {\n enabled: true,\n allowedRootFiles: ['jest.setup.ts'],\n excludePaths: [\n 'node_modules', 'dist', '.nx', '.git',\n 'architecture', 'tmp', 'scripts',\n ],\n },\n 'no-destructure': { enabled: true, allowTopLevel: true },\n 'require-return-type': { enabled: true },\n 'no-unmanaged-exceptions': { enabled: true },\n 'catch-error-pattern': { enabled: true },\n};\n\nexport const defaultRulesDir: readonly string[] = [];\n"]}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { IsLineDisabled } from './types';
|
|
2
|
+
export declare class DirectiveIndex {
|
|
3
|
+
private readonly lineDisables;
|
|
4
|
+
private readonly fileDisables;
|
|
5
|
+
constructor(lineDisables: Map<number, Set<string>>, fileDisables: Set<string>);
|
|
6
|
+
isLineDisabled(lineNum: number, ruleName: string): boolean;
|
|
7
|
+
}
|
|
8
|
+
export declare function parseDirectives(source: string): DirectiveIndex;
|
|
9
|
+
export declare function createIsLineDisabled(source: string): IsLineDisabled;
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.DirectiveIndex = void 0;
|
|
4
|
+
exports.parseDirectives = parseDirectives;
|
|
5
|
+
exports.createIsLineDisabled = createIsLineDisabled;
|
|
6
|
+
const DIRECTIVE_RE = /\/\/\s*(?:ai-hook-disable|webpieces-disable)(?:-(next|file|all))?(?:\s+([\w\-*,\s]+?))?(?:\s*--\s*(.*))?\s*$/;
|
|
7
|
+
class DirectiveIndex {
|
|
8
|
+
constructor(lineDisables, fileDisables) {
|
|
9
|
+
this.lineDisables = lineDisables;
|
|
10
|
+
this.fileDisables = fileDisables;
|
|
11
|
+
}
|
|
12
|
+
isLineDisabled(lineNum, ruleName) {
|
|
13
|
+
if (this.fileDisables.has('*') || this.fileDisables.has(ruleName))
|
|
14
|
+
return true;
|
|
15
|
+
const set = this.lineDisables.get(lineNum);
|
|
16
|
+
if (!set)
|
|
17
|
+
return false;
|
|
18
|
+
return set.has('*') || set.has(ruleName);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
exports.DirectiveIndex = DirectiveIndex;
|
|
22
|
+
function parseRuleList(raw) {
|
|
23
|
+
if (!raw || raw.trim() === '' || raw.trim() === '*')
|
|
24
|
+
return ['*'];
|
|
25
|
+
return raw.split(',').map((s) => s.trim()).filter((s) => s.length > 0);
|
|
26
|
+
}
|
|
27
|
+
function nextTargetLine(lines, lineIdx) {
|
|
28
|
+
for (let j = lineIdx + 1; j < lines.length; j += 1) {
|
|
29
|
+
const trimmed = lines[j].trim();
|
|
30
|
+
if (trimmed === '')
|
|
31
|
+
continue;
|
|
32
|
+
if (/^\/\/\s*(?:ai-hook-disable|webpieces-disable)/.test(trimmed))
|
|
33
|
+
continue;
|
|
34
|
+
return j + 1;
|
|
35
|
+
}
|
|
36
|
+
return null;
|
|
37
|
+
}
|
|
38
|
+
function addDisable(map, lineNum, rules) {
|
|
39
|
+
if (!map.has(lineNum))
|
|
40
|
+
map.set(lineNum, new Set());
|
|
41
|
+
const set = map.get(lineNum);
|
|
42
|
+
for (const r of rules)
|
|
43
|
+
set.add(r);
|
|
44
|
+
}
|
|
45
|
+
function resolveTarget(line, lines, i, map, rules) {
|
|
46
|
+
const beforeComment = line.slice(0, line.indexOf('//')).trim();
|
|
47
|
+
if (beforeComment !== '') {
|
|
48
|
+
addDisable(map, i + 1, rules);
|
|
49
|
+
}
|
|
50
|
+
else {
|
|
51
|
+
const target = nextTargetLine(lines, i);
|
|
52
|
+
if (target !== null)
|
|
53
|
+
addDisable(map, target, rules);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
function parseDirectives(source) {
|
|
57
|
+
const lines = source.split('\n');
|
|
58
|
+
const lineDisables = new Map();
|
|
59
|
+
const fileDisables = new Set();
|
|
60
|
+
for (let i = 0; i < lines.length; i += 1) {
|
|
61
|
+
const line = lines[i];
|
|
62
|
+
const match = line.match(DIRECTIVE_RE);
|
|
63
|
+
if (!match)
|
|
64
|
+
continue;
|
|
65
|
+
const variant = match[1] || null;
|
|
66
|
+
const rules = parseRuleList(match[2] || '');
|
|
67
|
+
if (variant === 'file') {
|
|
68
|
+
if (i < 20) {
|
|
69
|
+
for (const r of rules)
|
|
70
|
+
fileDisables.add(r);
|
|
71
|
+
}
|
|
72
|
+
continue;
|
|
73
|
+
}
|
|
74
|
+
if (variant === 'next') {
|
|
75
|
+
const target = nextTargetLine(lines, i);
|
|
76
|
+
if (target !== null)
|
|
77
|
+
addDisable(lineDisables, target, rules);
|
|
78
|
+
continue;
|
|
79
|
+
}
|
|
80
|
+
if (variant === 'all') {
|
|
81
|
+
resolveTarget(line, lines, i, lineDisables, ['*']);
|
|
82
|
+
continue;
|
|
83
|
+
}
|
|
84
|
+
resolveTarget(line, lines, i, lineDisables, rules);
|
|
85
|
+
}
|
|
86
|
+
return new DirectiveIndex(lineDisables, fileDisables);
|
|
87
|
+
}
|
|
88
|
+
function createIsLineDisabled(source) {
|
|
89
|
+
const index = parseDirectives(source);
|
|
90
|
+
return (lineNum, ruleName) => index.isLineDisabled(lineNum, ruleName);
|
|
91
|
+
}
|
|
92
|
+
//# sourceMappingURL=disable-directives.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"disable-directives.js","sourceRoot":"","sources":["../../../../../../packages/tooling/ai-hook-rules/src/core/disable-directives.ts"],"names":[],"mappings":"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","sourcesContent":["import type { IsLineDisabled } from './types';\n\nconst DIRECTIVE_RE =\n /\\/\\/\\s*(?:ai-hook-disable|webpieces-disable)(?:-(next|file|all))?(?:\\s+([\\w\\-*,\\s]+?))?(?:\\s*--\\s*(.*))?\\s*$/;\n\nexport class DirectiveIndex {\n private readonly lineDisables: Map<number, Set<string>>;\n private readonly fileDisables: Set<string>;\n\n constructor(lineDisables: Map<number, Set<string>>, fileDisables: Set<string>) {\n this.lineDisables = lineDisables;\n this.fileDisables = fileDisables;\n }\n\n isLineDisabled(lineNum: number, ruleName: string): boolean {\n if (this.fileDisables.has('*') || this.fileDisables.has(ruleName)) return true;\n const set = this.lineDisables.get(lineNum);\n if (!set) return false;\n return set.has('*') || set.has(ruleName);\n }\n}\n\nfunction parseRuleList(raw: string | undefined): readonly string[] {\n if (!raw || raw.trim() === '' || raw.trim() === '*') return ['*'];\n return raw.split(',').map((s) => s.trim()).filter((s) => s.length > 0);\n}\n\nfunction nextTargetLine(lines: readonly string[], lineIdx: number): number | null {\n for (let j = lineIdx + 1; j < lines.length; j += 1) {\n const trimmed = lines[j].trim();\n if (trimmed === '') continue;\n if (/^\\/\\/\\s*(?:ai-hook-disable|webpieces-disable)/.test(trimmed)) continue;\n return j + 1;\n }\n return null;\n}\n\nfunction addDisable(map: Map<number, Set<string>>, lineNum: number, rules: readonly string[]): void {\n if (!map.has(lineNum)) map.set(lineNum, new Set<string>());\n const set = map.get(lineNum)!;\n for (const r of rules) set.add(r);\n}\n\nfunction resolveTarget(\n line: string, lines: readonly string[], i: number,\n map: Map<number, Set<string>>, rules: readonly string[],\n): void {\n const beforeComment = line.slice(0, line.indexOf('//')).trim();\n if (beforeComment !== '') {\n addDisable(map, i + 1, rules);\n } else {\n const target = nextTargetLine(lines, i);\n if (target !== null) addDisable(map, target, rules);\n }\n}\n\nexport function parseDirectives(source: string): DirectiveIndex {\n const lines = source.split('\\n');\n const lineDisables = new Map<number, Set<string>>();\n const fileDisables = new Set<string>();\n\n for (let i = 0; i < lines.length; i += 1) {\n const line = lines[i];\n const match = line.match(DIRECTIVE_RE);\n if (!match) continue;\n const variant = match[1] || null;\n const rules = parseRuleList(match[2] || '');\n\n if (variant === 'file') {\n if (i < 20) { for (const r of rules) fileDisables.add(r); }\n continue;\n }\n if (variant === 'next') {\n const target = nextTargetLine(lines, i);\n if (target !== null) addDisable(lineDisables, target, rules);\n continue;\n }\n if (variant === 'all') {\n resolveTarget(line, lines, i, lineDisables, ['*']);\n continue;\n }\n resolveTarget(line, lines, i, lineDisables, rules);\n }\n return new DirectiveIndex(lineDisables, fileDisables);\n}\n\nexport function createIsLineDisabled(source: string): IsLineDisabled {\n const index = parseDirectives(source);\n return (lineNum: number, ruleName: string): boolean => index.isLineDisabled(lineNum, ruleName);\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function writeTemplateIfMissing(workspaceRoot: string, templateName: string): void;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.writeTemplateIfMissing = writeTemplateIfMissing;
|
|
4
|
+
const tslib_1 = require("tslib");
|
|
5
|
+
const fs = tslib_1.__importStar(require("fs"));
|
|
6
|
+
const path = tslib_1.__importStar(require("path"));
|
|
7
|
+
const INSTRUCT_DIR = '.webpieces/instruct-ai';
|
|
8
|
+
function writeTemplateIfMissing(workspaceRoot, templateName) {
|
|
9
|
+
const dir = path.join(workspaceRoot, INSTRUCT_DIR);
|
|
10
|
+
const filePath = path.join(dir, templateName);
|
|
11
|
+
if (fs.existsSync(filePath))
|
|
12
|
+
return;
|
|
13
|
+
const templatePath = path.join(__dirname, '..', '..', 'templates', templateName);
|
|
14
|
+
const content = fs.readFileSync(templatePath, 'utf-8');
|
|
15
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
16
|
+
fs.writeFileSync(filePath, content);
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=instruct-ai-writer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"instruct-ai-writer.js","sourceRoot":"","sources":["../../../../../../packages/tooling/ai-hook-rules/src/core/instruct-ai-writer.ts"],"names":[],"mappings":";;AAKA,wDASC;;AAdD,+CAAyB;AACzB,mDAA6B;AAE7B,MAAM,YAAY,GAAG,wBAAwB,CAAC;AAE9C,SAAgB,sBAAsB,CAAC,aAAqB,EAAE,YAAoB;IAC9E,MAAM,GAAG,GAAG,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE,YAAY,CAAC,CAAC;IACnD,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,YAAY,CAAC,CAAC;IAC9C,IAAI,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC;QAAE,OAAO;IAEpC,MAAM,YAAY,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,WAAW,EAAE,YAAY,CAAC,CAAC;IACjF,MAAM,OAAO,GAAG,EAAE,CAAC,YAAY,CAAC,YAAY,EAAE,OAAO,CAAC,CAAC;IACvD,EAAE,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACvC,EAAE,CAAC,aAAa,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;AACxC,CAAC","sourcesContent":["import * as fs from 'fs';\nimport * as path from 'path';\n\nconst INSTRUCT_DIR = '.webpieces/instruct-ai';\n\nexport function writeTemplateIfMissing(workspaceRoot: string, templateName: string): void {\n const dir = path.join(workspaceRoot, INSTRUCT_DIR);\n const filePath = path.join(dir, templateName);\n if (fs.existsSync(filePath)) return;\n\n const templatePath = path.join(__dirname, '..', '..', 'templates', templateName);\n const content = fs.readFileSync(templatePath, 'utf-8');\n fs.mkdirSync(dir, { recursive: true });\n fs.writeFileSync(filePath, content);\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { loadConfig, findConfigFile, CONFIG_FILENAME } from '@webpieces/rules-config';
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.CONFIG_FILENAME = exports.findConfigFile = exports.loadConfig = void 0;
|
|
4
|
+
// Re-export the shared workspace config loader so ai-hooks and the Nx
|
|
5
|
+
// validate-code executor use the same webpieces.config.json.
|
|
6
|
+
var rules_config_1 = require("@webpieces/rules-config");
|
|
7
|
+
Object.defineProperty(exports, "loadConfig", { enumerable: true, get: function () { return rules_config_1.loadConfig; } });
|
|
8
|
+
Object.defineProperty(exports, "findConfigFile", { enumerable: true, get: function () { return rules_config_1.findConfigFile; } });
|
|
9
|
+
Object.defineProperty(exports, "CONFIG_FILENAME", { enumerable: true, get: function () { return rules_config_1.CONFIG_FILENAME; } });
|
|
10
|
+
//# sourceMappingURL=load-config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"load-config.js","sourceRoot":"","sources":["../../../../../../packages/tooling/ai-hook-rules/src/core/load-config.ts"],"names":[],"mappings":";;;AAAA,sEAAsE;AACtE,6DAA6D;AAC7D,wDAAsF;AAA7E,0GAAA,UAAU,OAAA;AAAE,8GAAA,cAAc,OAAA;AAAE,+GAAA,eAAe,OAAA","sourcesContent":["// Re-export the shared workspace config loader so ai-hooks and the Nx\n// validate-code executor use the same webpieces.config.json.\nexport { loadConfig, findConfigFile, CONFIG_FILENAME } from '@webpieces/rules-config';\n"]}
|