@driftgard/node 1.4.0 → 1.5.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 +27 -2
- package/dist/errors.d.ts +5 -0
- package/dist/errors.js +10 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.js +13 -2
- package/dist/types.d.ts +29 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -27,10 +27,32 @@ const result = await dg.evaluate({
|
|
|
27
27
|
if (result.evaluation.allowed) {
|
|
28
28
|
console.log("Safe to return to user");
|
|
29
29
|
} else {
|
|
30
|
+
// Use the fallback message if configured in your control pack
|
|
31
|
+
if (result.fallback) {
|
|
32
|
+
console.log("Show to user:", result.fallback.message);
|
|
33
|
+
}
|
|
30
34
|
console.log("Blocked:", result.evaluation.violations);
|
|
31
35
|
}
|
|
32
36
|
```
|
|
33
37
|
|
|
38
|
+
## Conversation tracking
|
|
39
|
+
|
|
40
|
+
Link evaluations within an agent session using `session_id` and `parent_evaluation_id`:
|
|
41
|
+
|
|
42
|
+
```typescript
|
|
43
|
+
const result = await dg.evaluate({
|
|
44
|
+
project_id: "your-project-id",
|
|
45
|
+
prompt: "Transfer $500 to account 12345",
|
|
46
|
+
response: "I've initiated the transfer.",
|
|
47
|
+
model_id: "gpt-4o",
|
|
48
|
+
session_id: "sess_abc123", // groups evals in a conversation
|
|
49
|
+
parent_evaluation_id: "eval_prev_id", // chains to the previous eval
|
|
50
|
+
});
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
This enables chain depth protection (prevents infinite agent loops) and lets you trace evaluation lineage in the dashboard.
|
|
54
|
+
```
|
|
55
|
+
|
|
34
56
|
## A/B experiments
|
|
35
57
|
|
|
36
58
|
Tag evaluations with an `experiment_id` to compare governance metrics across models:
|
|
@@ -73,7 +95,7 @@ All fields in `usage` are optional. When provided, token and cost data appears i
|
|
|
73
95
|
|
|
74
96
|
- Single `evaluate()` method — send prompt/response, get verdict
|
|
75
97
|
- Auto-retry with exponential backoff on 5xx and network errors
|
|
76
|
-
- Typed errors: `AuthError`, `RateLimitError`, `FeatureNotAvailableError`
|
|
98
|
+
- Typed errors: `AuthError`, `RateLimitError`, `FeatureNotAvailableError`, `ChainDepthExceededError`
|
|
77
99
|
- Full TypeScript types for requests and responses
|
|
78
100
|
- Zero dependencies (uses native `fetch`)
|
|
79
101
|
|
|
@@ -91,7 +113,7 @@ const dg = new Driftgard({
|
|
|
91
113
|
## Error handling
|
|
92
114
|
|
|
93
115
|
```typescript
|
|
94
|
-
import { Driftgard, AuthError, RateLimitError, FeatureNotAvailableError } from "@driftgard/node";
|
|
116
|
+
import { Driftgard, AuthError, RateLimitError, FeatureNotAvailableError, ChainDepthExceededError } from "@driftgard/node";
|
|
95
117
|
|
|
96
118
|
try {
|
|
97
119
|
const result = await dg.evaluate({ ... });
|
|
@@ -100,6 +122,9 @@ try {
|
|
|
100
122
|
// Invalid or revoked API key (401)
|
|
101
123
|
} else if (e instanceof RateLimitError) {
|
|
102
124
|
// Too many requests (429)
|
|
125
|
+
} else if (e instanceof ChainDepthExceededError) {
|
|
126
|
+
// Agent loop detected — chain depth exceeded (429)
|
|
127
|
+
console.log(`Depth ${e.depth} exceeds max ${e.max}`);
|
|
103
128
|
} else if (e instanceof FeatureNotAvailableError) {
|
|
104
129
|
// API evaluate requires Compliance+ tier (403)
|
|
105
130
|
}
|
package/dist/errors.d.ts
CHANGED
|
@@ -13,3 +13,8 @@ export declare class FeatureNotAvailableError extends DriftgardError {
|
|
|
13
13
|
tier: string;
|
|
14
14
|
constructor(message?: string, tier?: string);
|
|
15
15
|
}
|
|
16
|
+
export declare class ChainDepthExceededError extends DriftgardError {
|
|
17
|
+
depth: number;
|
|
18
|
+
max: number;
|
|
19
|
+
constructor(message?: string, depth?: number, max?: number);
|
|
20
|
+
}
|
package/dist/errors.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.FeatureNotAvailableError = exports.RateLimitError = exports.AuthError = exports.DriftgardError = void 0;
|
|
3
|
+
exports.ChainDepthExceededError = exports.FeatureNotAvailableError = exports.RateLimitError = exports.AuthError = exports.DriftgardError = void 0;
|
|
4
4
|
class DriftgardError extends Error {
|
|
5
5
|
constructor(message, status, code) {
|
|
6
6
|
super(message);
|
|
@@ -32,3 +32,12 @@ class FeatureNotAvailableError extends DriftgardError {
|
|
|
32
32
|
}
|
|
33
33
|
}
|
|
34
34
|
exports.FeatureNotAvailableError = FeatureNotAvailableError;
|
|
35
|
+
class ChainDepthExceededError extends DriftgardError {
|
|
36
|
+
constructor(message = "Evaluation chain depth exceeded", depth = 0, max = 0) {
|
|
37
|
+
super(message, 429, "chain_depth_exceeded");
|
|
38
|
+
this.name = "ChainDepthExceededError";
|
|
39
|
+
this.depth = depth;
|
|
40
|
+
this.max = max;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
exports.ChainDepthExceededError = ChainDepthExceededError;
|
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { DriftgardConfig, EvaluateRequest, EvaluateResponse } from "./types";
|
|
2
2
|
export { DriftgardConfig, EvaluateRequest, EvaluateResponse } from "./types";
|
|
3
|
-
export { Violation, EvaluationResult, HitlInfo } from "./types";
|
|
4
|
-
export { DriftgardError, AuthError, RateLimitError, FeatureNotAvailableError } from "./errors";
|
|
3
|
+
export { Violation, EvaluationResult, FallbackResponse, HitlInfo } from "./types";
|
|
4
|
+
export { DriftgardError, AuthError, RateLimitError, FeatureNotAvailableError, ChainDepthExceededError } from "./errors";
|
|
5
5
|
export declare class Driftgard {
|
|
6
6
|
private apiKey;
|
|
7
7
|
private baseUrl;
|
package/dist/index.js
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.Driftgard = exports.FeatureNotAvailableError = exports.RateLimitError = exports.AuthError = exports.DriftgardError = void 0;
|
|
3
|
+
exports.Driftgard = exports.ChainDepthExceededError = exports.FeatureNotAvailableError = exports.RateLimitError = exports.AuthError = exports.DriftgardError = void 0;
|
|
4
4
|
const errors_1 = require("./errors");
|
|
5
5
|
var errors_2 = require("./errors");
|
|
6
6
|
Object.defineProperty(exports, "DriftgardError", { enumerable: true, get: function () { return errors_2.DriftgardError; } });
|
|
7
7
|
Object.defineProperty(exports, "AuthError", { enumerable: true, get: function () { return errors_2.AuthError; } });
|
|
8
8
|
Object.defineProperty(exports, "RateLimitError", { enumerable: true, get: function () { return errors_2.RateLimitError; } });
|
|
9
9
|
Object.defineProperty(exports, "FeatureNotAvailableError", { enumerable: true, get: function () { return errors_2.FeatureNotAvailableError; } });
|
|
10
|
+
Object.defineProperty(exports, "ChainDepthExceededError", { enumerable: true, get: function () { return errors_2.ChainDepthExceededError; } });
|
|
10
11
|
const DEFAULT_BASE_URL = "https://api.driftgard.com";
|
|
11
12
|
const DEFAULT_TIMEOUT = 30000;
|
|
12
13
|
const DEFAULT_MAX_RETRIES = 2;
|
|
@@ -31,6 +32,11 @@ class Driftgard {
|
|
|
31
32
|
model_id: req.model_id,
|
|
32
33
|
timestamp: req.timestamp || new Date().toISOString(),
|
|
33
34
|
...(req.experiment_id ? { experiment_id: req.experiment_id } : {}),
|
|
35
|
+
...(req.session_id ? { session_id: req.session_id } : {}),
|
|
36
|
+
...(req.parent_evaluation_id ? { parent_evaluation_id: req.parent_evaluation_id } : {}),
|
|
37
|
+
...(req.control_pack_id ? { control_pack_id: req.control_pack_id } : {}),
|
|
38
|
+
...(req.control_pack_version ? { control_pack_version: req.control_pack_version } : {}),
|
|
39
|
+
...(req.dry_run ? { dry_run: req.dry_run } : {}),
|
|
34
40
|
...(req.usage ? { usage: req.usage } : {}),
|
|
35
41
|
});
|
|
36
42
|
}
|
|
@@ -49,8 +55,13 @@ class Driftgard {
|
|
|
49
55
|
});
|
|
50
56
|
if (res.status === 401)
|
|
51
57
|
throw new errors_1.AuthError();
|
|
52
|
-
if (res.status === 429)
|
|
58
|
+
if (res.status === 429) {
|
|
59
|
+
const payload = await res.json().catch(() => ({}));
|
|
60
|
+
if (payload?.error === "chain_depth_exceeded") {
|
|
61
|
+
throw new errors_1.ChainDepthExceededError(payload.message, payload.depth, payload.max);
|
|
62
|
+
}
|
|
53
63
|
throw new errors_1.RateLimitError();
|
|
64
|
+
}
|
|
54
65
|
if (res.status === 403) {
|
|
55
66
|
const payload = await res.json().catch(() => ({}));
|
|
56
67
|
if (payload?.error === "feature_not_available") {
|
package/dist/types.d.ts
CHANGED
|
@@ -11,6 +11,11 @@ export interface EvaluateRequest {
|
|
|
11
11
|
model_id: string;
|
|
12
12
|
timestamp?: string;
|
|
13
13
|
experiment_id?: string;
|
|
14
|
+
session_id?: string;
|
|
15
|
+
parent_evaluation_id?: string;
|
|
16
|
+
control_pack_id?: string;
|
|
17
|
+
control_pack_version?: number;
|
|
18
|
+
dry_run?: boolean;
|
|
14
19
|
usage?: {
|
|
15
20
|
prompt_tokens?: number;
|
|
16
21
|
completion_tokens?: number;
|
|
@@ -32,6 +37,10 @@ export interface EvaluationResult {
|
|
|
32
37
|
flags?: {
|
|
33
38
|
pii_detected?: boolean;
|
|
34
39
|
pii_in_prompt?: boolean;
|
|
40
|
+
secret_detected?: boolean;
|
|
41
|
+
adversarial_input?: boolean;
|
|
42
|
+
adversarial_score?: number;
|
|
43
|
+
dlp_findings_count?: number;
|
|
35
44
|
meta_bypass_detected?: boolean;
|
|
36
45
|
judge_used?: boolean;
|
|
37
46
|
judge_called?: boolean;
|
|
@@ -39,6 +48,14 @@ export interface EvaluationResult {
|
|
|
39
48
|
hard_blocked?: boolean;
|
|
40
49
|
};
|
|
41
50
|
}
|
|
51
|
+
export interface FallbackResponse {
|
|
52
|
+
message: string;
|
|
53
|
+
code: string;
|
|
54
|
+
action: string;
|
|
55
|
+
source: string;
|
|
56
|
+
escalated: boolean;
|
|
57
|
+
retry_after_ms?: number | null;
|
|
58
|
+
}
|
|
42
59
|
export interface HitlInfo {
|
|
43
60
|
queued: boolean;
|
|
44
61
|
hitl_id?: string;
|
|
@@ -53,6 +70,17 @@ export interface EvaluateResponse {
|
|
|
53
70
|
active_control_pack_version: number;
|
|
54
71
|
data_mode: string;
|
|
55
72
|
telemetry_mode: string;
|
|
56
|
-
|
|
73
|
+
dry_run?: boolean;
|
|
74
|
+
experiment_id?: string;
|
|
75
|
+
session_id?: string;
|
|
76
|
+
parent_evaluation_id?: string;
|
|
77
|
+
usage?: {
|
|
78
|
+
prompt_tokens?: number;
|
|
79
|
+
completion_tokens?: number;
|
|
80
|
+
total_tokens?: number;
|
|
81
|
+
cost?: number;
|
|
82
|
+
};
|
|
83
|
+
hitl?: HitlInfo;
|
|
57
84
|
evaluation: EvaluationResult;
|
|
85
|
+
fallback?: FallbackResponse;
|
|
58
86
|
}
|
package/package.json
CHANGED