@driftgard/node 1.2.0 → 1.3.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 CHANGED
@@ -46,6 +46,27 @@ const result = await dg.evaluate({
46
46
  ```
47
47
 
48
48
  View experiment results on the Experiments page in the Driftgard dashboard.
49
+
50
+ ## Cost attribution
51
+
52
+ Pass optional `usage` metadata to track token consumption and cost per evaluation:
53
+
54
+ ```typescript
55
+ const result = await dg.evaluate({
56
+ project_id: "your-project-id",
57
+ prompt: "What stocks should I buy?",
58
+ response: "Based on current trends, you should invest in...",
59
+ model_id: "gpt-4o",
60
+ usage: {
61
+ prompt_tokens: 150,
62
+ completion_tokens: 320,
63
+ total_tokens: 470,
64
+ cost: 0.0047, // USD
65
+ },
66
+ });
67
+ ```
68
+
69
+ All fields in `usage` are optional. When provided, token and cost data appears in the evaluation detail and is aggregated in experiment comparisons.
49
70
  ```
50
71
 
51
72
  ## Features
package/dist/index.js CHANGED
@@ -30,6 +30,8 @@ class Driftgard {
30
30
  response: req.response,
31
31
  model_id: req.model_id,
32
32
  timestamp: req.timestamp || new Date().toISOString(),
33
+ ...(req.experiment_id ? { experiment_id: req.experiment_id } : {}),
34
+ ...(req.usage ? { usage: req.usage } : {}),
33
35
  });
34
36
  }
35
37
  async post(path, body, attempt = 0) {
@@ -0,0 +1,44 @@
1
+ /**
2
+ * DriftGard LangChain.js integration.
3
+ *
4
+ * Usage:
5
+ * import { Driftgard } from "@driftgard/sdk";
6
+ * import { DriftgardCallback } from "@driftgard/sdk/langchain";
7
+ * import { ChatOpenAI } from "@langchain/openai";
8
+ *
9
+ * const callback = new DriftgardCallback({
10
+ * apiKey: "dg_xxx",
11
+ * projectId: "proj_xxx",
12
+ * onBlock: "throw", // "throw", "log", or "ignore"
13
+ * });
14
+ * const llm = new ChatOpenAI({ model: "gpt-4", callbacks: [callback] });
15
+ *
16
+ * Requires: npm install @langchain/core
17
+ */
18
+ interface DriftgardCallbackConfig {
19
+ apiKey: string;
20
+ projectId: string;
21
+ modelId?: string;
22
+ experimentId?: string;
23
+ onBlock?: "throw" | "log" | "ignore";
24
+ baseUrl?: string;
25
+ }
26
+ export declare class DriftgardCallback {
27
+ private client;
28
+ private projectId;
29
+ private modelId?;
30
+ private experimentId?;
31
+ private onBlock;
32
+ private prompts;
33
+ name: string;
34
+ constructor(config: DriftgardCallbackConfig);
35
+ handleLLMStart(_serialized: Record<string, unknown>, prompts: string[], runId: string): void;
36
+ handleLLMEnd(output: {
37
+ generations: Array<Array<{
38
+ text?: string;
39
+ }>>;
40
+ llmOutput?: Record<string, unknown>;
41
+ }, runId: string): Promise<void>;
42
+ handleLLMError(_error: Error, runId: string): void;
43
+ }
44
+ export {};
@@ -0,0 +1,85 @@
1
+ "use strict";
2
+ /**
3
+ * DriftGard LangChain.js integration.
4
+ *
5
+ * Usage:
6
+ * import { Driftgard } from "@driftgard/sdk";
7
+ * import { DriftgardCallback } from "@driftgard/sdk/langchain";
8
+ * import { ChatOpenAI } from "@langchain/openai";
9
+ *
10
+ * const callback = new DriftgardCallback({
11
+ * apiKey: "dg_xxx",
12
+ * projectId: "proj_xxx",
13
+ * onBlock: "throw", // "throw", "log", or "ignore"
14
+ * });
15
+ * const llm = new ChatOpenAI({ model: "gpt-4", callbacks: [callback] });
16
+ *
17
+ * Requires: npm install @langchain/core
18
+ */
19
+ Object.defineProperty(exports, "__esModule", { value: true });
20
+ exports.DriftgardCallback = void 0;
21
+ const index_1 = require("./index");
22
+ const errors_1 = require("./errors");
23
+ class DriftgardCallback {
24
+ constructor(config) {
25
+ this.prompts = new Map();
26
+ this.name = "DriftgardCallback";
27
+ this.client = new index_1.Driftgard({
28
+ apiKey: config.apiKey,
29
+ baseUrl: config.baseUrl,
30
+ });
31
+ this.projectId = config.projectId;
32
+ this.modelId = config.modelId;
33
+ this.experimentId = config.experimentId;
34
+ this.onBlock = config.onBlock || "throw";
35
+ }
36
+ handleLLMStart(_serialized, prompts, runId) {
37
+ this.prompts.set(runId, prompts[0] || "");
38
+ }
39
+ async handleLLMEnd(output, runId) {
40
+ const prompt = this.prompts.get(runId) || "";
41
+ this.prompts.delete(runId);
42
+ let text = "";
43
+ try {
44
+ text = output.generations?.[0]?.[0]?.text || "";
45
+ }
46
+ catch {
47
+ text = String(output);
48
+ }
49
+ if (!prompt && !text)
50
+ return;
51
+ const model = this.modelId
52
+ || output.llmOutput?.model_name
53
+ || output.llmOutput?.model
54
+ || "unknown";
55
+ try {
56
+ const result = await this.client.evaluate({
57
+ project_id: this.projectId,
58
+ prompt,
59
+ response: text,
60
+ model_id: model,
61
+ experiment_id: this.experimentId,
62
+ });
63
+ const evaluation = result.evaluation;
64
+ if (!evaluation?.allowed) {
65
+ const violations = evaluation?.violations || [];
66
+ const msg = `DriftGard blocked: risk_score=${evaluation?.risk_score ?? 0}, violations=${violations.length}`;
67
+ if (this.onBlock === "throw") {
68
+ throw new errors_1.DriftgardError(msg, 0, "blocked");
69
+ }
70
+ else if (this.onBlock === "log") {
71
+ console.warn(`[driftgard] ${msg} (evaluation_id=${result.evaluation_id})`);
72
+ }
73
+ }
74
+ }
75
+ catch (e) {
76
+ if (e instanceof errors_1.DriftgardError && this.onBlock === "throw")
77
+ throw e;
78
+ // Don't break the LLM pipeline on DriftGard errors
79
+ }
80
+ }
81
+ handleLLMError(_error, runId) {
82
+ this.prompts.delete(runId);
83
+ }
84
+ }
85
+ exports.DriftgardCallback = DriftgardCallback;
@@ -0,0 +1,46 @@
1
+ /**
2
+ * DriftGard LlamaIndex.TS integration.
3
+ *
4
+ * Usage:
5
+ * import { DriftgardLlamaIndexHandler } from "@driftgard/sdk/llamaindex";
6
+ * import { Settings } from "llamaindex";
7
+ *
8
+ * const handler = new DriftgardLlamaIndexHandler({
9
+ * apiKey: "dg_xxx",
10
+ * projectId: "proj_xxx",
11
+ * onBlock: "throw",
12
+ * });
13
+ * Settings.callbackManager.on("llm-end", handler.onLLMEnd.bind(handler));
14
+ *
15
+ * Requires: npm install llamaindex
16
+ */
17
+ interface DriftgardLlamaIndexConfig {
18
+ apiKey: string;
19
+ projectId: string;
20
+ modelId?: string;
21
+ experimentId?: string;
22
+ onBlock?: "throw" | "log" | "ignore";
23
+ baseUrl?: string;
24
+ }
25
+ export declare class DriftgardLlamaIndexHandler {
26
+ private client;
27
+ private projectId;
28
+ private modelId?;
29
+ private experimentId?;
30
+ private onBlock;
31
+ constructor(config: DriftgardLlamaIndexConfig);
32
+ /**
33
+ * Call this on LLM end events.
34
+ * Accepts the prompt and response text, evaluates via DriftGard.
35
+ */
36
+ evaluate(prompt: string, response: string, model?: string): Promise<void>;
37
+ /**
38
+ * Convenience handler for LlamaIndex callback manager "llm-end" events.
39
+ */
40
+ onLLMEnd(payload: {
41
+ prompt?: string;
42
+ response?: string;
43
+ model?: string;
44
+ }): Promise<void>;
45
+ }
46
+ export {};
@@ -0,0 +1,72 @@
1
+ "use strict";
2
+ /**
3
+ * DriftGard LlamaIndex.TS integration.
4
+ *
5
+ * Usage:
6
+ * import { DriftgardLlamaIndexHandler } from "@driftgard/sdk/llamaindex";
7
+ * import { Settings } from "llamaindex";
8
+ *
9
+ * const handler = new DriftgardLlamaIndexHandler({
10
+ * apiKey: "dg_xxx",
11
+ * projectId: "proj_xxx",
12
+ * onBlock: "throw",
13
+ * });
14
+ * Settings.callbackManager.on("llm-end", handler.onLLMEnd.bind(handler));
15
+ *
16
+ * Requires: npm install llamaindex
17
+ */
18
+ Object.defineProperty(exports, "__esModule", { value: true });
19
+ exports.DriftgardLlamaIndexHandler = void 0;
20
+ const index_1 = require("./index");
21
+ const errors_1 = require("./errors");
22
+ class DriftgardLlamaIndexHandler {
23
+ constructor(config) {
24
+ this.client = new index_1.Driftgard({
25
+ apiKey: config.apiKey,
26
+ baseUrl: config.baseUrl,
27
+ });
28
+ this.projectId = config.projectId;
29
+ this.modelId = config.modelId;
30
+ this.experimentId = config.experimentId;
31
+ this.onBlock = config.onBlock || "throw";
32
+ }
33
+ /**
34
+ * Call this on LLM end events.
35
+ * Accepts the prompt and response text, evaluates via DriftGard.
36
+ */
37
+ async evaluate(prompt, response, model) {
38
+ if (!prompt && !response)
39
+ return;
40
+ try {
41
+ const result = await this.client.evaluate({
42
+ project_id: this.projectId,
43
+ prompt,
44
+ response,
45
+ model_id: model || this.modelId || "unknown",
46
+ experiment_id: this.experimentId,
47
+ });
48
+ const evaluation = result.evaluation;
49
+ if (!evaluation?.allowed) {
50
+ const violations = evaluation?.violations || [];
51
+ const msg = `DriftGard blocked: risk_score=${evaluation?.risk_score ?? 0}, violations=${violations.length}`;
52
+ if (this.onBlock === "throw") {
53
+ throw new errors_1.DriftgardError(msg, 0, "blocked");
54
+ }
55
+ else if (this.onBlock === "log") {
56
+ console.warn(`[driftgard] ${msg} (evaluation_id=${result.evaluation_id})`);
57
+ }
58
+ }
59
+ }
60
+ catch (e) {
61
+ if (e instanceof errors_1.DriftgardError && this.onBlock === "throw")
62
+ throw e;
63
+ }
64
+ }
65
+ /**
66
+ * Convenience handler for LlamaIndex callback manager "llm-end" events.
67
+ */
68
+ async onLLMEnd(payload) {
69
+ await this.evaluate(payload.prompt || "", payload.response || "", payload.model);
70
+ }
71
+ }
72
+ exports.DriftgardLlamaIndexHandler = DriftgardLlamaIndexHandler;
package/dist/types.d.ts CHANGED
@@ -11,6 +11,12 @@ export interface EvaluateRequest {
11
11
  model_id: string;
12
12
  timestamp?: string;
13
13
  experiment_id?: string;
14
+ usage?: {
15
+ prompt_tokens?: number;
16
+ completion_tokens?: number;
17
+ total_tokens?: number;
18
+ cost?: number;
19
+ };
14
20
  }
15
21
  export interface Violation {
16
22
  clause_id?: string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@driftgard/node",
3
- "version": "1.2.0",
3
+ "version": "1.3.0",
4
4
  "description": "Official Driftgard Node.js SDK — evaluate LLM interactions against your compliance policy",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",