promptdefend 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/LICENSE +36 -0
- package/README.md +174 -0
- package/index.d.ts +115 -0
- package/index.js +250 -0
- package/index.mjs +172 -0
- package/package.json +61 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
PROMPT DEFEND SDK - PROPRIETARY SOFTWARE LICENSE
|
|
2
|
+
|
|
3
|
+
Copyright © 2026 Prompt Defend. All Rights Reserved.
|
|
4
|
+
|
|
5
|
+
This SDK is provided to enable integration with the Prompt Defend API service.
|
|
6
|
+
Use of this SDK is subject to the Prompt Defend Terms of Service.
|
|
7
|
+
|
|
8
|
+
1. LICENSE GRANT
|
|
9
|
+
|
|
10
|
+
You are granted a limited, non-exclusive, non-transferable license to use this
|
|
11
|
+
SDK solely for the purpose of integrating with Prompt Defend's API services
|
|
12
|
+
under an active subscription.
|
|
13
|
+
|
|
14
|
+
2. RESTRICTIONS
|
|
15
|
+
|
|
16
|
+
You may NOT:
|
|
17
|
+
- Modify, adapt, or create derivative works of this SDK
|
|
18
|
+
- Reverse engineer, decompile, or disassemble this SDK
|
|
19
|
+
- Redistribute this SDK outside of your organization
|
|
20
|
+
- Use this SDK to build competing products or services
|
|
21
|
+
- Remove or alter any proprietary notices
|
|
22
|
+
|
|
23
|
+
3. NO WARRANTY
|
|
24
|
+
|
|
25
|
+
THIS SDK IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. PROMPT DEFEND
|
|
26
|
+
DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED.
|
|
27
|
+
|
|
28
|
+
4. LIMITATION OF LIABILITY
|
|
29
|
+
|
|
30
|
+
PROMPT DEFEND SHALL NOT BE LIABLE FOR ANY DAMAGES ARISING FROM THE USE OF
|
|
31
|
+
THIS SDK.
|
|
32
|
+
|
|
33
|
+
---
|
|
34
|
+
|
|
35
|
+
For support: support@promptdefend.dev
|
|
36
|
+
Website: https://promptdefend.dev
|
package/README.md
ADDED
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
# Prompt Defend Node.js SDK
|
|
2
|
+
|
|
3
|
+
[](https://badge.fury.io/js/promptdefend)
|
|
4
|
+
[](https://nodejs.org)
|
|
5
|
+
|
|
6
|
+
The official Node.js SDK for the [Prompt Defend](https://promptdefend.dev) AI Security API. Protect your AI applications with our 16-layer guardrail system.
|
|
7
|
+
|
|
8
|
+
## Installation
|
|
9
|
+
|
|
10
|
+
```bash
|
|
11
|
+
npm install promptdefend
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
Or with yarn:
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
yarn add promptdefend
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## Quick Start
|
|
21
|
+
|
|
22
|
+
```javascript
|
|
23
|
+
const { PromptDefend } = require('promptdefend');
|
|
24
|
+
|
|
25
|
+
// Initialize the client with your API key
|
|
26
|
+
const client = new PromptDefend({ apiKey: 'your-api-key' });
|
|
27
|
+
|
|
28
|
+
// Scan a prompt for security issues
|
|
29
|
+
const result = await client.scan('What is the weather today?');
|
|
30
|
+
|
|
31
|
+
if (result.safe) {
|
|
32
|
+
console.log('✅ Prompt is safe to process');
|
|
33
|
+
} else {
|
|
34
|
+
console.log(`⚠️ Warning: ${result.reason}`);
|
|
35
|
+
}
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## Features
|
|
39
|
+
|
|
40
|
+
- 🛡️ **16-Layer Protection** - Comprehensive guardrail system
|
|
41
|
+
- 🔒 **Prompt Injection Detection** - Block jailbreak and injection attempts
|
|
42
|
+
- ⚡ **Sub-millisecond Latency** - Average response time ~0.7ms
|
|
43
|
+
- 📦 **TypeScript Support** - Full type definitions included
|
|
44
|
+
- 🔧 **Error Handling** - Comprehensive error classes
|
|
45
|
+
- 🌐 **ESM & CommonJS** - Works with both module systems
|
|
46
|
+
|
|
47
|
+
## Usage
|
|
48
|
+
|
|
49
|
+
### ESM (ES Modules)
|
|
50
|
+
|
|
51
|
+
```javascript
|
|
52
|
+
import { PromptDefend } from 'promptdefend';
|
|
53
|
+
|
|
54
|
+
const client = new PromptDefend({ apiKey: 'your-api-key' });
|
|
55
|
+
const result = await client.scan('Hello, how are you?');
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
### CommonJS
|
|
59
|
+
|
|
60
|
+
```javascript
|
|
61
|
+
const { PromptDefend } = require('promptdefend');
|
|
62
|
+
|
|
63
|
+
const client = new PromptDefend({ apiKey: 'your-api-key' });
|
|
64
|
+
const result = await client.scan('Hello, how are you?');
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
### TypeScript
|
|
68
|
+
|
|
69
|
+
```typescript
|
|
70
|
+
import { PromptDefend, ScanResult, PromptDefendOptions } from 'promptdefend';
|
|
71
|
+
|
|
72
|
+
const options: PromptDefendOptions = {
|
|
73
|
+
apiKey: 'your-api-key',
|
|
74
|
+
baseUrl: 'https://api.promptdefend.dev'
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
const client = new PromptDefend(options);
|
|
78
|
+
const result: ScanResult = await client.scan('Test prompt');
|
|
79
|
+
|
|
80
|
+
console.log(result.safe); // boolean
|
|
81
|
+
console.log(result.reason); // string
|
|
82
|
+
console.log(result.details); // object
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
### Custom Configuration
|
|
86
|
+
|
|
87
|
+
```javascript
|
|
88
|
+
const { PromptDefend } = require('promptdefend');
|
|
89
|
+
|
|
90
|
+
const client = new PromptDefend({
|
|
91
|
+
apiKey: 'your-api-key',
|
|
92
|
+
baseUrl: 'https://api.promptdefend.dev', // Optional custom endpoint
|
|
93
|
+
timeout: 60000 // Custom timeout in milliseconds
|
|
94
|
+
});
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
## Error Handling
|
|
98
|
+
|
|
99
|
+
The SDK provides specific error classes for different error types:
|
|
100
|
+
|
|
101
|
+
```javascript
|
|
102
|
+
const {
|
|
103
|
+
PromptDefend,
|
|
104
|
+
PromptDefendError,
|
|
105
|
+
AuthenticationError,
|
|
106
|
+
NetworkError,
|
|
107
|
+
APIError
|
|
108
|
+
} = require('promptdefend');
|
|
109
|
+
|
|
110
|
+
const client = new PromptDefend({ apiKey: 'your-api-key' });
|
|
111
|
+
|
|
112
|
+
try {
|
|
113
|
+
const result = await client.scan('Test prompt');
|
|
114
|
+
} catch (error) {
|
|
115
|
+
if (error instanceof AuthenticationError) {
|
|
116
|
+
console.error(`Invalid API key: ${error.message}`);
|
|
117
|
+
} else if (error instanceof NetworkError) {
|
|
118
|
+
console.error(`Network issue: ${error.message}`);
|
|
119
|
+
} else if (error instanceof APIError) {
|
|
120
|
+
console.error(`API error (status ${error.statusCode}): ${error.message}`);
|
|
121
|
+
} else if (error instanceof PromptDefendError) {
|
|
122
|
+
console.error(`General error: ${error.message}`);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
## Response Object
|
|
128
|
+
|
|
129
|
+
The `scan()` method returns a `ScanResult` object with the following properties:
|
|
130
|
+
|
|
131
|
+
| Property | Type | Description |
|
|
132
|
+
|----------|------|-------------|
|
|
133
|
+
| `safe` | `boolean` | Whether the prompt is safe to process |
|
|
134
|
+
| `reason` | `string` | Explanation of the safety assessment |
|
|
135
|
+
| `details` | `object` | Full detection details from all 16 layers |
|
|
136
|
+
| `fastPath` | `boolean` | Whether allowlist short-circuit was used |
|
|
137
|
+
|
|
138
|
+
## API Reference
|
|
139
|
+
|
|
140
|
+
### PromptDefend Class
|
|
141
|
+
|
|
142
|
+
#### Constructor Options
|
|
143
|
+
|
|
144
|
+
```typescript
|
|
145
|
+
interface PromptDefendOptions {
|
|
146
|
+
apiKey: string; // Required: Your API key
|
|
147
|
+
baseUrl?: string; // Optional: Custom API base URL
|
|
148
|
+
timeout?: number; // Optional: Request timeout in milliseconds (default: 30000)
|
|
149
|
+
}
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
#### Methods
|
|
153
|
+
|
|
154
|
+
| Method | Description |
|
|
155
|
+
|--------|-------------|
|
|
156
|
+
| `scan(promptText: string): Promise<ScanResult>` | Scan a prompt and return results |
|
|
157
|
+
|
|
158
|
+
## Requirements
|
|
159
|
+
|
|
160
|
+
- Node.js 18.0.0 or higher
|
|
161
|
+
|
|
162
|
+
## License
|
|
163
|
+
|
|
164
|
+
This SDK is proprietary software. See [LICENSE](LICENSE) for details.
|
|
165
|
+
|
|
166
|
+
## Support
|
|
167
|
+
|
|
168
|
+
- 📚 [Documentation](https://docs.promptdefend.dev)
|
|
169
|
+
- 📧 [Email Support](mailto:support@promptdefend.dev)
|
|
170
|
+
- 🌐 [Website](https://promptdefend.dev)
|
|
171
|
+
|
|
172
|
+
---
|
|
173
|
+
|
|
174
|
+
© 2026 Prompt Defend. All Rights Reserved.
|
package/index.d.ts
ADDED
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TypeScript declarations for PromptJudge Node.js SDK
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
declare module 'promptjudge' {
|
|
6
|
+
export const VERSION: string;
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Base error class for PromptJudge errors.
|
|
10
|
+
*/
|
|
11
|
+
export class PromptJudgeError extends Error {
|
|
12
|
+
constructor(message: string);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Error thrown when API key is invalid or missing.
|
|
17
|
+
*/
|
|
18
|
+
export class AuthenticationError extends PromptJudgeError {
|
|
19
|
+
constructor(message: string);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Error thrown when a network error occurs.
|
|
24
|
+
*/
|
|
25
|
+
export class NetworkError extends PromptJudgeError {
|
|
26
|
+
constructor(message: string);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Error thrown when the API returns an error response.
|
|
31
|
+
*/
|
|
32
|
+
export class APIError extends PromptJudgeError {
|
|
33
|
+
statusCode: number | null;
|
|
34
|
+
constructor(message: string, statusCode?: number | null);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Represents the result of a prompt scan.
|
|
39
|
+
*/
|
|
40
|
+
export class ScanResult {
|
|
41
|
+
/** Whether the prompt is safe to process */
|
|
42
|
+
safe: boolean;
|
|
43
|
+
/** Explanation of the safety assessment */
|
|
44
|
+
reason: string;
|
|
45
|
+
|
|
46
|
+
constructor(safe: boolean, reason: string);
|
|
47
|
+
|
|
48
|
+
/** Convert the result to a plain object */
|
|
49
|
+
toJSON(): { safe: boolean; reason: string };
|
|
50
|
+
|
|
51
|
+
/** String representation of the result */
|
|
52
|
+
toString(): string;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Configuration options for PromptJudge client.
|
|
57
|
+
*/
|
|
58
|
+
export interface PromptJudgeOptions {
|
|
59
|
+
/** Your PromptJudge API key (required) */
|
|
60
|
+
apiKey: string;
|
|
61
|
+
/** Custom API base URL */
|
|
62
|
+
baseUrl?: string;
|
|
63
|
+
/** Request timeout in milliseconds (default: 30000) */
|
|
64
|
+
timeout?: number;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* PromptJudge API client.
|
|
69
|
+
*
|
|
70
|
+
* @example
|
|
71
|
+
* ```typescript
|
|
72
|
+
* import { PromptJudge } from 'promptjudge';
|
|
73
|
+
*
|
|
74
|
+
* const client = new PromptJudge({ apiKey: 'your-api-key' });
|
|
75
|
+
* const result = await client.scan('Hello, how are you?');
|
|
76
|
+
* console.log(result.safe);
|
|
77
|
+
* ```
|
|
78
|
+
*/
|
|
79
|
+
export class PromptJudge {
|
|
80
|
+
/** Your PromptJudge API key */
|
|
81
|
+
apiKey: string;
|
|
82
|
+
/** API base URL */
|
|
83
|
+
baseUrl: string;
|
|
84
|
+
/** Request timeout in milliseconds */
|
|
85
|
+
timeout: number;
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Create a PromptJudge client.
|
|
89
|
+
* @param options - Configuration options
|
|
90
|
+
*/
|
|
91
|
+
constructor(options: PromptJudgeOptions);
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Scan a prompt for security issues.
|
|
95
|
+
*
|
|
96
|
+
* @param promptText - The prompt text to analyze
|
|
97
|
+
* @returns Promise resolving to the scan result
|
|
98
|
+
* @throws {AuthenticationError} If the API key is invalid
|
|
99
|
+
* @throws {NetworkError} If a network error occurs
|
|
100
|
+
* @throws {APIError} If the API returns an error response
|
|
101
|
+
*/
|
|
102
|
+
scan(promptText: string): Promise<ScanResult>;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Convenience function to scan a prompt without creating a client instance.
|
|
107
|
+
*
|
|
108
|
+
* @param apiKey - Your PromptJudge API key
|
|
109
|
+
* @param promptText - The prompt text to analyze
|
|
110
|
+
* @returns Promise resolving to the scan result
|
|
111
|
+
*/
|
|
112
|
+
export function scan(apiKey: string, promptText: string): Promise<ScanResult>;
|
|
113
|
+
|
|
114
|
+
export default PromptJudge;
|
|
115
|
+
}
|
package/index.js
ADDED
|
@@ -0,0 +1,250 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PromptJudge Node.js SDK
|
|
3
|
+
* A client library for the PromptJudge AI Security API.
|
|
4
|
+
*
|
|
5
|
+
* @module promptjudge
|
|
6
|
+
* @version 1.0.0
|
|
7
|
+
* @license MIT
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
'use strict';
|
|
11
|
+
|
|
12
|
+
const VERSION = '1.0.0';
|
|
13
|
+
const DEFAULT_BASE_URL = 'https://api.promptjudge.com';
|
|
14
|
+
const DEFAULT_TIMEOUT = 30000; // 30 seconds in milliseconds
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Base error class for PromptJudge errors.
|
|
18
|
+
*/
|
|
19
|
+
class PromptJudgeError extends Error {
|
|
20
|
+
constructor(message) {
|
|
21
|
+
super(message);
|
|
22
|
+
this.name = 'PromptJudgeError';
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Error thrown when API key is invalid or missing.
|
|
28
|
+
*/
|
|
29
|
+
class AuthenticationError extends PromptJudgeError {
|
|
30
|
+
constructor(message) {
|
|
31
|
+
super(message);
|
|
32
|
+
this.name = 'AuthenticationError';
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Error thrown when a network error occurs.
|
|
38
|
+
*/
|
|
39
|
+
class NetworkError extends PromptJudgeError {
|
|
40
|
+
constructor(message) {
|
|
41
|
+
super(message);
|
|
42
|
+
this.name = 'NetworkError';
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Error thrown when the API returns an error response.
|
|
48
|
+
*/
|
|
49
|
+
class APIError extends PromptJudgeError {
|
|
50
|
+
constructor(message, statusCode = null) {
|
|
51
|
+
super(message);
|
|
52
|
+
this.name = 'APIError';
|
|
53
|
+
this.statusCode = statusCode;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Represents the result of a prompt scan.
|
|
59
|
+
*/
|
|
60
|
+
class ScanResult {
|
|
61
|
+
/**
|
|
62
|
+
* @param {boolean} safe - Whether the prompt is safe
|
|
63
|
+
* @param {string} reason - Explanation of the safety assessment
|
|
64
|
+
*/
|
|
65
|
+
constructor(safe, reason) {
|
|
66
|
+
this.safe = safe;
|
|
67
|
+
this.reason = reason;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Convert the result to a plain object.
|
|
72
|
+
* @returns {Object} Plain object representation
|
|
73
|
+
*/
|
|
74
|
+
toJSON() {
|
|
75
|
+
return {
|
|
76
|
+
safe: this.safe,
|
|
77
|
+
reason: this.reason
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* String representation of the result.
|
|
83
|
+
* @returns {string}
|
|
84
|
+
*/
|
|
85
|
+
toString() {
|
|
86
|
+
return `ScanResult { safe: ${this.safe}, reason: '${this.reason}' }`;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* PromptJudge API client.
|
|
92
|
+
*
|
|
93
|
+
* @example
|
|
94
|
+
* const { PromptJudge } = require('promptjudge');
|
|
95
|
+
*
|
|
96
|
+
* const client = new PromptJudge({ apiKey: 'your-api-key' });
|
|
97
|
+
* const result = await client.scan('Hello, how are you?');
|
|
98
|
+
* console.log(result.safe);
|
|
99
|
+
*/
|
|
100
|
+
class PromptJudge {
|
|
101
|
+
/**
|
|
102
|
+
* Create a PromptJudge client.
|
|
103
|
+
*
|
|
104
|
+
* @param {Object} options - Configuration options
|
|
105
|
+
* @param {string} options.apiKey - Your PromptJudge API key (required)
|
|
106
|
+
* @param {string} [options.baseUrl] - Custom API base URL
|
|
107
|
+
* @param {number} [options.timeout] - Request timeout in milliseconds
|
|
108
|
+
*/
|
|
109
|
+
constructor(options = {}) {
|
|
110
|
+
const { apiKey, baseUrl, timeout } = options;
|
|
111
|
+
|
|
112
|
+
if (!apiKey) {
|
|
113
|
+
throw new AuthenticationError('API key is required');
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
this.apiKey = apiKey;
|
|
117
|
+
this.baseUrl = (baseUrl || DEFAULT_BASE_URL).replace(/\/$/, '');
|
|
118
|
+
this.timeout = timeout || DEFAULT_TIMEOUT;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Scan a prompt for security issues.
|
|
123
|
+
*
|
|
124
|
+
* @param {string} promptText - The prompt text to analyze
|
|
125
|
+
* @returns {Promise<ScanResult>} The scan result
|
|
126
|
+
* @throws {AuthenticationError} If the API key is invalid
|
|
127
|
+
* @throws {NetworkError} If a network error occurs
|
|
128
|
+
* @throws {APIError} If the API returns an error response
|
|
129
|
+
*
|
|
130
|
+
* @example
|
|
131
|
+
* const result = await client.scan('What is the weather today?');
|
|
132
|
+
* if (result.safe) {
|
|
133
|
+
* console.log('Prompt is safe to process');
|
|
134
|
+
* } else {
|
|
135
|
+
* console.log(`Warning: ${result.reason}`);
|
|
136
|
+
* }
|
|
137
|
+
*/
|
|
138
|
+
async scan(promptText) {
|
|
139
|
+
if (typeof promptText !== 'string') {
|
|
140
|
+
throw new TypeError('promptText must be a string');
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
if (!promptText.trim()) {
|
|
144
|
+
throw new Error('promptText cannot be empty');
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
const url = `${this.baseUrl}/v1/scan`;
|
|
148
|
+
const payload = { prompt: promptText };
|
|
149
|
+
|
|
150
|
+
let response;
|
|
151
|
+
|
|
152
|
+
try {
|
|
153
|
+
const controller = new AbortController();
|
|
154
|
+
const timeoutId = setTimeout(() => controller.abort(), this.timeout);
|
|
155
|
+
|
|
156
|
+
response = await fetch(url, {
|
|
157
|
+
method: 'POST',
|
|
158
|
+
headers: {
|
|
159
|
+
'Authorization': `Bearer ${this.apiKey}`,
|
|
160
|
+
'Content-Type': 'application/json',
|
|
161
|
+
'User-Agent': `promptjudge-node/${VERSION}`
|
|
162
|
+
},
|
|
163
|
+
body: JSON.stringify(payload),
|
|
164
|
+
signal: controller.signal
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
clearTimeout(timeoutId);
|
|
168
|
+
} catch (error) {
|
|
169
|
+
if (error.name === 'AbortError') {
|
|
170
|
+
throw new NetworkError('Request timed out. Please try again.');
|
|
171
|
+
}
|
|
172
|
+
if (error.code === 'ENOTFOUND' || error.code === 'ECONNREFUSED') {
|
|
173
|
+
throw new NetworkError('Failed to connect to the API. Please check your internet connection.');
|
|
174
|
+
}
|
|
175
|
+
throw new NetworkError(`Network error occurred: ${error.message}`);
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
// Handle authentication errors
|
|
179
|
+
if (response.status === 401) {
|
|
180
|
+
throw new AuthenticationError('Invalid API key. Please check your credentials.');
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
if (response.status === 403) {
|
|
184
|
+
throw new AuthenticationError('Access forbidden. Your API key may not have the required permissions.');
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
// Handle other error responses
|
|
188
|
+
if (!response.ok) {
|
|
189
|
+
let errorMessage = 'Unknown error';
|
|
190
|
+
try {
|
|
191
|
+
const errorData = await response.json();
|
|
192
|
+
errorMessage = errorData.error || errorData.message || errorMessage;
|
|
193
|
+
} catch {
|
|
194
|
+
try {
|
|
195
|
+
errorMessage = await response.text() || errorMessage;
|
|
196
|
+
} catch {
|
|
197
|
+
// Use default error message
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
throw new APIError(`API error: ${errorMessage}`, response.status);
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
// Parse successful response
|
|
205
|
+
let data;
|
|
206
|
+
try {
|
|
207
|
+
data = await response.json();
|
|
208
|
+
} catch {
|
|
209
|
+
throw new APIError('Invalid JSON response from API');
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
if (typeof data.safe === 'undefined' || typeof data.reason === 'undefined') {
|
|
213
|
+
throw new APIError("Invalid response format: missing 'safe' or 'reason' field");
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
return new ScanResult(Boolean(data.safe), String(data.reason));
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
/**
|
|
221
|
+
* Convenience function to scan a prompt without creating a client instance.
|
|
222
|
+
*
|
|
223
|
+
* @param {string} apiKey - Your PromptJudge API key
|
|
224
|
+
* @param {string} promptText - The prompt text to analyze
|
|
225
|
+
* @returns {Promise<ScanResult>} The scan result
|
|
226
|
+
*
|
|
227
|
+
* @example
|
|
228
|
+
* const { scan } = require('promptjudge');
|
|
229
|
+
* const result = await scan('your-api-key', 'Hello world');
|
|
230
|
+
* console.log(result.safe);
|
|
231
|
+
*/
|
|
232
|
+
async function scan(apiKey, promptText) {
|
|
233
|
+
const client = new PromptJudge({ apiKey });
|
|
234
|
+
return client.scan(promptText);
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
// CommonJS exports
|
|
238
|
+
module.exports = {
|
|
239
|
+
PromptJudge,
|
|
240
|
+
ScanResult,
|
|
241
|
+
PromptJudgeError,
|
|
242
|
+
AuthenticationError,
|
|
243
|
+
NetworkError,
|
|
244
|
+
APIError,
|
|
245
|
+
scan,
|
|
246
|
+
VERSION
|
|
247
|
+
};
|
|
248
|
+
|
|
249
|
+
// ES Module named exports (for dual-mode packages)
|
|
250
|
+
module.exports.default = PromptJudge;
|
package/index.mjs
ADDED
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PromptJudge Node.js SDK (ES Module version)
|
|
3
|
+
* A client library for the PromptJudge AI Security API.
|
|
4
|
+
*
|
|
5
|
+
* @module promptjudge
|
|
6
|
+
* @version 1.0.0
|
|
7
|
+
* @license MIT
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
const VERSION = '1.0.0';
|
|
11
|
+
const DEFAULT_BASE_URL = 'https://api.promptjudge.com';
|
|
12
|
+
const DEFAULT_TIMEOUT = 30000;
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Base error class for PromptJudge errors.
|
|
16
|
+
*/
|
|
17
|
+
export class PromptJudgeError extends Error {
|
|
18
|
+
constructor(message) {
|
|
19
|
+
super(message);
|
|
20
|
+
this.name = 'PromptJudgeError';
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Error thrown when API key is invalid or missing.
|
|
26
|
+
*/
|
|
27
|
+
export class AuthenticationError extends PromptJudgeError {
|
|
28
|
+
constructor(message) {
|
|
29
|
+
super(message);
|
|
30
|
+
this.name = 'AuthenticationError';
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Error thrown when a network error occurs.
|
|
36
|
+
*/
|
|
37
|
+
export class NetworkError extends PromptJudgeError {
|
|
38
|
+
constructor(message) {
|
|
39
|
+
super(message);
|
|
40
|
+
this.name = 'NetworkError';
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Error thrown when the API returns an error response.
|
|
46
|
+
*/
|
|
47
|
+
export class APIError extends PromptJudgeError {
|
|
48
|
+
constructor(message, statusCode = null) {
|
|
49
|
+
super(message);
|
|
50
|
+
this.name = 'APIError';
|
|
51
|
+
this.statusCode = statusCode;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Represents the result of a prompt scan.
|
|
57
|
+
*/
|
|
58
|
+
export class ScanResult {
|
|
59
|
+
constructor(safe, reason) {
|
|
60
|
+
this.safe = safe;
|
|
61
|
+
this.reason = reason;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
toJSON() {
|
|
65
|
+
return {
|
|
66
|
+
safe: this.safe,
|
|
67
|
+
reason: this.reason
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
toString() {
|
|
72
|
+
return `ScanResult { safe: ${this.safe}, reason: '${this.reason}' }`;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* PromptJudge API client.
|
|
78
|
+
*/
|
|
79
|
+
export class PromptJudge {
|
|
80
|
+
constructor(options = {}) {
|
|
81
|
+
const { apiKey, baseUrl, timeout } = options;
|
|
82
|
+
|
|
83
|
+
if (!apiKey) {
|
|
84
|
+
throw new AuthenticationError('API key is required');
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
this.apiKey = apiKey;
|
|
88
|
+
this.baseUrl = (baseUrl || DEFAULT_BASE_URL).replace(/\/$/, '');
|
|
89
|
+
this.timeout = timeout || DEFAULT_TIMEOUT;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
async scan(promptText) {
|
|
93
|
+
if (typeof promptText !== 'string') {
|
|
94
|
+
throw new TypeError('promptText must be a string');
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
if (!promptText.trim()) {
|
|
98
|
+
throw new Error('promptText cannot be empty');
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
const url = `${this.baseUrl}/v1/scan`;
|
|
102
|
+
const payload = { prompt: promptText };
|
|
103
|
+
|
|
104
|
+
let response;
|
|
105
|
+
|
|
106
|
+
try {
|
|
107
|
+
const controller = new AbortController();
|
|
108
|
+
const timeoutId = setTimeout(() => controller.abort(), this.timeout);
|
|
109
|
+
|
|
110
|
+
response = await fetch(url, {
|
|
111
|
+
method: 'POST',
|
|
112
|
+
headers: {
|
|
113
|
+
'Authorization': `Bearer ${this.apiKey}`,
|
|
114
|
+
'Content-Type': 'application/json',
|
|
115
|
+
'User-Agent': `promptjudge-node/${VERSION}`
|
|
116
|
+
},
|
|
117
|
+
body: JSON.stringify(payload),
|
|
118
|
+
signal: controller.signal
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
clearTimeout(timeoutId);
|
|
122
|
+
} catch (error) {
|
|
123
|
+
if (error.name === 'AbortError') {
|
|
124
|
+
throw new NetworkError('Request timed out. Please try again.');
|
|
125
|
+
}
|
|
126
|
+
throw new NetworkError(`Network error occurred: ${error.message}`);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
if (response.status === 401) {
|
|
130
|
+
throw new AuthenticationError('Invalid API key. Please check your credentials.');
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
if (response.status === 403) {
|
|
134
|
+
throw new AuthenticationError('Access forbidden. Your API key may not have the required permissions.');
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
if (!response.ok) {
|
|
138
|
+
let errorMessage = 'Unknown error';
|
|
139
|
+
try {
|
|
140
|
+
const errorData = await response.json();
|
|
141
|
+
errorMessage = errorData.error || errorData.message || errorMessage;
|
|
142
|
+
} catch {
|
|
143
|
+
// Use default error message
|
|
144
|
+
}
|
|
145
|
+
throw new APIError(`API error: ${errorMessage}`, response.status);
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
let data;
|
|
149
|
+
try {
|
|
150
|
+
data = await response.json();
|
|
151
|
+
} catch {
|
|
152
|
+
throw new APIError('Invalid JSON response from API');
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
if (typeof data.safe === 'undefined' || typeof data.reason === 'undefined') {
|
|
156
|
+
throw new APIError("Invalid response format: missing 'safe' or 'reason' field");
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
return new ScanResult(Boolean(data.safe), String(data.reason));
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
/**
|
|
164
|
+
* Convenience function to scan a prompt without creating a client instance.
|
|
165
|
+
*/
|
|
166
|
+
export async function scan(apiKey, promptText) {
|
|
167
|
+
const client = new PromptJudge({ apiKey });
|
|
168
|
+
return client.scan(promptText);
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
export { VERSION };
|
|
172
|
+
export default PromptJudge;
|
package/package.json
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "promptdefend",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Node.js SDK for the Prompt Defend AI Security API - 16-Layer Guardrail Protection",
|
|
5
|
+
"main": "index.js",
|
|
6
|
+
"types": "index.d.ts",
|
|
7
|
+
"exports": {
|
|
8
|
+
".": {
|
|
9
|
+
"require": "./index.js",
|
|
10
|
+
"import": "./index.mjs",
|
|
11
|
+
"types": "./index.d.ts"
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
"scripts": {
|
|
15
|
+
"test": "node --test",
|
|
16
|
+
"lint": "eslint .",
|
|
17
|
+
"format": "prettier --write .",
|
|
18
|
+
"prepublishOnly": "npm test"
|
|
19
|
+
},
|
|
20
|
+
"keywords": [
|
|
21
|
+
"promptdefend",
|
|
22
|
+
"prompt-defend",
|
|
23
|
+
"ai",
|
|
24
|
+
"security",
|
|
25
|
+
"prompt-injection",
|
|
26
|
+
"jailbreak",
|
|
27
|
+
"guardrails",
|
|
28
|
+
"llm",
|
|
29
|
+
"api",
|
|
30
|
+
"sdk",
|
|
31
|
+
"ai-security",
|
|
32
|
+
"chatgpt",
|
|
33
|
+
"openai",
|
|
34
|
+
"claude",
|
|
35
|
+
"safety"
|
|
36
|
+
],
|
|
37
|
+
"author": "Prompt Defend <support@promptdefend.dev>",
|
|
38
|
+
"license": "SEE LICENSE IN LICENSE",
|
|
39
|
+
"homepage": "https://promptdefend.dev",
|
|
40
|
+
"repository": {
|
|
41
|
+
"type": "git",
|
|
42
|
+
"url": "https://github.com/promptdefend/promptdefend-node"
|
|
43
|
+
},
|
|
44
|
+
"bugs": {
|
|
45
|
+
"url": "https://promptdefend.dev/support"
|
|
46
|
+
},
|
|
47
|
+
"engines": {
|
|
48
|
+
"node": ">=18.0.0"
|
|
49
|
+
},
|
|
50
|
+
"files": [
|
|
51
|
+
"index.js",
|
|
52
|
+
"index.mjs",
|
|
53
|
+
"index.d.ts",
|
|
54
|
+
"README.md",
|
|
55
|
+
"LICENSE"
|
|
56
|
+
],
|
|
57
|
+
"devDependencies": {
|
|
58
|
+
"eslint": "^8.50.0",
|
|
59
|
+
"prettier": "^3.0.0"
|
|
60
|
+
}
|
|
61
|
+
}
|