node-ai-guard 1.0.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 +92 -0
- package/dist/index.cjs +50 -0
- package/dist/index.d.cts +27 -0
- package/dist/index.d.ts +27 -0
- package/dist/index.js +24 -0
- package/package.json +34 -0
package/README.md
ADDED
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
# π‘οΈ node-ai-guard
|
|
2
|
+
|
|
3
|
+
**The safety layer for AI Agents. Validate, sanitize, and govern AI-generated intents before they hit your production APIs.**
|
|
4
|
+
|
|
5
|
+
[](https://www.npmjs.com/package/node-ai-guard)
|
|
6
|
+
[](https://opensource.org/licenses/MIT)
|
|
7
|
+
[](https://www.typescriptlang.org/)
|
|
8
|
+
|
|
9
|
+
### **The Problem: AI Hallucinations & Excessive Agency**
|
|
10
|
+
Large Language Models (LLMs) are great at calling tools, but they are unpredictable. When you give an AI Agent access to your APIs (Stripe, Slack, Database), you face critical risks:
|
|
11
|
+
1. **Hallucinations:** The AI sends parameters that don't exist or are formatted incorrectly.
|
|
12
|
+
2. **Excessive Agency:** The AI tries to refund $10,000 instead of $10 because it misread the prompt.
|
|
13
|
+
3. **Security Risks:** A user tricks your AI into executing destructive commands via prompt injection.
|
|
14
|
+
|
|
15
|
+
`node-ai-guard` provides a **Zod-powered guardrail wrapper** designed specifically for AI-generated JSON payloads. It ensures every action is structurally sound and follows strict business safety rules.
|
|
16
|
+
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
## π Installation
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
npm install node-ai-guard zod
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
## π οΈ Quick Start
|
|
28
|
+
|
|
29
|
+
Define a **Guard** with a schema and custom safety rules. If the AI violates a rule, the guard returns a clear error that you can feed back to the AI for self-correction.
|
|
30
|
+
|
|
31
|
+
```typescript
|
|
32
|
+
import { createGuard } from 'node-ai-guard';
|
|
33
|
+
import { z } from 'zod';
|
|
34
|
+
|
|
35
|
+
// 1. Define your safety guard
|
|
36
|
+
const refundGuard = createGuard({
|
|
37
|
+
name: "process_refund",
|
|
38
|
+
description: "Used to issue a refund to a customer.",
|
|
39
|
+
schema: z.object({
|
|
40
|
+
orderId: z.string(),
|
|
41
|
+
amount: z.number(),
|
|
42
|
+
reason: z.string()
|
|
43
|
+
}),
|
|
44
|
+
// Hard safety rules the AI cannot bypass
|
|
45
|
+
rules: [
|
|
46
|
+
{
|
|
47
|
+
check: (data) => data.amount <= 100,
|
|
48
|
+
message: "Refunds over $100 require manual manager intervention."
|
|
49
|
+
}
|
|
50
|
+
]
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
// 2. Validate the AI's intent (e.g., from an LLM tool call)
|
|
54
|
+
const aiIntent = { orderId: "ORD-99", amount: 500, reason: "Defective" };
|
|
55
|
+
|
|
56
|
+
const result = await refundGuard.validate(aiIntent);
|
|
57
|
+
|
|
58
|
+
if (!result.success) {
|
|
59
|
+
console.log("π« Action Blocked:", result.error);
|
|
60
|
+
// Output: "Refunds over $100 require manual manager intervention."
|
|
61
|
+
}
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
---
|
|
65
|
+
|
|
66
|
+
## β¨ Key Features
|
|
67
|
+
|
|
68
|
+
* β
**Type-Safe Validation:** Full TypeScript support with [Zod](https://zod.dev/) integration.
|
|
69
|
+
* π‘οΈ **Business Rule Engine:** Go beyond data types. Set custom logic for risk scores and safety limits.
|
|
70
|
+
* π€ **AI Self-Correction:** Returns detailed error messages designed to help LLMs realize their mistake and retry.
|
|
71
|
+
* π¦ **Lightweight & Fast:** Zero bloat, optimized for high-throughput Node.js environments like Express or AWS Lambda.
|
|
72
|
+
* π **Audit Trail Ready:** Easily logs attempts to MongoDB or PostgreSQL for compliance and debugging.
|
|
73
|
+
|
|
74
|
+
---
|
|
75
|
+
|
|
76
|
+
## πΊοΈ Roadmap (Phase 1 & 2)
|
|
77
|
+
|
|
78
|
+
- [x] Core Zod Wrapper
|
|
79
|
+
- [x] Custom Safety Rules Engine
|
|
80
|
+
- [ ] **Middleware Support:** First-class support for Express.js and Fastify.
|
|
81
|
+
- [ ] **Human-in-the-Loop:** Built-in hooks for Slack/Discord "Approve/Deny" buttons.
|
|
82
|
+
- [ ] **Tool Definition Generator:** Automatically export OpenAI-compatible JSON tool definitions from your guards.
|
|
83
|
+
|
|
84
|
+
---
|
|
85
|
+
|
|
86
|
+
## π€ Contributing
|
|
87
|
+
|
|
88
|
+
This is an early-stage project built to solve AI trust issues. If you have ideas for safety patterns (Human-in-the-loop, rate limiting for agents, etc.), feel free to open an issue!
|
|
89
|
+
|
|
90
|
+
## π License
|
|
91
|
+
|
|
92
|
+
MIT Β© [josephallwin1996]
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/index.ts
|
|
21
|
+
var index_exports = {};
|
|
22
|
+
__export(index_exports, {
|
|
23
|
+
AIGuard: () => AIGuard,
|
|
24
|
+
createGuard: () => createGuard
|
|
25
|
+
});
|
|
26
|
+
module.exports = __toCommonJS(index_exports);
|
|
27
|
+
var import_zod = require("zod");
|
|
28
|
+
var AIGuard = class {
|
|
29
|
+
constructor(config) {
|
|
30
|
+
this.config = config;
|
|
31
|
+
}
|
|
32
|
+
async validate(input) {
|
|
33
|
+
const result = await this.config.schema.safeParseAsync(input);
|
|
34
|
+
if (!result.success) {
|
|
35
|
+
return { success: false, error: result.error.format() };
|
|
36
|
+
}
|
|
37
|
+
if (this.config.maxLimit && result.data.amount > this.config.maxLimit) {
|
|
38
|
+
return { success: false, error: "Safety limit exceeded!" };
|
|
39
|
+
}
|
|
40
|
+
return { success: true, data: result.data };
|
|
41
|
+
}
|
|
42
|
+
};
|
|
43
|
+
function createGuard(config) {
|
|
44
|
+
return new AIGuard(config);
|
|
45
|
+
}
|
|
46
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
47
|
+
0 && (module.exports = {
|
|
48
|
+
AIGuard,
|
|
49
|
+
createGuard
|
|
50
|
+
});
|
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
|
|
3
|
+
interface GuardConfig<T extends z.ZodRawShape> {
|
|
4
|
+
name: string;
|
|
5
|
+
schema: z.ZodObject<T>;
|
|
6
|
+
maxLimit?: number;
|
|
7
|
+
}
|
|
8
|
+
declare class AIGuard<T extends z.ZodRawShape> {
|
|
9
|
+
private config;
|
|
10
|
+
constructor(config: GuardConfig<T>);
|
|
11
|
+
validate(input: unknown): Promise<{
|
|
12
|
+
success: boolean;
|
|
13
|
+
error: z.core.$ZodFormattedError<z.core.$InferObjectOutput<T, {}>, string>;
|
|
14
|
+
data?: never;
|
|
15
|
+
} | {
|
|
16
|
+
success: boolean;
|
|
17
|
+
error: string;
|
|
18
|
+
data?: never;
|
|
19
|
+
} | {
|
|
20
|
+
success: boolean;
|
|
21
|
+
data: z.core.$InferObjectOutput<T, {}>;
|
|
22
|
+
error?: never;
|
|
23
|
+
}>;
|
|
24
|
+
}
|
|
25
|
+
declare function createGuard<T extends z.ZodRawShape>(config: GuardConfig<T>): AIGuard<T>;
|
|
26
|
+
|
|
27
|
+
export { AIGuard, type GuardConfig, createGuard };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
|
|
3
|
+
interface GuardConfig<T extends z.ZodRawShape> {
|
|
4
|
+
name: string;
|
|
5
|
+
schema: z.ZodObject<T>;
|
|
6
|
+
maxLimit?: number;
|
|
7
|
+
}
|
|
8
|
+
declare class AIGuard<T extends z.ZodRawShape> {
|
|
9
|
+
private config;
|
|
10
|
+
constructor(config: GuardConfig<T>);
|
|
11
|
+
validate(input: unknown): Promise<{
|
|
12
|
+
success: boolean;
|
|
13
|
+
error: z.core.$ZodFormattedError<z.core.$InferObjectOutput<T, {}>, string>;
|
|
14
|
+
data?: never;
|
|
15
|
+
} | {
|
|
16
|
+
success: boolean;
|
|
17
|
+
error: string;
|
|
18
|
+
data?: never;
|
|
19
|
+
} | {
|
|
20
|
+
success: boolean;
|
|
21
|
+
data: z.core.$InferObjectOutput<T, {}>;
|
|
22
|
+
error?: never;
|
|
23
|
+
}>;
|
|
24
|
+
}
|
|
25
|
+
declare function createGuard<T extends z.ZodRawShape>(config: GuardConfig<T>): AIGuard<T>;
|
|
26
|
+
|
|
27
|
+
export { AIGuard, type GuardConfig, createGuard };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
// src/index.ts
|
|
2
|
+
import "zod";
|
|
3
|
+
var AIGuard = class {
|
|
4
|
+
constructor(config) {
|
|
5
|
+
this.config = config;
|
|
6
|
+
}
|
|
7
|
+
async validate(input) {
|
|
8
|
+
const result = await this.config.schema.safeParseAsync(input);
|
|
9
|
+
if (!result.success) {
|
|
10
|
+
return { success: false, error: result.error.format() };
|
|
11
|
+
}
|
|
12
|
+
if (this.config.maxLimit && result.data.amount > this.config.maxLimit) {
|
|
13
|
+
return { success: false, error: "Safety limit exceeded!" };
|
|
14
|
+
}
|
|
15
|
+
return { success: true, data: result.data };
|
|
16
|
+
}
|
|
17
|
+
};
|
|
18
|
+
function createGuard(config) {
|
|
19
|
+
return new AIGuard(config);
|
|
20
|
+
}
|
|
21
|
+
export {
|
|
22
|
+
AIGuard,
|
|
23
|
+
createGuard
|
|
24
|
+
};
|
package/package.json
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "node-ai-guard",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "A lightweight TypeScript/Node.js safety layer for AI Agents. Secure your APIs against LLM hallucinations and excessive agency using Zod-powered guardrails",
|
|
5
|
+
"main": "./dist/index.cjs",
|
|
6
|
+
"module": "./dist/index.js",
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
8
|
+
"files": ["dist"],
|
|
9
|
+
"scripts": {
|
|
10
|
+
"dev": "tsx watch src/index.ts",
|
|
11
|
+
"build": "tsup src/index.ts --format cjs,esm --dts --clean",
|
|
12
|
+
"lint": "tsc --noEmit"
|
|
13
|
+
},
|
|
14
|
+
"repository": {
|
|
15
|
+
"type": "git",
|
|
16
|
+
"url": "git+https://github.com/josephallwin1996/node-ai-guard.git"
|
|
17
|
+
},
|
|
18
|
+
"keywords": ["ai", "agents", "security", "guardrails", "zod"],
|
|
19
|
+
"author": "Joseph Allwin",
|
|
20
|
+
"license": "MIT",
|
|
21
|
+
"type": "module",
|
|
22
|
+
"bugs": {
|
|
23
|
+
"url": "https://github.com/josephallwin1996/node-ai-guard/issues"
|
|
24
|
+
},
|
|
25
|
+
"homepage": "https://github.com/josephallwin1996/node-ai-guard#readme",
|
|
26
|
+
"dependencies": {
|
|
27
|
+
"zod": "^4.3.6"
|
|
28
|
+
},
|
|
29
|
+
"devDependencies": {
|
|
30
|
+
"tsup": "^8.5.1",
|
|
31
|
+
"tsx": "^4.21.0",
|
|
32
|
+
"typescript": "^5.9.3"
|
|
33
|
+
}
|
|
34
|
+
}
|