@veritera.ai/forge-openclaw 1.1.2

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/dist/index.cjs ADDED
@@ -0,0 +1,160 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+
30
+ // src/index.ts
31
+ var index_exports = {};
32
+ __export(index_exports, {
33
+ ForgeSkill: () => ForgeSkill,
34
+ default: () => index_default
35
+ });
36
+ module.exports = __toCommonJS(index_exports);
37
+ var import_sdk = __toESM(require("@veritera.ai/sdk"), 1);
38
+ var ForgeSkill = class {
39
+ forge;
40
+ policy;
41
+ agentId;
42
+ skipActions;
43
+ onBlocked;
44
+ onVerified;
45
+ debug;
46
+ /** Skill metadata for OpenClaw registration */
47
+ static skillName = "forge-verify";
48
+ static version = "1.1.2";
49
+ static description = "Forge verification \u2014 verifies every action before execution";
50
+ constructor(config) {
51
+ if (!config.apiKey) {
52
+ throw new Error("Forge OpenClaw Skill: apiKey is required");
53
+ }
54
+ this.forge = new import_sdk.default({
55
+ apiKey: config.apiKey,
56
+ baseUrl: config.baseUrl
57
+ });
58
+ this.policy = config.policy;
59
+ this.agentId = config.agentId ?? "openclaw-agent";
60
+ this.skipActions = new Set(config.skipActions ?? []);
61
+ this.onBlocked = config.onBlocked;
62
+ this.onVerified = config.onVerified;
63
+ this.debug = config.debug ?? false;
64
+ }
65
+ /**
66
+ * Verify a tool call before execution.
67
+ * Returns the verification result. If not verified, the action should be blocked.
68
+ *
69
+ * @param toolCall - The OpenClaw tool call to verify
70
+ * @returns SkillResult with verification status
71
+ */
72
+ async verify(toolCall) {
73
+ const action = toolCall.name;
74
+ if (this.skipActions.has(action)) {
75
+ if (this.debug) console.log(`[Forge] Skipping verification for: ${action}`);
76
+ return { verified: true, action };
77
+ }
78
+ try {
79
+ const result = await this.forge.verifyDecision({
80
+ agentId: this.agentId,
81
+ action,
82
+ params: toolCall.arguments ?? {},
83
+ policy: this.policy
84
+ });
85
+ if (this.debug) {
86
+ console.log(`[Forge] ${result.verified ? "\u2714 VERIFIED" : "\u2717 BLOCKED"}: ${action} (${result.latencyMs}ms)`);
87
+ }
88
+ if (result.verified) {
89
+ this.onVerified?.(action, result);
90
+ } else {
91
+ this.onBlocked?.(action, result.reason, result);
92
+ }
93
+ return {
94
+ verified: result.verified,
95
+ action,
96
+ verificationId: result.verificationId,
97
+ latencyMs: result.latencyMs,
98
+ reason: result.reason
99
+ };
100
+ } catch (err) {
101
+ if (this.debug) {
102
+ console.error(`[Forge] Verification failed for ${action}:`, err);
103
+ }
104
+ return {
105
+ verified: false,
106
+ action,
107
+ reason: "Verification service unreachable \u2014 action blocked (fail-closed)"
108
+ };
109
+ }
110
+ }
111
+ /**
112
+ * Pre-execution interceptor for OpenClaw.
113
+ * Register this as a skill hook to verify every action automatically.
114
+ *
115
+ * @param toolCall - The tool call from OpenClaw
116
+ * @returns The tool call if verified, null if blocked
117
+ */
118
+ async intercept(toolCall) {
119
+ const result = await this.verify(toolCall);
120
+ if (!result.verified) {
121
+ return null;
122
+ }
123
+ return toolCall;
124
+ }
125
+ /**
126
+ * Express/Connect-style middleware for custom integrations.
127
+ * Verifies the action in req.body and blocks if denied.
128
+ */
129
+ middleware() {
130
+ return async (req, res, next) => {
131
+ const toolCall = {
132
+ name: req.body?.action ?? req.body?.name ?? "unknown",
133
+ arguments: req.body?.params ?? req.body?.arguments ?? {}
134
+ };
135
+ const result = await this.verify(toolCall);
136
+ if (!result.verified) {
137
+ return res.status(403).json({
138
+ blocked: true,
139
+ action: toolCall.name,
140
+ reason: result.reason,
141
+ verificationId: result.verificationId
142
+ });
143
+ }
144
+ req.forgeVerification = result;
145
+ next();
146
+ };
147
+ }
148
+ /**
149
+ * Get the Forge client instance for direct API access.
150
+ */
151
+ getClient() {
152
+ return this.forge;
153
+ }
154
+ };
155
+ var index_default = ForgeSkill;
156
+ // Annotate the CommonJS export names for ESM import in node:
157
+ 0 && (module.exports = {
158
+ ForgeSkill
159
+ });
160
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts"],"sourcesContent":["/**\n * Forge OpenClaw Skill\n * ===================\n * Verification skill for OpenClaw agents.\n * Intercepts every tool call and verifies it through Forge before execution.\n *\n * Usage:\n * import { ForgeSkill } from \"@veritera.ai/forge-openclaw\"\n *\n * const skill = new ForgeSkill({ apiKey: \"vt_live_...\" })\n * agent.addSkill(skill)\n *\n * Every action your agent takes is now verified before execution.\n * Blocked actions never reach your tools.\n */\n\nimport Forge from \"@veritera.ai/sdk\";\nimport type { VeriteraConfig, VerifyResponse } from \"@veritera.ai/sdk\";\n\n// ── Types ──\n\nexport interface ForgeSkillConfig {\n /** Forge API key (vt_live_... or vt_test_...) */\n apiKey: string;\n /** Base URL for Forge API (default: https://veritera.ai) */\n baseUrl?: string;\n /** Policy name to evaluate against (optional) */\n policy?: string;\n /** Agent ID override (default: auto-detected from OpenClaw context) */\n agentId?: string;\n /** Actions to skip verification for (e.g., [\"read_file\", \"list_dir\"]) */\n skipActions?: string[];\n /** Called when an action is blocked */\n onBlocked?: (action: string, reason: string | null, result: VerifyResponse) => void;\n /** Called when an action is verified */\n onVerified?: (action: string, result: VerifyResponse) => void;\n /** Enable debug logging */\n debug?: boolean;\n}\n\nexport interface ToolCall {\n name: string;\n arguments?: Record<string, unknown>;\n [key: string]: unknown;\n}\n\nexport interface SkillResult {\n verified: boolean;\n action: string;\n verificationId?: string;\n latencyMs?: number;\n reason?: string | null;\n}\n\n// ── Forge OpenClaw Skill ──\n\nexport class ForgeSkill {\n private forge: InstanceType<typeof Forge>;\n private policy: string | undefined;\n private agentId: string;\n private skipActions: Set<string>;\n private onBlocked?: ForgeSkillConfig[\"onBlocked\"];\n private onVerified?: ForgeSkillConfig[\"onVerified\"];\n private debug: boolean;\n\n /** Skill metadata for OpenClaw registration */\n static readonly skillName = \"forge-verify\";\n static readonly version = \"1.1.2\";\n static readonly description = \"Forge verification — verifies every action before execution\";\n\n constructor(config: ForgeSkillConfig) {\n if (!config.apiKey) {\n throw new Error(\"Forge OpenClaw Skill: apiKey is required\");\n }\n\n this.forge = new Forge({\n apiKey: config.apiKey,\n baseUrl: config.baseUrl,\n });\n this.policy = config.policy;\n this.agentId = config.agentId ?? \"openclaw-agent\";\n this.skipActions = new Set(config.skipActions ?? []);\n this.onBlocked = config.onBlocked;\n this.onVerified = config.onVerified;\n this.debug = config.debug ?? false;\n }\n\n /**\n * Verify a tool call before execution.\n * Returns the verification result. If not verified, the action should be blocked.\n *\n * @param toolCall - The OpenClaw tool call to verify\n * @returns SkillResult with verification status\n */\n async verify(toolCall: ToolCall): Promise<SkillResult> {\n const action = toolCall.name;\n\n // Skip verification for whitelisted actions\n if (this.skipActions.has(action)) {\n if (this.debug) console.log(`[Forge] Skipping verification for: ${action}`);\n return { verified: true, action };\n }\n\n try {\n const result = await this.forge.verifyDecision({\n agentId: this.agentId,\n action,\n params: (toolCall.arguments ?? {}) as Record<string, unknown>,\n policy: this.policy,\n });\n\n if (this.debug) {\n console.log(`[Forge] ${result.verified ? \"✔ VERIFIED\" : \"✗ BLOCKED\"}: ${action} (${result.latencyMs}ms)`);\n }\n\n if (result.verified) {\n this.onVerified?.(action, result);\n } else {\n this.onBlocked?.(action, result.reason, result);\n }\n\n return {\n verified: result.verified,\n action,\n verificationId: result.verificationId,\n latencyMs: result.latencyMs,\n reason: result.reason,\n };\n } catch (err) {\n // Fail-closed: if verification service is unreachable, block the action\n if (this.debug) {\n console.error(`[Forge] Verification failed for ${action}:`, err);\n }\n return {\n verified: false,\n action,\n reason: \"Verification service unreachable — action blocked (fail-closed)\",\n };\n }\n }\n\n /**\n * Pre-execution interceptor for OpenClaw.\n * Register this as a skill hook to verify every action automatically.\n *\n * @param toolCall - The tool call from OpenClaw\n * @returns The tool call if verified, null if blocked\n */\n async intercept(toolCall: ToolCall): Promise<ToolCall | null> {\n const result = await this.verify(toolCall);\n if (!result.verified) {\n return null; // Blocked — OpenClaw will not execute this tool call\n }\n return toolCall; // Verified — proceed with execution\n }\n\n /**\n * Express/Connect-style middleware for custom integrations.\n * Verifies the action in req.body and blocks if denied.\n */\n middleware() {\n return async (req: any, res: any, next: any) => {\n const toolCall: ToolCall = {\n name: req.body?.action ?? req.body?.name ?? \"unknown\",\n arguments: req.body?.params ?? req.body?.arguments ?? {},\n };\n\n const result = await this.verify(toolCall);\n\n if (!result.verified) {\n return res.status(403).json({\n blocked: true,\n action: toolCall.name,\n reason: result.reason,\n verificationId: result.verificationId,\n });\n }\n\n // Attach verification result to request for downstream use\n req.forgeVerification = result;\n next();\n };\n }\n\n /**\n * Get the Forge client instance for direct API access.\n */\n getClient(): InstanceType<typeof Forge> {\n return this.forge;\n }\n}\n\n// Default export for convenience\nexport default ForgeSkill;\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAgBA,iBAAkB;AAwCX,IAAM,aAAN,MAAiB;AAAA,EACd;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA;AAAA,EAGR,OAAgB,YAAY;AAAA,EAC5B,OAAgB,UAAU;AAAA,EAC1B,OAAgB,cAAc;AAAA,EAE9B,YAAY,QAA0B;AACpC,QAAI,CAAC,OAAO,QAAQ;AAClB,YAAM,IAAI,MAAM,0CAA0C;AAAA,IAC5D;AAEA,SAAK,QAAQ,IAAI,WAAAA,QAAM;AAAA,MACrB,QAAQ,OAAO;AAAA,MACf,SAAS,OAAO;AAAA,IAClB,CAAC;AACD,SAAK,SAAS,OAAO;AACrB,SAAK,UAAU,OAAO,WAAW;AACjC,SAAK,cAAc,IAAI,IAAI,OAAO,eAAe,CAAC,CAAC;AACnD,SAAK,YAAY,OAAO;AACxB,SAAK,aAAa,OAAO;AACzB,SAAK,QAAQ,OAAO,SAAS;AAAA,EAC/B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,OAAO,UAA0C;AACrD,UAAM,SAAS,SAAS;AAGxB,QAAI,KAAK,YAAY,IAAI,MAAM,GAAG;AAChC,UAAI,KAAK,MAAO,SAAQ,IAAI,sCAAsC,MAAM,EAAE;AAC1E,aAAO,EAAE,UAAU,MAAM,OAAO;AAAA,IAClC;AAEA,QAAI;AACF,YAAM,SAAS,MAAM,KAAK,MAAM,eAAe;AAAA,QAC7C,SAAS,KAAK;AAAA,QACd;AAAA,QACA,QAAS,SAAS,aAAa,CAAC;AAAA,QAChC,QAAQ,KAAK;AAAA,MACf,CAAC;AAED,UAAI,KAAK,OAAO;AACd,gBAAQ,IAAI,WAAW,OAAO,WAAW,oBAAe,gBAAW,KAAK,MAAM,KAAK,OAAO,SAAS,KAAK;AAAA,MAC1G;AAEA,UAAI,OAAO,UAAU;AACnB,aAAK,aAAa,QAAQ,MAAM;AAAA,MAClC,OAAO;AACL,aAAK,YAAY,QAAQ,OAAO,QAAQ,MAAM;AAAA,MAChD;AAEA,aAAO;AAAA,QACL,UAAU,OAAO;AAAA,QACjB;AAAA,QACA,gBAAgB,OAAO;AAAA,QACvB,WAAW,OAAO;AAAA,QAClB,QAAQ,OAAO;AAAA,MACjB;AAAA,IACF,SAAS,KAAK;AAEZ,UAAI,KAAK,OAAO;AACd,gBAAQ,MAAM,mCAAmC,MAAM,KAAK,GAAG;AAAA,MACjE;AACA,aAAO;AAAA,QACL,UAAU;AAAA,QACV;AAAA,QACA,QAAQ;AAAA,MACV;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,UAAU,UAA8C;AAC5D,UAAM,SAAS,MAAM,KAAK,OAAO,QAAQ;AACzC,QAAI,CAAC,OAAO,UAAU;AACpB,aAAO;AAAA,IACT;AACA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,aAAa;AACX,WAAO,OAAO,KAAU,KAAU,SAAc;AAC9C,YAAM,WAAqB;AAAA,QACzB,MAAM,IAAI,MAAM,UAAU,IAAI,MAAM,QAAQ;AAAA,QAC5C,WAAW,IAAI,MAAM,UAAU,IAAI,MAAM,aAAa,CAAC;AAAA,MACzD;AAEA,YAAM,SAAS,MAAM,KAAK,OAAO,QAAQ;AAEzC,UAAI,CAAC,OAAO,UAAU;AACpB,eAAO,IAAI,OAAO,GAAG,EAAE,KAAK;AAAA,UAC1B,SAAS;AAAA,UACT,QAAQ,SAAS;AAAA,UACjB,QAAQ,OAAO;AAAA,UACf,gBAAgB,OAAO;AAAA,QACzB,CAAC;AAAA,MACH;AAGA,UAAI,oBAAoB;AACxB,WAAK;AAAA,IACP;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,YAAwC;AACtC,WAAO,KAAK;AAAA,EACd;AACF;AAGA,IAAO,gBAAQ;","names":["Forge"]}
@@ -0,0 +1,89 @@
1
+ import Forge, { VerifyResponse } from '@veritera.ai/sdk';
2
+
3
+ /**
4
+ * Forge OpenClaw Skill
5
+ * ===================
6
+ * Verification skill for OpenClaw agents.
7
+ * Intercepts every tool call and verifies it through Forge before execution.
8
+ *
9
+ * Usage:
10
+ * import { ForgeSkill } from "@veritera.ai/forge-openclaw"
11
+ *
12
+ * const skill = new ForgeSkill({ apiKey: "vt_live_..." })
13
+ * agent.addSkill(skill)
14
+ *
15
+ * Every action your agent takes is now verified before execution.
16
+ * Blocked actions never reach your tools.
17
+ */
18
+
19
+ interface ForgeSkillConfig {
20
+ /** Forge API key (vt_live_... or vt_test_...) */
21
+ apiKey: string;
22
+ /** Base URL for Forge API (default: https://veritera.ai) */
23
+ baseUrl?: string;
24
+ /** Policy name to evaluate against (optional) */
25
+ policy?: string;
26
+ /** Agent ID override (default: auto-detected from OpenClaw context) */
27
+ agentId?: string;
28
+ /** Actions to skip verification for (e.g., ["read_file", "list_dir"]) */
29
+ skipActions?: string[];
30
+ /** Called when an action is blocked */
31
+ onBlocked?: (action: string, reason: string | null, result: VerifyResponse) => void;
32
+ /** Called when an action is verified */
33
+ onVerified?: (action: string, result: VerifyResponse) => void;
34
+ /** Enable debug logging */
35
+ debug?: boolean;
36
+ }
37
+ interface ToolCall {
38
+ name: string;
39
+ arguments?: Record<string, unknown>;
40
+ [key: string]: unknown;
41
+ }
42
+ interface SkillResult {
43
+ verified: boolean;
44
+ action: string;
45
+ verificationId?: string;
46
+ latencyMs?: number;
47
+ reason?: string | null;
48
+ }
49
+ declare class ForgeSkill {
50
+ private forge;
51
+ private policy;
52
+ private agentId;
53
+ private skipActions;
54
+ private onBlocked?;
55
+ private onVerified?;
56
+ private debug;
57
+ /** Skill metadata for OpenClaw registration */
58
+ static readonly skillName = "forge-verify";
59
+ static readonly version = "1.1.2";
60
+ static readonly description = "Forge verification \u2014 verifies every action before execution";
61
+ constructor(config: ForgeSkillConfig);
62
+ /**
63
+ * Verify a tool call before execution.
64
+ * Returns the verification result. If not verified, the action should be blocked.
65
+ *
66
+ * @param toolCall - The OpenClaw tool call to verify
67
+ * @returns SkillResult with verification status
68
+ */
69
+ verify(toolCall: ToolCall): Promise<SkillResult>;
70
+ /**
71
+ * Pre-execution interceptor for OpenClaw.
72
+ * Register this as a skill hook to verify every action automatically.
73
+ *
74
+ * @param toolCall - The tool call from OpenClaw
75
+ * @returns The tool call if verified, null if blocked
76
+ */
77
+ intercept(toolCall: ToolCall): Promise<ToolCall | null>;
78
+ /**
79
+ * Express/Connect-style middleware for custom integrations.
80
+ * Verifies the action in req.body and blocks if denied.
81
+ */
82
+ middleware(): (req: any, res: any, next: any) => Promise<any>;
83
+ /**
84
+ * Get the Forge client instance for direct API access.
85
+ */
86
+ getClient(): InstanceType<typeof Forge>;
87
+ }
88
+
89
+ export { ForgeSkill, type ForgeSkillConfig, type SkillResult, type ToolCall, ForgeSkill as default };
@@ -0,0 +1,89 @@
1
+ import Forge, { VerifyResponse } from '@veritera.ai/sdk';
2
+
3
+ /**
4
+ * Forge OpenClaw Skill
5
+ * ===================
6
+ * Verification skill for OpenClaw agents.
7
+ * Intercepts every tool call and verifies it through Forge before execution.
8
+ *
9
+ * Usage:
10
+ * import { ForgeSkill } from "@veritera.ai/forge-openclaw"
11
+ *
12
+ * const skill = new ForgeSkill({ apiKey: "vt_live_..." })
13
+ * agent.addSkill(skill)
14
+ *
15
+ * Every action your agent takes is now verified before execution.
16
+ * Blocked actions never reach your tools.
17
+ */
18
+
19
+ interface ForgeSkillConfig {
20
+ /** Forge API key (vt_live_... or vt_test_...) */
21
+ apiKey: string;
22
+ /** Base URL for Forge API (default: https://veritera.ai) */
23
+ baseUrl?: string;
24
+ /** Policy name to evaluate against (optional) */
25
+ policy?: string;
26
+ /** Agent ID override (default: auto-detected from OpenClaw context) */
27
+ agentId?: string;
28
+ /** Actions to skip verification for (e.g., ["read_file", "list_dir"]) */
29
+ skipActions?: string[];
30
+ /** Called when an action is blocked */
31
+ onBlocked?: (action: string, reason: string | null, result: VerifyResponse) => void;
32
+ /** Called when an action is verified */
33
+ onVerified?: (action: string, result: VerifyResponse) => void;
34
+ /** Enable debug logging */
35
+ debug?: boolean;
36
+ }
37
+ interface ToolCall {
38
+ name: string;
39
+ arguments?: Record<string, unknown>;
40
+ [key: string]: unknown;
41
+ }
42
+ interface SkillResult {
43
+ verified: boolean;
44
+ action: string;
45
+ verificationId?: string;
46
+ latencyMs?: number;
47
+ reason?: string | null;
48
+ }
49
+ declare class ForgeSkill {
50
+ private forge;
51
+ private policy;
52
+ private agentId;
53
+ private skipActions;
54
+ private onBlocked?;
55
+ private onVerified?;
56
+ private debug;
57
+ /** Skill metadata for OpenClaw registration */
58
+ static readonly skillName = "forge-verify";
59
+ static readonly version = "1.1.2";
60
+ static readonly description = "Forge verification \u2014 verifies every action before execution";
61
+ constructor(config: ForgeSkillConfig);
62
+ /**
63
+ * Verify a tool call before execution.
64
+ * Returns the verification result. If not verified, the action should be blocked.
65
+ *
66
+ * @param toolCall - The OpenClaw tool call to verify
67
+ * @returns SkillResult with verification status
68
+ */
69
+ verify(toolCall: ToolCall): Promise<SkillResult>;
70
+ /**
71
+ * Pre-execution interceptor for OpenClaw.
72
+ * Register this as a skill hook to verify every action automatically.
73
+ *
74
+ * @param toolCall - The tool call from OpenClaw
75
+ * @returns The tool call if verified, null if blocked
76
+ */
77
+ intercept(toolCall: ToolCall): Promise<ToolCall | null>;
78
+ /**
79
+ * Express/Connect-style middleware for custom integrations.
80
+ * Verifies the action in req.body and blocks if denied.
81
+ */
82
+ middleware(): (req: any, res: any, next: any) => Promise<any>;
83
+ /**
84
+ * Get the Forge client instance for direct API access.
85
+ */
86
+ getClient(): InstanceType<typeof Forge>;
87
+ }
88
+
89
+ export { ForgeSkill, type ForgeSkillConfig, type SkillResult, type ToolCall, ForgeSkill as default };
package/dist/index.js ADDED
@@ -0,0 +1,125 @@
1
+ // src/index.ts
2
+ import Forge from "@veritera.ai/sdk";
3
+ var ForgeSkill = class {
4
+ forge;
5
+ policy;
6
+ agentId;
7
+ skipActions;
8
+ onBlocked;
9
+ onVerified;
10
+ debug;
11
+ /** Skill metadata for OpenClaw registration */
12
+ static skillName = "forge-verify";
13
+ static version = "1.1.2";
14
+ static description = "Forge verification \u2014 verifies every action before execution";
15
+ constructor(config) {
16
+ if (!config.apiKey) {
17
+ throw new Error("Forge OpenClaw Skill: apiKey is required");
18
+ }
19
+ this.forge = new Forge({
20
+ apiKey: config.apiKey,
21
+ baseUrl: config.baseUrl
22
+ });
23
+ this.policy = config.policy;
24
+ this.agentId = config.agentId ?? "openclaw-agent";
25
+ this.skipActions = new Set(config.skipActions ?? []);
26
+ this.onBlocked = config.onBlocked;
27
+ this.onVerified = config.onVerified;
28
+ this.debug = config.debug ?? false;
29
+ }
30
+ /**
31
+ * Verify a tool call before execution.
32
+ * Returns the verification result. If not verified, the action should be blocked.
33
+ *
34
+ * @param toolCall - The OpenClaw tool call to verify
35
+ * @returns SkillResult with verification status
36
+ */
37
+ async verify(toolCall) {
38
+ const action = toolCall.name;
39
+ if (this.skipActions.has(action)) {
40
+ if (this.debug) console.log(`[Forge] Skipping verification for: ${action}`);
41
+ return { verified: true, action };
42
+ }
43
+ try {
44
+ const result = await this.forge.verifyDecision({
45
+ agentId: this.agentId,
46
+ action,
47
+ params: toolCall.arguments ?? {},
48
+ policy: this.policy
49
+ });
50
+ if (this.debug) {
51
+ console.log(`[Forge] ${result.verified ? "\u2714 VERIFIED" : "\u2717 BLOCKED"}: ${action} (${result.latencyMs}ms)`);
52
+ }
53
+ if (result.verified) {
54
+ this.onVerified?.(action, result);
55
+ } else {
56
+ this.onBlocked?.(action, result.reason, result);
57
+ }
58
+ return {
59
+ verified: result.verified,
60
+ action,
61
+ verificationId: result.verificationId,
62
+ latencyMs: result.latencyMs,
63
+ reason: result.reason
64
+ };
65
+ } catch (err) {
66
+ if (this.debug) {
67
+ console.error(`[Forge] Verification failed for ${action}:`, err);
68
+ }
69
+ return {
70
+ verified: false,
71
+ action,
72
+ reason: "Verification service unreachable \u2014 action blocked (fail-closed)"
73
+ };
74
+ }
75
+ }
76
+ /**
77
+ * Pre-execution interceptor for OpenClaw.
78
+ * Register this as a skill hook to verify every action automatically.
79
+ *
80
+ * @param toolCall - The tool call from OpenClaw
81
+ * @returns The tool call if verified, null if blocked
82
+ */
83
+ async intercept(toolCall) {
84
+ const result = await this.verify(toolCall);
85
+ if (!result.verified) {
86
+ return null;
87
+ }
88
+ return toolCall;
89
+ }
90
+ /**
91
+ * Express/Connect-style middleware for custom integrations.
92
+ * Verifies the action in req.body and blocks if denied.
93
+ */
94
+ middleware() {
95
+ return async (req, res, next) => {
96
+ const toolCall = {
97
+ name: req.body?.action ?? req.body?.name ?? "unknown",
98
+ arguments: req.body?.params ?? req.body?.arguments ?? {}
99
+ };
100
+ const result = await this.verify(toolCall);
101
+ if (!result.verified) {
102
+ return res.status(403).json({
103
+ blocked: true,
104
+ action: toolCall.name,
105
+ reason: result.reason,
106
+ verificationId: result.verificationId
107
+ });
108
+ }
109
+ req.forgeVerification = result;
110
+ next();
111
+ };
112
+ }
113
+ /**
114
+ * Get the Forge client instance for direct API access.
115
+ */
116
+ getClient() {
117
+ return this.forge;
118
+ }
119
+ };
120
+ var index_default = ForgeSkill;
121
+ export {
122
+ ForgeSkill,
123
+ index_default as default
124
+ };
125
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts"],"sourcesContent":["/**\n * Forge OpenClaw Skill\n * ===================\n * Verification skill for OpenClaw agents.\n * Intercepts every tool call and verifies it through Forge before execution.\n *\n * Usage:\n * import { ForgeSkill } from \"@veritera.ai/forge-openclaw\"\n *\n * const skill = new ForgeSkill({ apiKey: \"vt_live_...\" })\n * agent.addSkill(skill)\n *\n * Every action your agent takes is now verified before execution.\n * Blocked actions never reach your tools.\n */\n\nimport Forge from \"@veritera.ai/sdk\";\nimport type { VeriteraConfig, VerifyResponse } from \"@veritera.ai/sdk\";\n\n// ── Types ──\n\nexport interface ForgeSkillConfig {\n /** Forge API key (vt_live_... or vt_test_...) */\n apiKey: string;\n /** Base URL for Forge API (default: https://veritera.ai) */\n baseUrl?: string;\n /** Policy name to evaluate against (optional) */\n policy?: string;\n /** Agent ID override (default: auto-detected from OpenClaw context) */\n agentId?: string;\n /** Actions to skip verification for (e.g., [\"read_file\", \"list_dir\"]) */\n skipActions?: string[];\n /** Called when an action is blocked */\n onBlocked?: (action: string, reason: string | null, result: VerifyResponse) => void;\n /** Called when an action is verified */\n onVerified?: (action: string, result: VerifyResponse) => void;\n /** Enable debug logging */\n debug?: boolean;\n}\n\nexport interface ToolCall {\n name: string;\n arguments?: Record<string, unknown>;\n [key: string]: unknown;\n}\n\nexport interface SkillResult {\n verified: boolean;\n action: string;\n verificationId?: string;\n latencyMs?: number;\n reason?: string | null;\n}\n\n// ── Forge OpenClaw Skill ──\n\nexport class ForgeSkill {\n private forge: InstanceType<typeof Forge>;\n private policy: string | undefined;\n private agentId: string;\n private skipActions: Set<string>;\n private onBlocked?: ForgeSkillConfig[\"onBlocked\"];\n private onVerified?: ForgeSkillConfig[\"onVerified\"];\n private debug: boolean;\n\n /** Skill metadata for OpenClaw registration */\n static readonly skillName = \"forge-verify\";\n static readonly version = \"1.1.2\";\n static readonly description = \"Forge verification — verifies every action before execution\";\n\n constructor(config: ForgeSkillConfig) {\n if (!config.apiKey) {\n throw new Error(\"Forge OpenClaw Skill: apiKey is required\");\n }\n\n this.forge = new Forge({\n apiKey: config.apiKey,\n baseUrl: config.baseUrl,\n });\n this.policy = config.policy;\n this.agentId = config.agentId ?? \"openclaw-agent\";\n this.skipActions = new Set(config.skipActions ?? []);\n this.onBlocked = config.onBlocked;\n this.onVerified = config.onVerified;\n this.debug = config.debug ?? false;\n }\n\n /**\n * Verify a tool call before execution.\n * Returns the verification result. If not verified, the action should be blocked.\n *\n * @param toolCall - The OpenClaw tool call to verify\n * @returns SkillResult with verification status\n */\n async verify(toolCall: ToolCall): Promise<SkillResult> {\n const action = toolCall.name;\n\n // Skip verification for whitelisted actions\n if (this.skipActions.has(action)) {\n if (this.debug) console.log(`[Forge] Skipping verification for: ${action}`);\n return { verified: true, action };\n }\n\n try {\n const result = await this.forge.verifyDecision({\n agentId: this.agentId,\n action,\n params: (toolCall.arguments ?? {}) as Record<string, unknown>,\n policy: this.policy,\n });\n\n if (this.debug) {\n console.log(`[Forge] ${result.verified ? \"✔ VERIFIED\" : \"✗ BLOCKED\"}: ${action} (${result.latencyMs}ms)`);\n }\n\n if (result.verified) {\n this.onVerified?.(action, result);\n } else {\n this.onBlocked?.(action, result.reason, result);\n }\n\n return {\n verified: result.verified,\n action,\n verificationId: result.verificationId,\n latencyMs: result.latencyMs,\n reason: result.reason,\n };\n } catch (err) {\n // Fail-closed: if verification service is unreachable, block the action\n if (this.debug) {\n console.error(`[Forge] Verification failed for ${action}:`, err);\n }\n return {\n verified: false,\n action,\n reason: \"Verification service unreachable — action blocked (fail-closed)\",\n };\n }\n }\n\n /**\n * Pre-execution interceptor for OpenClaw.\n * Register this as a skill hook to verify every action automatically.\n *\n * @param toolCall - The tool call from OpenClaw\n * @returns The tool call if verified, null if blocked\n */\n async intercept(toolCall: ToolCall): Promise<ToolCall | null> {\n const result = await this.verify(toolCall);\n if (!result.verified) {\n return null; // Blocked — OpenClaw will not execute this tool call\n }\n return toolCall; // Verified — proceed with execution\n }\n\n /**\n * Express/Connect-style middleware for custom integrations.\n * Verifies the action in req.body and blocks if denied.\n */\n middleware() {\n return async (req: any, res: any, next: any) => {\n const toolCall: ToolCall = {\n name: req.body?.action ?? req.body?.name ?? \"unknown\",\n arguments: req.body?.params ?? req.body?.arguments ?? {},\n };\n\n const result = await this.verify(toolCall);\n\n if (!result.verified) {\n return res.status(403).json({\n blocked: true,\n action: toolCall.name,\n reason: result.reason,\n verificationId: result.verificationId,\n });\n }\n\n // Attach verification result to request for downstream use\n req.forgeVerification = result;\n next();\n };\n }\n\n /**\n * Get the Forge client instance for direct API access.\n */\n getClient(): InstanceType<typeof Forge> {\n return this.forge;\n }\n}\n\n// Default export for convenience\nexport default ForgeSkill;\n"],"mappings":"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","names":[]}
package/package.json ADDED
@@ -0,0 +1,31 @@
1
+ {
2
+ "name": "@veritera.ai/forge-openclaw",
3
+ "version": "1.1.2",
4
+ "description": "Forge verification skill for OpenClaw agents — verify every action before execution",
5
+ "type": "module",
6
+ "main": "./dist/index.cjs",
7
+ "module": "./dist/index.js",
8
+ "types": "./dist/index.d.ts",
9
+ "exports": {
10
+ ".": {
11
+ "import": "./dist/index.js",
12
+ "require": "./dist/index.cjs",
13
+ "types": "./dist/index.d.ts"
14
+ }
15
+ },
16
+ "files": ["dist"],
17
+ "scripts": {
18
+ "build": "tsup",
19
+ "test": "vitest run"
20
+ },
21
+ "keywords": ["forge", "veritera", "openclaw", "ai", "verification", "agent", "skill"],
22
+ "author": "Veritera AI <engineering@veritera.ai>",
23
+ "license": "MIT",
24
+ "dependencies": {
25
+ "@veritera.ai/sdk": "^1.1.2"
26
+ },
27
+ "devDependencies": {
28
+ "tsup": "^8.0.0",
29
+ "typescript": "^5.0.0"
30
+ }
31
+ }