atabey 0.0.13 → 0.0.15
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/ATABEY.md +1 -1
- package/PRIVACY.md +8 -14
- package/README.md +405 -56
- package/bin/cli.js +72 -5
- package/dist/framework-mcp/src/index.js +988 -63
- package/dist/framework-mcp/src/index.js.map +1 -1
- package/dist/framework-mcp/src/tools/compliance/mask_pii.d.ts +17 -0
- package/dist/framework-mcp/src/tools/compliance/mask_pii.js +56 -0
- package/dist/framework-mcp/src/tools/compliance/mask_pii.js.map +1 -0
- package/dist/framework-mcp/src/tools/definitions.js +10 -9
- package/dist/framework-mcp/src/tools/definitions.js.map +1 -1
- package/dist/framework-mcp/src/tools/framework/run_tests.js +25 -0
- package/dist/framework-mcp/src/tools/framework/run_tests.js.map +1 -1
- package/dist/framework-mcp/src/tools/index.js +7 -8
- package/dist/framework-mcp/src/tools/index.js.map +1 -1
- package/dist/framework-mcp/src/tools/messaging/approve_operation.d.ts +22 -0
- package/dist/framework-mcp/src/tools/messaging/approve_operation.js +81 -0
- package/dist/framework-mcp/src/tools/messaging/approve_operation.js.map +1 -0
- package/dist/framework-mcp/src/tools/messaging/ask_human.d.ts +15 -0
- package/dist/framework-mcp/src/tools/messaging/ask_human.js +89 -20
- package/dist/framework-mcp/src/tools/messaging/ask_human.js.map +1 -1
- package/dist/framework-mcp/src/tools/observability/check_ports.d.ts +1 -0
- package/dist/framework-mcp/src/tools/observability/check_ports.js +24 -8
- package/dist/framework-mcp/src/tools/observability/check_ports.js.map +1 -1
- package/dist/framework-mcp/src/tools/quality/analyze_code_quality.js +13 -64
- package/dist/framework-mcp/src/tools/quality/analyze_code_quality.js.map +1 -1
- package/dist/framework-mcp/src/tools/schemas.d.ts +48 -53
- package/dist/framework-mcp/src/tools/schemas.js +18 -22
- package/dist/framework-mcp/src/tools/schemas.js.map +1 -1
- package/dist/framework-mcp/src/tools/shell/run_command.js +146 -90
- package/dist/framework-mcp/src/tools/shell/run_command.js.map +1 -1
- package/dist/framework-mcp/src/tools/types.d.ts +11 -105
- package/dist/framework-mcp/src/tools/types.js +1 -0
- package/dist/framework-mcp/src/tools/types.js.map +1 -1
- package/dist/framework-mcp/src/utils/auth.d.ts +36 -0
- package/dist/framework-mcp/src/utils/auth.js +79 -0
- package/dist/framework-mcp/src/utils/auth.js.map +1 -0
- package/dist/framework-mcp/src/utils/auto-rollback.d.ts +71 -0
- package/dist/framework-mcp/src/utils/auto-rollback.js +266 -0
- package/dist/framework-mcp/src/utils/auto-rollback.js.map +1 -0
- package/dist/framework-mcp/src/utils/compliance.js +12 -4
- package/dist/framework-mcp/src/utils/compliance.js.map +1 -1
- package/dist/framework-mcp/src/utils/context-optimizer.d.ts +69 -0
- package/dist/framework-mcp/src/utils/context-optimizer.js +157 -0
- package/dist/framework-mcp/src/utils/context-optimizer.js.map +1 -0
- package/dist/framework-mcp/src/utils/discipline.d.ts +68 -0
- package/dist/framework-mcp/src/utils/discipline.js +218 -0
- package/dist/framework-mcp/src/utils/discipline.js.map +1 -0
- package/dist/framework-mcp/src/utils/finops.d.ts +143 -0
- package/dist/framework-mcp/src/utils/finops.js +326 -0
- package/dist/framework-mcp/src/utils/finops.js.map +1 -0
- package/dist/framework-mcp/src/utils/human-in-loop.d.ts +95 -0
- package/dist/framework-mcp/src/utils/human-in-loop.js +216 -0
- package/dist/framework-mcp/src/utils/human-in-loop.js.map +1 -0
- package/dist/framework-mcp/src/utils/license-scanner.d.ts +71 -0
- package/dist/framework-mcp/src/utils/license-scanner.js +284 -0
- package/dist/framework-mcp/src/utils/license-scanner.js.map +1 -0
- package/dist/framework-mcp/src/utils/loop-detector.d.ts +105 -0
- package/dist/framework-mcp/src/utils/loop-detector.js +362 -0
- package/dist/framework-mcp/src/utils/loop-detector.js.map +1 -0
- package/dist/framework-mcp/src/utils/quality.d.ts +19 -0
- package/dist/framework-mcp/src/utils/quality.js +125 -0
- package/dist/framework-mcp/src/utils/quality.js.map +1 -0
- package/dist/framework-mcp/src/utils/rules-engine.d.ts +78 -0
- package/dist/framework-mcp/src/utils/rules-engine.js +232 -0
- package/dist/framework-mcp/src/utils/rules-engine.js.map +1 -0
- package/dist/framework-mcp/src/utils/silent-router.d.ts +49 -0
- package/dist/framework-mcp/src/utils/silent-router.js +155 -0
- package/dist/framework-mcp/src/utils/silent-router.js.map +1 -0
- package/dist/framework-mcp/src/utils/storage.d.ts +1 -0
- package/dist/framework-mcp/src/utils/storage.js +2 -2
- package/dist/framework-mcp/src/utils/storage.js.map +1 -1
- package/dist/framework-mcp/src/utils/telemetry-streamer.d.ts +133 -0
- package/dist/framework-mcp/src/utils/telemetry-streamer.js +397 -0
- package/dist/framework-mcp/src/utils/telemetry-streamer.js.map +1 -0
- package/dist/framework-mcp/tests/tools/file_system/file_system_tools.test.js +2 -2
- package/dist/framework-mcp/tests/tools/file_system/file_system_tools.test.js.map +1 -1
- package/dist/framework-mcp/tests/tools/framework/run_tests.test.d.ts +1 -0
- package/dist/framework-mcp/tests/tools/framework/run_tests.test.js +49 -0
- package/dist/framework-mcp/tests/tools/framework/run_tests.test.js.map +1 -0
- package/dist/framework-mcp/tests/tools/messaging/send_message.test.js +14 -5
- package/dist/framework-mcp/tests/tools/messaging/send_message.test.js.map +1 -1
- package/dist/framework-mcp/tests/tools/observability/check_ports.test.d.ts +1 -0
- package/dist/framework-mcp/tests/tools/observability/check_ports.test.js +44 -0
- package/dist/framework-mcp/tests/tools/observability/check_ports.test.js.map +1 -0
- package/dist/framework-mcp/tests/tools/shell/run_command.test.js +44 -14
- package/dist/framework-mcp/tests/tools/shell/run_command.test.js.map +1 -1
- package/dist/framework-mcp/tests/utils/auto-rollback.test.d.ts +7 -0
- package/dist/framework-mcp/tests/utils/auto-rollback.test.js +178 -0
- package/dist/framework-mcp/tests/utils/auto-rollback.test.js.map +1 -0
- package/dist/framework-mcp/tests/utils/context-optimizer.test.d.ts +1 -0
- package/dist/framework-mcp/tests/utils/context-optimizer.test.js +62 -0
- package/dist/framework-mcp/tests/utils/context-optimizer.test.js.map +1 -0
- package/dist/framework-mcp/tests/utils/finops.test.d.ts +7 -0
- package/dist/framework-mcp/tests/utils/finops.test.js +157 -0
- package/dist/framework-mcp/tests/utils/finops.test.js.map +1 -0
- package/dist/framework-mcp/tests/utils/human-in-loop.test.d.ts +1 -0
- package/dist/framework-mcp/tests/utils/human-in-loop.test.js +59 -0
- package/dist/framework-mcp/tests/utils/human-in-loop.test.js.map +1 -0
- package/dist/framework-mcp/tests/utils/license-scanner.test.d.ts +7 -0
- package/dist/framework-mcp/tests/utils/license-scanner.test.js +131 -0
- package/dist/framework-mcp/tests/utils/license-scanner.test.js.map +1 -0
- package/dist/framework-mcp/tests/utils/loop-detector.test.d.ts +7 -0
- package/dist/framework-mcp/tests/utils/loop-detector.test.js +204 -0
- package/dist/framework-mcp/tests/utils/loop-detector.test.js.map +1 -0
- package/dist/framework-mcp/tests/utils/rules-engine.test.d.ts +1 -0
- package/dist/framework-mcp/tests/utils/rules-engine.test.js +106 -0
- package/dist/framework-mcp/tests/utils/rules-engine.test.js.map +1 -0
- package/dist/framework-mcp/tests/utils/telemetry-streamer.test.d.ts +7 -0
- package/dist/framework-mcp/tests/utils/telemetry-streamer.test.js +201 -0
- package/dist/framework-mcp/tests/utils/telemetry-streamer.test.js.map +1 -0
- package/dist/src/cli/commands/check.js +16 -1
- package/dist/src/cli/commands/check.js.map +1 -1
- package/dist/src/cli/commands/dashboard.js +188 -164
- package/dist/src/cli/commands/dashboard.js.map +1 -1
- package/dist/src/cli/commands/gateway.js +2 -2
- package/dist/src/cli/commands/gateway.js.map +1 -1
- package/dist/src/cli/commands/init/scaffold-core.d.ts +2 -0
- package/dist/src/cli/commands/init/scaffold-core.js +16 -1
- package/dist/src/cli/commands/init/scaffold-core.js.map +1 -1
- package/dist/src/cli/commands/init/scaffold-ops.js +2 -2
- package/dist/src/cli/commands/init/scaffold-ops.js.map +1 -1
- package/dist/src/cli/commands/init/scaffold-standards.js +13 -1
- package/dist/src/cli/commands/init/scaffold-standards.js.map +1 -1
- package/dist/src/cli/commands/init.d.ts +4 -0
- package/dist/src/cli/commands/init.js +94 -31
- package/dist/src/cli/commands/init.js.map +1 -1
- package/dist/src/cli/commands/mcp.js +3 -1
- package/dist/src/cli/commands/mcp.js.map +1 -1
- package/dist/src/cli/commands/quickstart.d.ts +1 -1
- package/dist/src/cli/commands/quickstart.js +12 -24
- package/dist/src/cli/commands/quickstart.js.map +1 -1
- package/dist/src/cli/commands/script.js +8 -1
- package/dist/src/cli/commands/script.js.map +1 -1
- package/dist/src/cli/index.js +24 -23
- package/dist/src/cli/index.js.map +1 -1
- package/dist/src/cli/shims.js +7 -7
- package/dist/src/cli/utils/pkg.js +2 -3
- package/dist/src/cli/utils/pkg.js.map +1 -1
- package/dist/src/cli/utils/quality.d.ts +10 -0
- package/dist/src/cli/utils/quality.js +10 -0
- package/dist/src/cli/utils/quality.js.map +1 -0
- package/dist/src/modules/agents/definitions.js +45 -40
- package/dist/src/modules/agents/definitions.js.map +1 -1
- package/dist/src/modules/agents/registry/manager.js +6 -1
- package/dist/src/modules/agents/registry/manager.js.map +1 -1
- package/dist/src/modules/engines/agent-executor.d.ts +6 -10
- package/dist/src/modules/engines/agent-executor.js +63 -21
- package/dist/src/modules/engines/agent-executor.js.map +1 -1
- package/dist/src/modules/engines/agent-loop.d.ts +34 -0
- package/dist/src/modules/engines/agent-loop.js +102 -0
- package/dist/src/modules/engines/agent-loop.js.map +1 -0
- package/dist/src/modules/engines/evaluation-engine.d.ts +12 -2
- package/dist/src/modules/engines/evaluation-engine.js +78 -11
- package/dist/src/modules/engines/evaluation-engine.js.map +1 -1
- package/dist/src/modules/engines/quality-gate.d.ts +13 -5
- package/dist/src/modules/engines/quality-gate.js +39 -31
- package/dist/src/modules/engines/quality-gate.js.map +1 -1
- package/dist/src/modules/engines/routing-engine.d.ts +5 -3
- package/dist/src/modules/engines/routing-engine.js +16 -9
- package/dist/src/modules/engines/routing-engine.js.map +1 -1
- package/dist/src/modules/gateway/cost-tracker.d.ts +5 -0
- package/dist/src/modules/gateway/cost-tracker.js +71 -0
- package/dist/src/modules/gateway/cost-tracker.js.map +1 -1
- package/dist/src/modules/gateway/gateway.d.ts +4 -0
- package/dist/src/modules/gateway/gateway.js +8 -0
- package/dist/src/modules/gateway/gateway.js.map +1 -1
- package/dist/src/shared/audit.js +3 -2
- package/dist/src/shared/audit.js.map +1 -1
- package/dist/src/shared/pii.d.ts +41 -9
- package/dist/src/shared/pii.js +122 -31
- package/dist/src/shared/pii.js.map +1 -1
- package/dist/src/shared/storage.d.ts +62 -0
- package/dist/src/shared/storage.js +47 -7
- package/dist/src/shared/storage.js.map +1 -1
- package/dist/tests/embedding.test.d.ts +1 -0
- package/dist/tests/embedding.test.js +82 -0
- package/dist/tests/embedding.test.js.map +1 -0
- package/dist/tests/engines/evaluation-engine.test.d.ts +1 -0
- package/dist/tests/engines/evaluation-engine.test.js +71 -0
- package/dist/tests/engines/evaluation-engine.test.js.map +1 -0
- package/dist/tests/engines/planning-engine.test.d.ts +1 -0
- package/dist/tests/engines/planning-engine.test.js +100 -0
- package/dist/tests/engines/planning-engine.test.js.map +1 -0
- package/dist/tests/engines/quality-gate.test.d.ts +1 -0
- package/dist/tests/engines/quality-gate.test.js +59 -0
- package/dist/tests/engines/quality-gate.test.js.map +1 -0
- package/dist/tests/engines/risk-engine.test.d.ts +1 -0
- package/dist/tests/engines/risk-engine.test.js +80 -0
- package/dist/tests/engines/risk-engine.test.js.map +1 -0
- package/dist/tests/engines/routing-engine.test.d.ts +1 -0
- package/dist/tests/engines/routing-engine.test.js +78 -0
- package/dist/tests/engines/routing-engine.test.js.map +1 -0
- package/dist/tests/integration/hermes_locking.test.js +1 -0
- package/dist/tests/integration/hermes_locking.test.js.map +1 -1
- package/dist/tests/modules/engines/agent-executor.test.js +1 -1
- package/dist/tests/modules/engines/agent-executor.test.js.map +1 -1
- package/dist/tests/modules/gateway/cost-tracker.test.js +20 -1
- package/dist/tests/modules/gateway/cost-tracker.test.js.map +1 -1
- package/dist/tests/shared/lock.test.d.ts +1 -0
- package/dist/tests/shared/lock.test.js +95 -0
- package/dist/tests/shared/lock.test.js.map +1 -0
- package/dist/tests/shared/pii.test.d.ts +1 -0
- package/dist/tests/shared/pii.test.js +183 -0
- package/dist/tests/shared/pii.test.js.map +1 -0
- package/framework-mcp/README.md +307 -35
- package/framework-mcp/dist/dashboard/assets/index-B_rK57vi.js +1221 -0
- package/framework-mcp/dist/dashboard/index.html +1 -1
- package/framework-mcp/dist/framework-mcp/src/index.js +988 -63
- package/framework-mcp/dist/framework-mcp/src/tools/compliance/mask_pii.js +55 -0
- package/framework-mcp/dist/framework-mcp/src/tools/definitions.js +10 -9
- package/framework-mcp/dist/framework-mcp/src/tools/framework/run_tests.js +25 -0
- package/framework-mcp/dist/framework-mcp/src/tools/index.js +7 -8
- package/framework-mcp/dist/framework-mcp/src/tools/messaging/approve_operation.js +80 -0
- package/framework-mcp/dist/framework-mcp/src/tools/messaging/ask_human.js +89 -20
- package/framework-mcp/dist/framework-mcp/src/tools/observability/check_ports.js +24 -8
- package/framework-mcp/dist/framework-mcp/src/tools/quality/analyze_code_quality.js +13 -64
- package/framework-mcp/dist/framework-mcp/src/tools/schemas.js +18 -22
- package/framework-mcp/dist/framework-mcp/src/tools/shell/run_command.js +146 -90
- package/framework-mcp/dist/framework-mcp/src/tools/types.js +1 -0
- package/framework-mcp/dist/framework-mcp/src/utils/auth.js +78 -0
- package/framework-mcp/dist/framework-mcp/src/utils/auto-rollback.js +265 -0
- package/framework-mcp/dist/framework-mcp/src/utils/compliance.js +12 -4
- package/framework-mcp/dist/framework-mcp/src/utils/context-optimizer.js +156 -0
- package/framework-mcp/dist/framework-mcp/src/utils/discipline.js +217 -0
- package/framework-mcp/dist/framework-mcp/src/utils/finops.js +325 -0
- package/framework-mcp/dist/framework-mcp/src/utils/human-in-loop.js +215 -0
- package/framework-mcp/dist/framework-mcp/src/utils/license-scanner.js +283 -0
- package/framework-mcp/dist/framework-mcp/src/utils/loop-detector.js +361 -0
- package/framework-mcp/dist/framework-mcp/src/utils/quality.js +124 -0
- package/framework-mcp/dist/framework-mcp/src/utils/rules-engine.js +231 -0
- package/framework-mcp/dist/framework-mcp/src/utils/silent-router.js +154 -0
- package/framework-mcp/dist/framework-mcp/src/utils/storage.js +2 -2
- package/framework-mcp/dist/framework-mcp/src/utils/telemetry-streamer.js +396 -0
- package/framework-mcp/dist/src/cli/platforms/core.js +72 -0
- package/framework-mcp/dist/src/cli/platforms/index.js +5 -0
- package/framework-mcp/dist/src/cli/platforms/paths.js +101 -0
- package/framework-mcp/dist/src/cli/platforms/scaffold.js +72 -0
- package/framework-mcp/dist/src/cli/platforms/utils.js +75 -0
- package/framework-mcp/dist/src/cli/utils/claude.js +57 -0
- package/framework-mcp/dist/src/cli/utils/compliance.js +12 -0
- package/framework-mcp/dist/src/cli/utils/fs.js +138 -0
- package/framework-mcp/dist/src/cli/utils/pkg.js +282 -0
- package/framework-mcp/dist/src/cli/utils/quality.js +9 -0
- package/framework-mcp/dist/src/modules/agents/definitions.js +563 -0
- package/framework-mcp/dist/src/modules/agents/registry/analyst.js +39 -0
- package/framework-mcp/dist/src/modules/agents/registry/architect.js +42 -0
- package/framework-mcp/dist/src/modules/agents/registry/backend.js +50 -0
- package/framework-mcp/dist/src/modules/agents/registry/database.js +45 -0
- package/framework-mcp/dist/src/modules/agents/registry/devops.js +45 -0
- package/framework-mcp/dist/src/modules/agents/registry/explorer.js +37 -0
- package/framework-mcp/dist/src/modules/agents/registry/frontend.js +52 -0
- package/framework-mcp/dist/src/modules/agents/registry/git.js +36 -0
- package/framework-mcp/dist/src/modules/agents/registry/manager.js +64 -0
- package/framework-mcp/dist/src/modules/agents/registry/mobile.js +41 -0
- package/framework-mcp/dist/src/modules/agents/registry/native.js +41 -0
- package/framework-mcp/dist/src/modules/agents/registry/quality.js +43 -0
- package/framework-mcp/dist/src/modules/agents/registry/security.js +42 -0
- package/framework-mcp/dist/src/modules/agents/types.js +1 -0
- package/framework-mcp/dist/src/modules/engines/evaluation-engine.js +169 -0
- package/framework-mcp/dist/src/modules/engines/quality-gate.js +92 -0
- package/framework-mcp/dist/src/modules/engines/risk-engine.js +105 -0
- package/framework-mcp/dist/src/modules/engines/routing-engine.js +408 -0
- package/framework-mcp/dist/src/modules/engines/types.js +1 -0
- package/framework-mcp/dist/src/modules/providers/definitions.js +140 -0
- package/framework-mcp/dist/src/modules/providers/registry.js +18 -0
- package/framework-mcp/dist/src/modules/providers/shared.js +104 -0
- package/framework-mcp/dist/src/modules/providers/types.js +1 -0
- package/framework-mcp/dist/src/modules/skills/adapter-skills.js +449 -0
- package/framework-mcp/dist/src/modules/skills/definitions.js +70 -0
- package/framework-mcp/dist/src/shared/audit.js +220 -0
- package/framework-mcp/dist/src/shared/errors.js +68 -0
- package/framework-mcp/dist/src/shared/lock.js +159 -0
- package/framework-mcp/dist/src/shared/pii.js +122 -31
- package/framework-mcp/dist/src/shared/retention.js +170 -0
- package/framework-mcp/dist/src/shared/storage.js +47 -7
- package/framework-mcp/dist/src/shared/string.js +29 -0
- package/framework-mcp/package.json +8 -2
- package/mcp.json +12 -6
- package/package.json +11 -5
- package/templates/full/ATABEY_FULL.md +1 -1
- package/framework-mcp/dist/dashboard/assets/index-BAPGLiWE.js +0 -267
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { classifyData, containsPII, maskObject, maskText } from "../../../../src/shared/pii.js";
|
|
2
|
+
export function handleMaskPII(root, args) {
|
|
3
|
+
const mode = args.mode || "auto";
|
|
4
|
+
const strictMode = args.strictMode ?? false;
|
|
5
|
+
// Mode: text
|
|
6
|
+
if (mode === "text" || (mode === "auto" && args.text && !args.data)) {
|
|
7
|
+
if (!args.text) {
|
|
8
|
+
return {
|
|
9
|
+
isError: true,
|
|
10
|
+
content: [{ type: "text", text: "[ERROR] 'text' parameter is required when mode is 'text'." }],
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
const masked = maskText(args.text);
|
|
14
|
+
const hasPII = containsPII(args.text);
|
|
15
|
+
const classification = classifyData(args.text);
|
|
16
|
+
return {
|
|
17
|
+
content: [{
|
|
18
|
+
type: "text",
|
|
19
|
+
text: JSON.stringify({
|
|
20
|
+
originalLength: args.text.length,
|
|
21
|
+
maskedLength: masked.length,
|
|
22
|
+
hasPII,
|
|
23
|
+
classification,
|
|
24
|
+
masked,
|
|
25
|
+
}, null, 2),
|
|
26
|
+
}],
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
// Mode: object
|
|
30
|
+
if (mode === "object" || (mode === "auto" && args.data)) {
|
|
31
|
+
if (!args.data) {
|
|
32
|
+
return {
|
|
33
|
+
isError: true,
|
|
34
|
+
content: [{ type: "text", text: "[ERROR] 'data' parameter is required when mode is 'object'." }],
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
const masked = maskObject(args.data, 0, strictMode);
|
|
38
|
+
const hasPII = containsPII(JSON.stringify(args.data));
|
|
39
|
+
const classification = classifyData(JSON.stringify(args.data));
|
|
40
|
+
return {
|
|
41
|
+
content: [{
|
|
42
|
+
type: "text",
|
|
43
|
+
text: JSON.stringify({
|
|
44
|
+
hasPII,
|
|
45
|
+
classification,
|
|
46
|
+
masked,
|
|
47
|
+
}, null, 2),
|
|
48
|
+
}],
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
return {
|
|
52
|
+
isError: true,
|
|
53
|
+
content: [{ type: "text", text: "[ERROR] Provide either 'text' (string) or 'data' (object) parameter." }],
|
|
54
|
+
};
|
|
55
|
+
}
|
|
@@ -172,6 +172,12 @@ export const TOOLS = [
|
|
|
172
172
|
description: "Pause execution and ask the human developer a clarifying question via the terminal.",
|
|
173
173
|
inputSchema: zodToMcpSchema(schemas.AskHumanSchema),
|
|
174
174
|
},
|
|
175
|
+
// ─── PII / Compliance ─────────────────────────────────────────
|
|
176
|
+
{
|
|
177
|
+
name: "mask_pii",
|
|
178
|
+
description: "Mask Personally Identifiable Information (PII) in text or structured data. Compliant with KVKK (Law No. 6698) and GDPR. Detects and masks emails, phone numbers, TC IDs, API keys, tokens, IPs, credit cards, IBANs, and more.",
|
|
179
|
+
inputSchema: zodToMcpSchema(schemas.MaskPIISchema),
|
|
180
|
+
},
|
|
175
181
|
// ─── Code Quality ─────────────────────────────────────────────
|
|
176
182
|
{
|
|
177
183
|
name: "analyze_code_quality",
|
|
@@ -183,15 +189,10 @@ export const TOOLS = [
|
|
|
183
189
|
description: "Check architecture compliance in a given path. Verifies layer boundaries (Controller→Service→Repository), import direction rules, and strict mode.",
|
|
184
190
|
inputSchema: zodToMcpSchema(schemas.CheckArchitectureComplianceSchema),
|
|
185
191
|
},
|
|
186
|
-
// ───
|
|
187
|
-
{
|
|
188
|
-
name: "llm_gateway_query",
|
|
189
|
-
description: "Send a chat completion request through the ATABEY LLM Gateway. The gateway automatically load-balances across providers (OpenAI, Anthropic, Google, Grok, Ollama) using configurable strategies (failover, round-robin, cost-optimized). Allows any MCP-connected AI to route LLM requests through the gateway.",
|
|
190
|
-
inputSchema: zodToMcpSchema(schemas.LLMGatewayQuerySchema),
|
|
191
|
-
},
|
|
192
|
+
// ─── Human-in-the-Loop ────────────────────────────────────────
|
|
192
193
|
{
|
|
193
|
-
name: "
|
|
194
|
-
description: "
|
|
195
|
-
inputSchema: zodToMcpSchema(schemas.
|
|
194
|
+
name: "approve_operation",
|
|
195
|
+
description: "Approve, reject, or list pending risk-gated operations. Use this when an operation was blocked by the Risk Gate (risk score ≥ 60). Action: 'approve' | 'reject' | 'list'.",
|
|
196
|
+
inputSchema: zodToMcpSchema(schemas.ApproveOperationSchema),
|
|
196
197
|
},
|
|
197
198
|
];
|
|
@@ -1,11 +1,36 @@
|
|
|
1
1
|
import { execSync } from "child_process";
|
|
2
2
|
import { getBackendLanguage, getDefaultTestCommand } from "../../utils/cli.js";
|
|
3
|
+
const TEST_COMMAND_ALLOW_LIST = [
|
|
4
|
+
"npm test",
|
|
5
|
+
"npm run test",
|
|
6
|
+
"npx vitest",
|
|
7
|
+
"pytest",
|
|
8
|
+
"go test",
|
|
9
|
+
"dotnet test",
|
|
10
|
+
"mvn test",
|
|
11
|
+
"./gradlew test",
|
|
12
|
+
"cargo test"
|
|
13
|
+
];
|
|
3
14
|
/**
|
|
4
15
|
* Executes project tests and returns results for agent analysis.
|
|
5
16
|
*/
|
|
6
17
|
export function handleRunTests(projectRoot, args) {
|
|
7
18
|
const language = getBackendLanguage(projectRoot);
|
|
8
19
|
const testCommand = args.command || getDefaultTestCommand(language);
|
|
20
|
+
// Validate command to prevent shell injection / chaining
|
|
21
|
+
const isAllowed = TEST_COMMAND_ALLOW_LIST.some(allowedCmd => testCommand.startsWith(allowedCmd));
|
|
22
|
+
if (!isAllowed) {
|
|
23
|
+
return {
|
|
24
|
+
isError: true,
|
|
25
|
+
content: [{ type: "text", text: `[ERROR] Test command not allowed: "${testCommand}". Must start with one of: ${TEST_COMMAND_ALLOW_LIST.join(", ")}` }]
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
if (/[;&|><$`\n\r]/.test(testCommand)) {
|
|
29
|
+
return {
|
|
30
|
+
isError: true,
|
|
31
|
+
content: [{ type: "text", text: "[ERROR] Test command rejected: Shell metacharacters are forbidden to prevent command injection." }]
|
|
32
|
+
};
|
|
33
|
+
}
|
|
9
34
|
try {
|
|
10
35
|
const output = execSync(testCommand, { cwd: projectRoot, encoding: "utf8", stdio: "pipe" });
|
|
11
36
|
return {
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { handleMaskPII } from "./compliance/mask_pii.js";
|
|
1
2
|
import { handleAcquireLock, handleReleaseLock } from "./control_plane/locking.js";
|
|
2
3
|
import { handleRegisterAgent } from "./control_plane/registry.js";
|
|
3
4
|
import { TOOLS } from "./definitions.js";
|
|
@@ -13,14 +14,13 @@ import { handleRunTests } from "./framework/run_tests.js";
|
|
|
13
14
|
import { handleSubmitPlan } from "./framework/submit_plan.js";
|
|
14
15
|
import { handleUpdateContractHash } from "./framework/update_contract_hash.js";
|
|
15
16
|
import { handleUpdateProjectMemory } from "./framework/update_memory.js";
|
|
16
|
-
import { handleLLMGatewayQuery } from "./gateway/llm_gateway_query.js";
|
|
17
|
-
import { handleLLMGatewayStatus } from "./gateway/llm_gateway_status.js";
|
|
18
17
|
import { handleDeleteKnowledge } from "./memory/delete_knowledge.js";
|
|
19
18
|
import { handleGetMemoryInsights } from "./memory/get_insights.js";
|
|
20
19
|
import { handleReadProjectMemory } from "./memory/read_memory.js";
|
|
21
20
|
import { handleSearchKnowledge } from "./memory/search_knowledge.js";
|
|
22
21
|
import { handleStoreKnowledge } from "./memory/store_knowledge.js";
|
|
23
22
|
import { handleAskHuman } from "./messaging/ask_human.js";
|
|
23
|
+
import { handleApproveOperation } from "./messaging/approve_operation.js";
|
|
24
24
|
import { handleLogAgentAction } from "./messaging/log_action.js";
|
|
25
25
|
import { handleSendAgentMessage } from "./messaging/send_message.js";
|
|
26
26
|
import { handleCheckPorts } from "./observability/check_ports.js";
|
|
@@ -65,6 +65,7 @@ export const toolHandlers = {
|
|
|
65
65
|
send_agent_message: bind(handleSendAgentMessage),
|
|
66
66
|
log_agent_action: bind(handleLogAgentAction),
|
|
67
67
|
ask_human: bind(handleAskHuman),
|
|
68
|
+
approve_operation: bind(handleApproveOperation),
|
|
68
69
|
update_contract_hash: bind(handleUpdateContractHash),
|
|
69
70
|
acquire_lock: bind(handleAcquireLock),
|
|
70
71
|
release_lock: bind(handleReleaseLock),
|
|
@@ -73,9 +74,7 @@ export const toolHandlers = {
|
|
|
73
74
|
check_lint: bind(handleCheckLint),
|
|
74
75
|
analyze_code_quality: bind(handleAnalyzeCodeQuality),
|
|
75
76
|
check_architecture_compliance: bind(handleCheckArchitectureCompliance),
|
|
76
|
-
|
|
77
|
-
llm_gateway_query: bind(handleLLMGatewayQuery),
|
|
78
|
-
llm_gateway_status: bind(handleLLMGatewayStatus),
|
|
77
|
+
mask_pii: bind(handleMaskPII),
|
|
79
78
|
};
|
|
80
79
|
// Map of tool names to their Zod validation schemas
|
|
81
80
|
export const toolSchemas = {
|
|
@@ -116,11 +115,11 @@ export const toolSchemas = {
|
|
|
116
115
|
send_agent_message: schemas.SendAgentMessageSchema,
|
|
117
116
|
log_agent_action: schemas.LogAgentActionSchema,
|
|
118
117
|
ask_human: schemas.AskHumanSchema,
|
|
118
|
+
approve_operation: schemas.ApproveOperationSchema,
|
|
119
119
|
// Code Quality
|
|
120
120
|
analyze_code_quality: schemas.AnalyzeCodeQualitySchema,
|
|
121
121
|
check_architecture_compliance: schemas.CheckArchitectureComplianceSchema,
|
|
122
|
-
//
|
|
123
|
-
|
|
124
|
-
llm_gateway_status: schemas.LLMGatewayStatusSchema,
|
|
122
|
+
// PII / Compliance
|
|
123
|
+
mask_pii: schemas.MaskPIISchema,
|
|
125
124
|
};
|
|
126
125
|
export { TOOLS };
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { approveOperation, getPendingApprovals, rejectOperation } from "../../utils/human-in-loop.js";
|
|
2
|
+
/**
|
|
3
|
+
* MCP Tool: approve_operation
|
|
4
|
+
*
|
|
5
|
+
* In AI CLI (Claude Code, Gemini CLI), running "atabey approve <traceId>"
|
|
6
|
+
* is not possible — anything typed in chat is treated as a message, not a CLI command.
|
|
7
|
+
*
|
|
8
|
+
* This tool moves the risk gate approval flow directly into an MCP tool call:
|
|
9
|
+
*
|
|
10
|
+
* 1. Atabey blocks a high-risk operation
|
|
11
|
+
* 2. Tells the developer: "call the approve_operation tool"
|
|
12
|
+
* 3. AI calls this tool → operation is approved/rejected
|
|
13
|
+
*
|
|
14
|
+
* Developer never has to switch to terminal.
|
|
15
|
+
*/
|
|
16
|
+
export async function handleApproveOperation(_root, args) {
|
|
17
|
+
const { action, traceId, reason } = args;
|
|
18
|
+
// LIST: Show pending approvals
|
|
19
|
+
if (action === "list") {
|
|
20
|
+
const pending = getPendingApprovals();
|
|
21
|
+
if (pending.length === 0) {
|
|
22
|
+
return {
|
|
23
|
+
content: [{ type: "text", text: "[APPROVALS] No pending operations waiting for approval." }],
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
const lines = [
|
|
27
|
+
`[APPROVALS] ${pending.length} pending operation(s):\n`,
|
|
28
|
+
...pending.map(req => [
|
|
29
|
+
" ─────────────────────────────────────",
|
|
30
|
+
` Trace ID: ${req.traceId}`,
|
|
31
|
+
` Tool: ${req.toolName}`,
|
|
32
|
+
` Agent: ${req.agent}`,
|
|
33
|
+
` Risk Score: ${req.riskScore}/100 (${req.riskLevel})`,
|
|
34
|
+
` Reason: ${req.reason}`,
|
|
35
|
+
` Expires: ${new Date(req.expiresAt).toISOString()}`,
|
|
36
|
+
].join("\n")),
|
|
37
|
+
"",
|
|
38
|
+
"To approve: call approve_operation with action=\"approve\" and traceId=\"<id>\"",
|
|
39
|
+
"To reject: call approve_operation with action=\"reject\" and traceId=\"<id>\"",
|
|
40
|
+
];
|
|
41
|
+
return {
|
|
42
|
+
content: [{ type: "text", text: lines.join("\n") }],
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
// APPROVE or REJECT: traceId is required
|
|
46
|
+
if (!traceId) {
|
|
47
|
+
return {
|
|
48
|
+
isError: true,
|
|
49
|
+
content: [{ type: "text", text: `[ERROR] traceId is required for "${action}" action.` }],
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
if (action === "approve") {
|
|
53
|
+
const result = approveOperation(traceId);
|
|
54
|
+
return {
|
|
55
|
+
content: [{
|
|
56
|
+
type: "text",
|
|
57
|
+
text: result.success
|
|
58
|
+
? `[APPROVED] ✅ ${result.message}\nYou may retry the blocked operation now.`
|
|
59
|
+
: `[ERROR] ${result.message}`,
|
|
60
|
+
}],
|
|
61
|
+
isError: !result.success,
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
if (action === "reject") {
|
|
65
|
+
const result = rejectOperation(traceId);
|
|
66
|
+
return {
|
|
67
|
+
content: [{
|
|
68
|
+
type: "text",
|
|
69
|
+
text: result.success
|
|
70
|
+
? `[REJECTED] ⛔ ${result.message}${reason ? `\nReason: ${reason}` : ""}`
|
|
71
|
+
: `[ERROR] ${result.message}`,
|
|
72
|
+
}],
|
|
73
|
+
isError: !result.success,
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
return {
|
|
77
|
+
isError: true,
|
|
78
|
+
content: [{ type: "text", text: `[ERROR] Unknown action: "${String(action)}". Use "approve", "reject", or "list".` }],
|
|
79
|
+
};
|
|
80
|
+
}
|
|
@@ -1,30 +1,99 @@
|
|
|
1
|
-
import
|
|
1
|
+
import fs from "fs";
|
|
2
|
+
import path from "path";
|
|
3
|
+
/**
|
|
4
|
+
* ─── ASK HUMAN — File Bridge ─────────────────────────────────────────
|
|
5
|
+
*
|
|
6
|
+
* AI CLIs (Claude Code, Gemini CLI) start the MCP server as a stdio subprocess.
|
|
7
|
+
* In this subprocess, stdin is isTTY=false (used for MCP JSON-RPC).
|
|
8
|
+
*
|
|
9
|
+
* Solution: File-based Q&A bridge.
|
|
10
|
+
* 1. Question → written to .atabey/hitl/question.txt
|
|
11
|
+
* 2. Developer answers via `atabey hitl` command
|
|
12
|
+
* 3. Answer → written to .atabey/hitl/answer.txt
|
|
13
|
+
* 4. This handler reads the answer and returns it to the AI
|
|
14
|
+
*
|
|
15
|
+
* Dashboard: Can also be answered via /api/approvals endpoint on the web dashboard.
|
|
16
|
+
*/
|
|
2
17
|
export async function handleAskHuman(root, args) {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
18
|
+
const timeoutSeconds = args.timeoutSeconds ?? 120;
|
|
19
|
+
const hitlDir = path.join(root, ".atabey", "hitl");
|
|
20
|
+
const questionFile = path.join(hitlDir, "question.txt");
|
|
21
|
+
const answerFile = path.join(hitlDir, "answer.txt");
|
|
6
22
|
try {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
23
|
+
// Ensure hitl directory exists
|
|
24
|
+
fs.mkdirSync(hitlDir, { recursive: true });
|
|
25
|
+
// Clear any stale answer file
|
|
26
|
+
if (fs.existsSync(answerFile)) {
|
|
27
|
+
fs.unlinkSync(answerFile);
|
|
28
|
+
}
|
|
29
|
+
// Write the question with metadata
|
|
30
|
+
const questionPayload = JSON.stringify({
|
|
31
|
+
timestamp: new Date().toISOString(),
|
|
32
|
+
question: args.question,
|
|
33
|
+
timeoutAt: new Date(Date.now() + timeoutSeconds * 1000).toISOString(),
|
|
34
|
+
}, null, 2);
|
|
35
|
+
fs.writeFileSync(questionFile, questionPayload);
|
|
36
|
+
// Write human-readable prompt file alongside
|
|
37
|
+
fs.writeFileSync(path.join(hitlDir, "PENDING.txt"), [
|
|
38
|
+
"═══════════════════════════════════════════════════",
|
|
39
|
+
" [ATABEY] AGENT WAITING FOR YOUR ANSWER",
|
|
40
|
+
"═══════════════════════════════════════════════════",
|
|
41
|
+
"",
|
|
42
|
+
`QUESTION: ${args.question}`,
|
|
43
|
+
"",
|
|
44
|
+
"To answer, run in your terminal:",
|
|
45
|
+
" atabey hitl answer \"your answer here\"",
|
|
46
|
+
"",
|
|
47
|
+
"Or use the dashboard: http://localhost:5858",
|
|
48
|
+
"═══════════════════════════════════════════════════",
|
|
49
|
+
].join("\n"));
|
|
50
|
+
process.stderr.write(`[HITL] Question written to ${questionFile}\n`);
|
|
51
|
+
process.stderr.write("[HITL] Run: atabey hitl answer \"your answer\"\n");
|
|
52
|
+
// Poll for answer file
|
|
53
|
+
const pollIntervalMs = 1000;
|
|
54
|
+
const maxAttempts = timeoutSeconds;
|
|
55
|
+
for (let attempt = 0; attempt < maxAttempts; attempt++) {
|
|
56
|
+
await new Promise(resolve => setTimeout(resolve, pollIntervalMs));
|
|
57
|
+
if (fs.existsSync(answerFile)) {
|
|
58
|
+
const answer = fs.readFileSync(answerFile, "utf8").trim();
|
|
59
|
+
// Clean up
|
|
60
|
+
try {
|
|
61
|
+
fs.unlinkSync(questionFile);
|
|
62
|
+
fs.unlinkSync(answerFile);
|
|
63
|
+
const pendingFile = path.join(hitlDir, "PENDING.txt");
|
|
64
|
+
if (fs.existsSync(pendingFile))
|
|
65
|
+
fs.unlinkSync(pendingFile);
|
|
66
|
+
}
|
|
67
|
+
catch { /* cleanup is best-effort */ }
|
|
68
|
+
process.stderr.write("[HITL] Answer received.\n");
|
|
69
|
+
return {
|
|
70
|
+
content: [{ type: "text", text: `[HUMAN RESPONSE] ${answer}` }],
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
// Timeout — clean up question file
|
|
75
|
+
try {
|
|
76
|
+
if (fs.existsSync(questionFile))
|
|
77
|
+
fs.unlinkSync(questionFile);
|
|
78
|
+
const pendingFile = path.join(hitlDir, "PENDING.txt");
|
|
79
|
+
if (fs.existsSync(pendingFile))
|
|
80
|
+
fs.unlinkSync(pendingFile);
|
|
81
|
+
}
|
|
82
|
+
catch { /* cleanup is best-effort */ }
|
|
83
|
+
return {
|
|
84
|
+
content: [{
|
|
85
|
+
type: "text",
|
|
86
|
+
text: `[HITL TIMEOUT] No answer received within ${timeoutSeconds}s.\n` +
|
|
87
|
+
`Question was: "${args.question}"\n` +
|
|
88
|
+
"To answer pending questions, run: atabey hitl answer \"your answer\"",
|
|
89
|
+
}],
|
|
90
|
+
};
|
|
22
91
|
}
|
|
23
92
|
catch (error) {
|
|
24
93
|
const message = error instanceof Error ? error.message : String(error);
|
|
25
94
|
return {
|
|
26
95
|
isError: true,
|
|
27
|
-
content: [{ type: "text", text: `[ERROR]
|
|
96
|
+
content: [{ type: "text", text: `[ERROR] ask_human failed: ${message}` }],
|
|
28
97
|
};
|
|
29
98
|
}
|
|
30
99
|
}
|
|
@@ -1,16 +1,32 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { spawnSync } from "child_process";
|
|
2
2
|
/**
|
|
3
3
|
* Checks for active network ports and their status.
|
|
4
|
+
* Uses spawnSync instead of execSync to prevent shell injection.
|
|
4
5
|
*/
|
|
5
6
|
export function handleCheckPorts(projectRoot, args) {
|
|
6
|
-
const
|
|
7
|
+
const rawFilter = args.filter || "";
|
|
8
|
+
// Sanitize filter to prevent command injection (allow only alphanumeric, dots, colons, dashes, underscores)
|
|
9
|
+
const filter = rawFilter.replace(/[^a-zA-Z0-9.:_-]/g, "");
|
|
7
10
|
try {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
11
|
+
let output;
|
|
12
|
+
if (process.platform === "win32") {
|
|
13
|
+
const result = spawnSync("netstat", ["-ano"], { encoding: "utf8" });
|
|
14
|
+
if (result.error)
|
|
15
|
+
throw result.error;
|
|
16
|
+
const lines = (result.stdout || "").split("\n").filter(l => l.includes("LISTENING"));
|
|
17
|
+
output = filter
|
|
18
|
+
? lines.filter(l => l.includes(filter)).join("\n")
|
|
19
|
+
: lines.join("\n");
|
|
20
|
+
}
|
|
21
|
+
else {
|
|
22
|
+
const result = spawnSync("lsof", ["-i", "-P", "-n"], { encoding: "utf8" });
|
|
23
|
+
if (result.error)
|
|
24
|
+
throw result.error;
|
|
25
|
+
const lines = (result.stdout || "").split("\n").filter(l => l.includes("LISTEN"));
|
|
26
|
+
output = filter
|
|
27
|
+
? lines.filter(l => l.includes(filter)).join("\n")
|
|
28
|
+
: lines.join("\n");
|
|
29
|
+
}
|
|
14
30
|
return {
|
|
15
31
|
content: [{
|
|
16
32
|
type: "text",
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { execSync } from "child_process";
|
|
2
2
|
import fs from "fs";
|
|
3
3
|
import path from "path";
|
|
4
|
+
import { analyzePathQuality } from "../../utils/quality.js";
|
|
4
5
|
/**
|
|
5
6
|
* Code quality analysis tool for Atabey MCP.
|
|
6
7
|
*
|
|
@@ -10,6 +11,13 @@ import path from "path";
|
|
|
10
11
|
* - Code complexity analysis (checkComplexity)
|
|
11
12
|
*/
|
|
12
13
|
export function handleAnalyzeCodeQuality(projectRoot, args) {
|
|
14
|
+
// Validate path parameter to prevent command injection
|
|
15
|
+
if (!/^[a-zA-Z0-9_./-]+$/.test(args.path)) {
|
|
16
|
+
return {
|
|
17
|
+
isError: true,
|
|
18
|
+
content: [{ type: "text", text: `[ERROR] Invalid path characters detected: ${args.path}` }]
|
|
19
|
+
};
|
|
20
|
+
}
|
|
13
21
|
const targetPath = path.resolve(projectRoot, args.path);
|
|
14
22
|
if (!fs.existsSync(targetPath)) {
|
|
15
23
|
return {
|
|
@@ -81,73 +89,14 @@ export function handleAnalyzeCodeQuality(projectRoot, args) {
|
|
|
81
89
|
}
|
|
82
90
|
// 3. Code Complexity Check (basic heuristic)
|
|
83
91
|
if (args.checkComplexity !== false) {
|
|
84
|
-
const
|
|
85
|
-
|
|
86
|
-
if (!fs.existsSync(dir))
|
|
87
|
-
return;
|
|
88
|
-
const entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
89
|
-
for (const entry of entries) {
|
|
90
|
-
const fullPath = path.join(dir, entry.name);
|
|
91
|
-
if (entry.isDirectory() && !entry.name.startsWith("node_modules") && !entry.name.startsWith(".")) {
|
|
92
|
-
scanDirectory(fullPath);
|
|
93
|
-
}
|
|
94
|
-
else if (entry.isFile() && (entry.name.endsWith(".ts") || entry.name.endsWith(".tsx"))) {
|
|
95
|
-
try {
|
|
96
|
-
const content = fs.readFileSync(fullPath, "utf8");
|
|
97
|
-
const lines = content.split("\n");
|
|
98
|
-
// Check for long functions (>50 lines)
|
|
99
|
-
let inFunction = false;
|
|
100
|
-
let funcLines = 0;
|
|
101
|
-
let funcName = "";
|
|
102
|
-
const relativePath = path.relative(projectRoot, fullPath);
|
|
103
|
-
for (let i = 0; i < lines.length; i++) {
|
|
104
|
-
const line = lines[i];
|
|
105
|
-
// Detect function start
|
|
106
|
-
const funcMatch = line.match(/(?:public|private|protected|static\s+)?(?:async\s+)?(?:function\s+)?(\w+)\s*\([^)]*\)\s*{/);
|
|
107
|
-
if (funcMatch) {
|
|
108
|
-
inFunction = true;
|
|
109
|
-
funcLines = 1;
|
|
110
|
-
funcName = funcMatch[1];
|
|
111
|
-
continue;
|
|
112
|
-
}
|
|
113
|
-
// Detect method in class
|
|
114
|
-
const methodMatch = line.match(/^\s*(?:public|private|protected|static\s+)?(\w+)\s*\([^)]*\)\s*{/);
|
|
115
|
-
if (methodMatch && !line.includes("function")) {
|
|
116
|
-
inFunction = true;
|
|
117
|
-
funcLines = 1;
|
|
118
|
-
funcName = methodMatch[1];
|
|
119
|
-
continue;
|
|
120
|
-
}
|
|
121
|
-
if (inFunction) {
|
|
122
|
-
if (line.includes("}")) {
|
|
123
|
-
if (funcLines > 50) {
|
|
124
|
-
complexityIssues.push(`- ${relativePath}:${i + 1} — Function \`${funcName}\` is ${funcLines} lines long (max: 50)`);
|
|
125
|
-
}
|
|
126
|
-
inFunction = false;
|
|
127
|
-
}
|
|
128
|
-
funcLines++;
|
|
129
|
-
}
|
|
130
|
-
// Check nesting depth (>4 levels)
|
|
131
|
-
const indentMatch = line.match(/^(?:\s{2}){5,}/);
|
|
132
|
-
if (indentMatch && !line.trim().startsWith("//") && !line.trim().startsWith("*")) {
|
|
133
|
-
const depth = Math.floor(indentMatch[0].length / 2);
|
|
134
|
-
if (depth > 4) {
|
|
135
|
-
complexityIssues.push(`- ${relativePath}:${i + 1} — Nesting depth ${depth} (max: 4)`);
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
}
|
|
139
|
-
}
|
|
140
|
-
catch {
|
|
141
|
-
// Skip files that can't be read
|
|
142
|
-
}
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
}
|
|
146
|
-
scanDirectory(targetPath);
|
|
92
|
+
const qualityResult = analyzePathQuality(projectRoot, args.path);
|
|
93
|
+
const complexityIssues = qualityResult.issues.filter(issue => issue.type === "complexity");
|
|
147
94
|
if (complexityIssues.length > 0) {
|
|
148
95
|
hasErrors = true;
|
|
149
96
|
results.push(`## ⚠️ Code Complexity Issues (${complexityIssues.length})`);
|
|
150
|
-
|
|
97
|
+
complexityIssues.forEach(issue => {
|
|
98
|
+
results.push(`- ${issue.file}:${issue.line} — ${issue.message}`);
|
|
99
|
+
});
|
|
151
100
|
}
|
|
152
101
|
else {
|
|
153
102
|
results.push("## ✅ Code Complexity: OK");
|
|
@@ -34,7 +34,7 @@ export const ReplaceTextSchema = z.object({
|
|
|
34
34
|
path: z.string().min(1, "Path is required"),
|
|
35
35
|
oldText: z.string().min(1, "oldText is required"),
|
|
36
36
|
newText: z.string(),
|
|
37
|
-
allowMultiple: z.boolean().default(false),
|
|
37
|
+
allowMultiple: z.boolean().optional().default(false),
|
|
38
38
|
}).strict();
|
|
39
39
|
// ─── Search & Exploration
|
|
40
40
|
export const ListDirSchema = z.object({
|
|
@@ -58,7 +58,7 @@ export const BatchSurgicalEditSchema = z.object({
|
|
|
58
58
|
path: z.string().min(1),
|
|
59
59
|
oldText: z.string().min(1),
|
|
60
60
|
newText: z.string(),
|
|
61
|
-
allowMultiple: z.boolean().default(false),
|
|
61
|
+
allowMultiple: z.boolean().optional().default(false),
|
|
62
62
|
})),
|
|
63
63
|
}).strict();
|
|
64
64
|
export const PatchFileSchema = z.object({
|
|
@@ -97,7 +97,7 @@ export const SubmitPlanSchema = z.object({
|
|
|
97
97
|
export const AcquireLockSchema = z.object({
|
|
98
98
|
resource: z.string().min(1),
|
|
99
99
|
agent: AgentIDSchema,
|
|
100
|
-
ttl: z.number().int().positive().default(60),
|
|
100
|
+
ttl: z.number().int().positive().optional().default(60),
|
|
101
101
|
}).strict();
|
|
102
102
|
export const ReleaseLockSchema = z.object({
|
|
103
103
|
resource: z.string().min(1),
|
|
@@ -106,7 +106,7 @@ export const ReleaseLockSchema = z.object({
|
|
|
106
106
|
export const RegisterAgentSchema = z.object({
|
|
107
107
|
agent: AgentIDSchema,
|
|
108
108
|
role: z.string().min(1),
|
|
109
|
-
capability: z.number().int().min(1).max(10).default(5),
|
|
109
|
+
capability: z.number().int().min(1).max(10).optional().default(5),
|
|
110
110
|
specialties: z.record(z.number()).optional(),
|
|
111
111
|
}).strict();
|
|
112
112
|
export const UpdateContractHashSchema = z.object({}).strict();
|
|
@@ -123,7 +123,7 @@ export const StoreKnowledgeSchema = z.object({
|
|
|
123
123
|
export const SearchKnowledgeSchema = z.object({
|
|
124
124
|
query: z.string().min(1, "Query is required"),
|
|
125
125
|
category: z.enum(["ARCHITECTURE", "DECISION", "CODE_SNIPPET", "RULE", "TASK_HISTORY"]).optional(),
|
|
126
|
-
limit: z.number().int().positive().default(5),
|
|
126
|
+
limit: z.number().int().positive().optional().default(5),
|
|
127
127
|
}).strict();
|
|
128
128
|
export const DeleteKnowledgeSchema = z.object({
|
|
129
129
|
id: z.string().optional(),
|
|
@@ -137,8 +137,8 @@ export const SendAgentMessageSchema = z.object({
|
|
|
137
137
|
content: z.string().min(1, "Content cannot be empty"),
|
|
138
138
|
traceId: TraceIDSchema,
|
|
139
139
|
parentId: TaskIDSchema.optional(),
|
|
140
|
-
priority: z.enum(["HIGH", "NORMAL", "LOW"]).default("NORMAL"),
|
|
141
|
-
requiresApproval: z.boolean().default(false),
|
|
140
|
+
priority: z.enum(["HIGH", "NORMAL", "LOW"]).optional().default("NORMAL"),
|
|
141
|
+
requiresApproval: z.boolean().optional().default(false),
|
|
142
142
|
}).strict();
|
|
143
143
|
export const LogAgentActionSchema = z.object({
|
|
144
144
|
agent: AgentIDSchema,
|
|
@@ -150,23 +150,12 @@ export const LogAgentActionSchema = z.object({
|
|
|
150
150
|
}).strict();
|
|
151
151
|
export const AskHumanSchema = z.object({
|
|
152
152
|
question: z.string().min(10, "Question must be clear and detailed."),
|
|
153
|
+
timeoutSeconds: z.number().int().positive().optional().default(120),
|
|
153
154
|
}).strict();
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
messages: z.array(z.object({
|
|
157
|
-
role: z.enum(["system", "user", "assistant", "tool"]),
|
|
158
|
-
content: z.string().min(1),
|
|
159
|
-
})).min(1, "At least one message is required"),
|
|
160
|
-
system: z.string().optional(),
|
|
161
|
-
model: z.string().optional(),
|
|
162
|
-
provider: z.enum(["openai", "anthropic", "google", "grok", "ollama"]).optional(),
|
|
163
|
-
strategy: z.enum(["round-robin", "least-latency", "cost-optimized", "failover", "priority-based", "model-based"]).optional(),
|
|
164
|
-
temperature: z.number().min(0).max(2).optional(),
|
|
165
|
-
maxTokens: z.number().int().positive().optional(),
|
|
155
|
+
export const ApproveOperationSchema = z.object({
|
|
156
|
+
action: z.enum(["approve", "reject", "list"]),
|
|
166
157
|
traceId: z.string().optional(),
|
|
167
|
-
|
|
168
|
-
export const LLMGatewayStatusSchema = z.object({
|
|
169
|
-
detail: z.enum(["overview", "providers", "stats"]).optional().default("overview"),
|
|
158
|
+
reason: z.string().optional(),
|
|
170
159
|
}).strict();
|
|
171
160
|
// ─── Code Quality Analysis ──────────────────────────────────────────
|
|
172
161
|
export const AnalyzeCodeQualitySchema = z.object({
|
|
@@ -180,3 +169,10 @@ export const CheckArchitectureComplianceSchema = z.object({
|
|
|
180
169
|
path: z.string().min(1, "Path to check is required"),
|
|
181
170
|
rules: z.array(z.string()).optional(),
|
|
182
171
|
}).strict();
|
|
172
|
+
// ─── PII / Compliance ───────────────────────────────────────────────
|
|
173
|
+
export const MaskPIISchema = z.object({
|
|
174
|
+
text: z.string().optional(),
|
|
175
|
+
data: z.record(z.unknown()).optional(),
|
|
176
|
+
mode: z.enum(["text", "object", "auto"]).optional().default("auto"),
|
|
177
|
+
strictMode: z.boolean().optional().default(false),
|
|
178
|
+
}).strict();
|