moltblock 0.4.0 → 0.6.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 → README.md} +96 -1
- package/dist/agents.d.ts +4 -4
- package/dist/agents.js +30 -16
- package/dist/cli.js +6 -1
- package/dist/code-verifier.d.ts +13 -0
- package/dist/code-verifier.js +21 -0
- package/dist/composite-verifier.d.ts +21 -0
- package/dist/composite-verifier.js +42 -0
- package/dist/config.d.ts +57 -2
- package/dist/config.js +121 -46
- package/dist/domain-prompts.d.ts +21 -0
- package/dist/domain-prompts.js +33 -0
- package/dist/entity-base.d.ts +37 -0
- package/dist/entity-base.js +87 -0
- package/dist/graph-runner.d.ts +11 -1
- package/dist/graph-runner.js +15 -4
- package/dist/improvement.d.ts +1 -1
- package/dist/improvement.js +21 -9
- package/dist/index.d.ts +10 -3
- package/dist/index.js +16 -4
- package/dist/policy-verifier.d.ts +29 -0
- package/dist/policy-verifier.js +90 -0
- package/dist/risk.d.ts +13 -0
- package/dist/risk.js +63 -0
- package/dist/verifier-interface.d.ts +24 -0
- package/dist/verifier-interface.js +4 -0
- package/package.json +3 -2
- package/skill/SKILL.md +103 -0
package/{readme.md → README.md}
RENAMED
|
@@ -67,7 +67,7 @@ Blockchain is optional and used only for anchoring.
|
|
|
67
67
|
|
|
68
68
|
## Run (Code Entity MVP)
|
|
69
69
|
|
|
70
|
-
Requires Node.js
|
|
70
|
+
Requires Node.js 22+, and (for full loop) any OpenAI-compatible API:
|
|
71
71
|
- **OpenAI** — `https://api.openai.com/v1` with `OPENAI_API_KEY`
|
|
72
72
|
- **Anthropic Claude** — `https://api.anthropic.com/v1` with `ANTHROPIC_API_KEY`
|
|
73
73
|
- **Google Gemini** — `https://generativelanguage.googleapis.com/v1beta/openai` with `GOOGLE_API_KEY`
|
|
@@ -105,6 +105,19 @@ npx moltblock "Implement add(a, b)."
|
|
|
105
105
|
|
|
106
106
|
## Configuration
|
|
107
107
|
|
|
108
|
+
### Zero-config (auto-detect)
|
|
109
|
+
|
|
110
|
+
If you have an API key set in your environment, moltblock detects the provider automatically — no config file needed:
|
|
111
|
+
|
|
112
|
+
```bash
|
|
113
|
+
export OPENAI_API_KEY="sk-..." # auto-detects OpenAI
|
|
114
|
+
npx moltblock "Implement add(a, b)." --json
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
Override with CLI flags: `--provider google --model gemini-2.0-flash` or `-p zai -m glm-4.7`.
|
|
118
|
+
|
|
119
|
+
Detection priority: `OPENAI_API_KEY` > `GOOGLE_API_KEY` > `MOLTBLOCK_ZAI_API_KEY` > localhost.
|
|
120
|
+
|
|
108
121
|
### Quick setup
|
|
109
122
|
|
|
110
123
|
Create a config file at `~/.moltblock/moltblock.json` (user-wide) or `./moltblock.json` (project-specific):
|
|
@@ -195,6 +208,87 @@ npm test
|
|
|
195
208
|
- **Molt and governance** — `GovernanceConfig` (rate limit, veto); `canMolt()`, `triggerMolt()`, `pause()`, `resume()`, `emergencyShutdown()`; audit log and governance state in `Store`.
|
|
196
209
|
- **Multi-entity handoff** — `signArtifact()` / `verifyArtifact()`; inbox per entity; `sendArtifact()`, `receiveArtifacts()` for Entity A → Entity B.
|
|
197
210
|
|
|
211
|
+
### New in v0.6
|
|
212
|
+
|
|
213
|
+
- **Pluggable verifier system** — `Verifier` interface so verification isn't limited to vitest. Implement `verify(memory, context)` to plug in any gating strategy.
|
|
214
|
+
- **PolicyVerifier** — Rule-based verifier with ~20 built-in deny rules. Catches destructive commands (`rm -rf`, `DROP TABLE`), sensitive file access (`.ssh/`, `/etc/shadow`), hardcoded secrets, and exfiltration patterns — all without an LLM call.
|
|
215
|
+
- **CodeVerifier** — Adapter wrapping the existing vitest verifier into the pluggable interface.
|
|
216
|
+
- **CompositeVerifier** — Chains multiple verifiers (e.g. policy + code); all must pass. Supports fail-fast and collect-all modes.
|
|
217
|
+
- **Generic Entity** — `Entity` class with pluggable verifier and domain-aware prompts. Use `new Entity({ domain: "general" })` for non-code tasks.
|
|
218
|
+
- **Domain prompts** — Registry mapping domains to role-specific system prompts. Built-in `"code"` and `"general"` domains; register custom domains with `registerDomain()`.
|
|
219
|
+
- **Risk classification** — `classifyRisk(task)` returns `"low"` / `"medium"` / `"high"` with reasons. Pure regex matching, no LLM needed.
|
|
220
|
+
- **Policy rules in config** — Add custom `policy.rules` to `moltblock.json` for project-specific allow/deny rules.
|
|
221
|
+
- **OpenClaw skill** — `skill/SKILL.md` for one-step installation into OpenClaw workspace.
|
|
222
|
+
|
|
223
|
+
---
|
|
224
|
+
|
|
225
|
+
## Policy Verifier
|
|
226
|
+
|
|
227
|
+
The `PolicyVerifier` catches dangerous patterns in artifacts and tasks without needing an LLM:
|
|
228
|
+
|
|
229
|
+
```typescript
|
|
230
|
+
import { PolicyVerifier, WorkingMemory } from "moltblock";
|
|
231
|
+
|
|
232
|
+
const verifier = new PolicyVerifier();
|
|
233
|
+
const memory = new WorkingMemory();
|
|
234
|
+
memory.setFinalCandidate("rm -rf /");
|
|
235
|
+
|
|
236
|
+
const result = await verifier.verify(memory);
|
|
237
|
+
// result.passed === false
|
|
238
|
+
// result.evidence includes "[cmd-rm-rf] Recursive force delete"
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
Custom rules can be added via constructor or config:
|
|
242
|
+
|
|
243
|
+
```typescript
|
|
244
|
+
const verifier = new PolicyVerifier([
|
|
245
|
+
{
|
|
246
|
+
id: "allow-tmp-cleanup",
|
|
247
|
+
description: "Allow cleanup in /tmp",
|
|
248
|
+
target: "artifact",
|
|
249
|
+
pattern: "\\/tmp\\/",
|
|
250
|
+
action: "allow",
|
|
251
|
+
category: "destructive-cmd",
|
|
252
|
+
enabled: true,
|
|
253
|
+
},
|
|
254
|
+
]);
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
---
|
|
258
|
+
|
|
259
|
+
## Risk Classification
|
|
260
|
+
|
|
261
|
+
Classify task risk before deciding whether to verify:
|
|
262
|
+
|
|
263
|
+
```typescript
|
|
264
|
+
import { classifyRisk } from "moltblock";
|
|
265
|
+
|
|
266
|
+
classifyRisk("write a hello world function");
|
|
267
|
+
// { level: "low", reasons: [] }
|
|
268
|
+
|
|
269
|
+
classifyRisk("sudo rm -rf /home/user");
|
|
270
|
+
// { level: "high", reasons: ["Sudo privilege escalation", "Recursive file deletion (rm -rf)"] }
|
|
271
|
+
```
|
|
272
|
+
|
|
273
|
+
---
|
|
274
|
+
|
|
275
|
+
## Generic Entity
|
|
276
|
+
|
|
277
|
+
For non-code tasks, use the generic `Entity` with domain-aware prompts:
|
|
278
|
+
|
|
279
|
+
```typescript
|
|
280
|
+
import { Entity, PolicyVerifier, CompositeVerifier, CodeVerifier } from "moltblock";
|
|
281
|
+
|
|
282
|
+
// General-purpose entity (policy verification only)
|
|
283
|
+
const entity = new Entity({ domain: "general" });
|
|
284
|
+
|
|
285
|
+
// Code entity with both policy and vitest verification
|
|
286
|
+
const codeEntity = new Entity({
|
|
287
|
+
domain: "code",
|
|
288
|
+
verifier: new CompositeVerifier([new PolicyVerifier(), new CodeVerifier()]),
|
|
289
|
+
});
|
|
290
|
+
```
|
|
291
|
+
|
|
198
292
|
---
|
|
199
293
|
|
|
200
294
|
## Roadmap
|
|
@@ -202,6 +296,7 @@ npm test
|
|
|
202
296
|
- v0.1 — Protocol + architecture
|
|
203
297
|
- v0.2 — MVP Entity implementation (spec + Code Entity loop + graph, memory, improvement, governance, handoff)
|
|
204
298
|
- v0.3 — Multi-Entity collaboration (orchestration and tooling)
|
|
299
|
+
- v0.6 — Pluggable verification, policy rules, generic entity, risk classification, OpenClaw skill
|
|
205
300
|
|
|
206
301
|
---
|
|
207
302
|
|
package/dist/agents.d.ts
CHANGED
|
@@ -7,17 +7,17 @@ import { Store } from "./persistence.js";
|
|
|
7
7
|
/**
|
|
8
8
|
* Generator: task -> draft artifact (code).
|
|
9
9
|
*/
|
|
10
|
-
export declare function runGenerator(gateway: LLMGateway, memory: WorkingMemory, store?: Store | null): Promise<void>;
|
|
10
|
+
export declare function runGenerator(gateway: LLMGateway, memory: WorkingMemory, store?: Store | null, domain?: string): Promise<void>;
|
|
11
11
|
/**
|
|
12
12
|
* Critic: draft + task -> critique.
|
|
13
13
|
*/
|
|
14
|
-
export declare function runCritic(gateway: LLMGateway, memory: WorkingMemory, store?: Store | null): Promise<void>;
|
|
14
|
+
export declare function runCritic(gateway: LLMGateway, memory: WorkingMemory, store?: Store | null, domain?: string): Promise<void>;
|
|
15
15
|
/**
|
|
16
16
|
* Judge: task + draft + critique -> final candidate artifact.
|
|
17
17
|
*/
|
|
18
|
-
export declare function runJudge(gateway: LLMGateway, memory: WorkingMemory, store?: Store | null): Promise<void>;
|
|
18
|
+
export declare function runJudge(gateway: LLMGateway, memory: WorkingMemory, store?: Store | null, domain?: string): Promise<void>;
|
|
19
19
|
/**
|
|
20
20
|
* Run a single role with task and inputs (node_id -> content from predecessors).
|
|
21
21
|
* Returns the role's output string. Used by the graph runner.
|
|
22
22
|
*/
|
|
23
|
-
export declare function runRole(role: string, gateway: LLMGateway, task: string, inputs: Record<string, string>, longTermContext?: string, store?: Store | null): Promise<string>;
|
|
23
|
+
export declare function runRole(role: string, gateway: LLMGateway, task: string, inputs: Record<string, string>, longTermContext?: string, store?: Store | null, domain?: string): Promise<string>;
|
package/dist/agents.js
CHANGED
|
@@ -1,35 +1,49 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Agents: Generator, Critic, Judge. Each uses LLMGateway and reads/writes WorkingMemory.
|
|
3
3
|
*/
|
|
4
|
+
import { getDomainPrompts } from "./domain-prompts.js";
|
|
4
5
|
import { getStrategy } from "./persistence.js";
|
|
5
6
|
// Default prompts; can be overridden by strategy store (recursive improvement)
|
|
6
7
|
// Note: Prompts updated to produce TypeScript instead of Python
|
|
7
8
|
const CODE_GENERATOR_SYSTEM = `You are the Generator for a Code Entity. You produce a single TypeScript implementation that satisfies the user's task. Output only valid TypeScript code, no markdown fences or extra commentary. The code will be reviewed by a Critic and then verified by running tests.`;
|
|
8
9
|
const CODE_CRITIC_SYSTEM = `You are the Critic. Review the draft code for bugs, edge cases, and style. Be concise. List specific issues and suggestions. Do not rewrite the code; only critique.`;
|
|
9
10
|
const CODE_JUDGE_SYSTEM = `You are the Judge. Given the task, the draft code, and the critique, produce the final single TypeScript implementation. Output only valid TypeScript code, no markdown fences or extra commentary. Incorporate the critic's feedback. The result will be run through vitest.`;
|
|
10
|
-
function systemPrompt(role, store) {
|
|
11
|
+
function systemPrompt(role, store, domain = "code") {
|
|
11
12
|
if (store) {
|
|
12
13
|
const s = getStrategy(store, role);
|
|
13
14
|
if (s) {
|
|
14
15
|
return s;
|
|
15
16
|
}
|
|
16
17
|
}
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
18
|
+
// Hard-coded defaults for "code" domain (backward compat)
|
|
19
|
+
if (domain === "code") {
|
|
20
|
+
const defaults = {
|
|
21
|
+
generator: CODE_GENERATOR_SYSTEM,
|
|
22
|
+
critic: CODE_CRITIC_SYSTEM,
|
|
23
|
+
judge: CODE_JUDGE_SYSTEM,
|
|
24
|
+
};
|
|
25
|
+
const d = defaults[role];
|
|
26
|
+
if (d)
|
|
27
|
+
return d;
|
|
28
|
+
}
|
|
29
|
+
// Fall back to domain prompt registry
|
|
30
|
+
const prompts = getDomainPrompts(domain);
|
|
31
|
+
const roleMap = {
|
|
32
|
+
generator: prompts.generator,
|
|
33
|
+
critic: prompts.critic,
|
|
34
|
+
judge: prompts.judge,
|
|
21
35
|
};
|
|
22
|
-
return
|
|
36
|
+
return roleMap[role] ?? prompts.generator;
|
|
23
37
|
}
|
|
24
38
|
/**
|
|
25
39
|
* Generator: task -> draft artifact (code).
|
|
26
40
|
*/
|
|
27
|
-
export async function runGenerator(gateway, memory, store = null) {
|
|
41
|
+
export async function runGenerator(gateway, memory, store = null, domain = "code") {
|
|
28
42
|
let userContent = memory.task;
|
|
29
43
|
if (memory.longTermContext) {
|
|
30
44
|
userContent = userContent + "\n\nRelevant verified knowledge:\n" + memory.longTermContext;
|
|
31
45
|
}
|
|
32
|
-
const system = systemPrompt("generator", store);
|
|
46
|
+
const system = systemPrompt("generator", store, domain);
|
|
33
47
|
const messages = [
|
|
34
48
|
{ role: "system", content: system },
|
|
35
49
|
{ role: "user", content: userContent },
|
|
@@ -40,8 +54,8 @@ export async function runGenerator(gateway, memory, store = null) {
|
|
|
40
54
|
/**
|
|
41
55
|
* Critic: draft + task -> critique.
|
|
42
56
|
*/
|
|
43
|
-
export async function runCritic(gateway, memory, store = null) {
|
|
44
|
-
const system = systemPrompt("critic", store);
|
|
57
|
+
export async function runCritic(gateway, memory, store = null, domain = "code") {
|
|
58
|
+
const system = systemPrompt("critic", store, domain);
|
|
45
59
|
const messages = [
|
|
46
60
|
{ role: "system", content: system },
|
|
47
61
|
{ role: "user", content: `Task:\n${memory.task}\n\nDraft code:\n${memory.draft}` },
|
|
@@ -52,8 +66,8 @@ export async function runCritic(gateway, memory, store = null) {
|
|
|
52
66
|
/**
|
|
53
67
|
* Judge: task + draft + critique -> final candidate artifact.
|
|
54
68
|
*/
|
|
55
|
-
export async function runJudge(gateway, memory, store = null) {
|
|
56
|
-
const system = systemPrompt("judge", store);
|
|
69
|
+
export async function runJudge(gateway, memory, store = null, domain = "code") {
|
|
70
|
+
const system = systemPrompt("judge", store, domain);
|
|
57
71
|
const messages = [
|
|
58
72
|
{ role: "system", content: system },
|
|
59
73
|
{
|
|
@@ -68,13 +82,13 @@ export async function runJudge(gateway, memory, store = null) {
|
|
|
68
82
|
* Run a single role with task and inputs (node_id -> content from predecessors).
|
|
69
83
|
* Returns the role's output string. Used by the graph runner.
|
|
70
84
|
*/
|
|
71
|
-
export async function runRole(role, gateway, task, inputs, longTermContext = "", store = null) {
|
|
85
|
+
export async function runRole(role, gateway, task, inputs, longTermContext = "", store = null, domain = "code") {
|
|
72
86
|
let userContent = task;
|
|
73
87
|
if (longTermContext) {
|
|
74
88
|
userContent = task + "\n\nRelevant verified knowledge:\n" + longTermContext;
|
|
75
89
|
}
|
|
76
90
|
if (role === "generator") {
|
|
77
|
-
const system = systemPrompt("generator", store);
|
|
91
|
+
const system = systemPrompt("generator", store, domain);
|
|
78
92
|
const messages = [
|
|
79
93
|
{ role: "system", content: system },
|
|
80
94
|
{ role: "user", content: userContent },
|
|
@@ -87,7 +101,7 @@ export async function runRole(role, gateway, task, inputs, longTermContext = "",
|
|
|
87
101
|
if (longTermContext) {
|
|
88
102
|
content = content + "\n\nRelevant verified knowledge:\n" + longTermContext;
|
|
89
103
|
}
|
|
90
|
-
const system = systemPrompt("critic", store);
|
|
104
|
+
const system = systemPrompt("critic", store, domain);
|
|
91
105
|
const messages = [
|
|
92
106
|
{ role: "system", content: system },
|
|
93
107
|
{ role: "user", content: content },
|
|
@@ -101,7 +115,7 @@ export async function runRole(role, gateway, task, inputs, longTermContext = "",
|
|
|
101
115
|
if (longTermContext) {
|
|
102
116
|
content = content + "\n\nRelevant verified knowledge:\n" + longTermContext;
|
|
103
117
|
}
|
|
104
|
-
const system = systemPrompt("judge", store);
|
|
118
|
+
const system = systemPrompt("judge", store, domain);
|
|
105
119
|
const messages = [
|
|
106
120
|
{ role: "system", content: system },
|
|
107
121
|
{ role: "user", content: content },
|
package/dist/cli.js
CHANGED
|
@@ -14,6 +14,8 @@ async function main() {
|
|
|
14
14
|
.argument("<task>", "Task description (e.g. 'Implement a function add(a,b) that returns a+b.')")
|
|
15
15
|
.option("-t, --test <path>", "Path to file containing test code (e.g. vitest test module). If omitted, only syntax check.")
|
|
16
16
|
.option("--json", "Output result as JSON (draft, critique, final, verification_passed, authoritative_artifact).")
|
|
17
|
+
.option("-p, --provider <name>", "LLM provider (openai, google, zai, local). Auto-detected from env if omitted.")
|
|
18
|
+
.option("-m, --model <name>", "Model for all roles (overrides provider default).")
|
|
17
19
|
.action(async (task, options) => {
|
|
18
20
|
// Validate task input
|
|
19
21
|
const validation = validateTask(task);
|
|
@@ -30,7 +32,10 @@ async function main() {
|
|
|
30
32
|
if (options.test && fs.existsSync(options.test)) {
|
|
31
33
|
testCode = fs.readFileSync(options.test, "utf-8");
|
|
32
34
|
}
|
|
33
|
-
const entity = new CodeEntity(defaultCodeEntityBindings(
|
|
35
|
+
const entity = new CodeEntity(defaultCodeEntityBindings({
|
|
36
|
+
provider: options.provider,
|
|
37
|
+
model: options.model,
|
|
38
|
+
}));
|
|
34
39
|
const memory = await entity.run(task, { testCode });
|
|
35
40
|
if (options.json) {
|
|
36
41
|
const out = {
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CodeVerifier: adapter that wraps the existing vitest-based runVerifier into the Verifier interface.
|
|
3
|
+
*/
|
|
4
|
+
import type { WorkingMemory } from "./memory.js";
|
|
5
|
+
import type { Verifier, VerificationResult, VerifierContext } from "./verifier-interface.js";
|
|
6
|
+
/**
|
|
7
|
+
* Wraps the existing vitest verifier (runVerifier) into the pluggable Verifier interface.
|
|
8
|
+
* Uses context.testCode for the test file, same as CodeEntity.
|
|
9
|
+
*/
|
|
10
|
+
export declare class CodeVerifier implements Verifier {
|
|
11
|
+
readonly name = "CodeVerifier";
|
|
12
|
+
verify(memory: WorkingMemory, context?: VerifierContext): Promise<VerificationResult>;
|
|
13
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CodeVerifier: adapter that wraps the existing vitest-based runVerifier into the Verifier interface.
|
|
3
|
+
*/
|
|
4
|
+
import { runVerifier } from "./verifier.js";
|
|
5
|
+
/**
|
|
6
|
+
* Wraps the existing vitest verifier (runVerifier) into the pluggable Verifier interface.
|
|
7
|
+
* Uses context.testCode for the test file, same as CodeEntity.
|
|
8
|
+
*/
|
|
9
|
+
export class CodeVerifier {
|
|
10
|
+
name = "CodeVerifier";
|
|
11
|
+
async verify(memory, context) {
|
|
12
|
+
const testCode = context?.testCode;
|
|
13
|
+
// runVerifier mutates memory.verificationPassed / verificationEvidence
|
|
14
|
+
await runVerifier(memory, testCode);
|
|
15
|
+
return {
|
|
16
|
+
passed: memory.verificationPassed,
|
|
17
|
+
evidence: memory.verificationEvidence || (memory.verificationPassed ? "Verification passed." : "Verification failed."),
|
|
18
|
+
verifierName: this.name,
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CompositeVerifier: runs multiple verifiers, all must pass.
|
|
3
|
+
*/
|
|
4
|
+
import type { WorkingMemory } from "./memory.js";
|
|
5
|
+
import type { Verifier, VerificationResult, VerifierContext } from "./verifier-interface.js";
|
|
6
|
+
export interface CompositeVerifierOptions {
|
|
7
|
+
/** If true, stop at first failure. Defaults to true. */
|
|
8
|
+
failFast?: boolean;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Runs verifiers sequentially. All must pass for the composite to pass.
|
|
12
|
+
* Fail-fast mode (default) stops at the first failure.
|
|
13
|
+
* Collect-all mode runs every verifier and reports all results.
|
|
14
|
+
*/
|
|
15
|
+
export declare class CompositeVerifier implements Verifier {
|
|
16
|
+
readonly name = "CompositeVerifier";
|
|
17
|
+
private verifiers;
|
|
18
|
+
private failFast;
|
|
19
|
+
constructor(verifiers: Verifier[], options?: CompositeVerifierOptions);
|
|
20
|
+
verify(memory: WorkingMemory, context?: VerifierContext): Promise<VerificationResult>;
|
|
21
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CompositeVerifier: runs multiple verifiers, all must pass.
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* Runs verifiers sequentially. All must pass for the composite to pass.
|
|
6
|
+
* Fail-fast mode (default) stops at the first failure.
|
|
7
|
+
* Collect-all mode runs every verifier and reports all results.
|
|
8
|
+
*/
|
|
9
|
+
export class CompositeVerifier {
|
|
10
|
+
name = "CompositeVerifier";
|
|
11
|
+
verifiers;
|
|
12
|
+
failFast;
|
|
13
|
+
constructor(verifiers, options) {
|
|
14
|
+
if (verifiers.length === 0) {
|
|
15
|
+
throw new Error("CompositeVerifier requires at least one verifier");
|
|
16
|
+
}
|
|
17
|
+
this.verifiers = verifiers;
|
|
18
|
+
this.failFast = options?.failFast ?? true;
|
|
19
|
+
}
|
|
20
|
+
async verify(memory, context) {
|
|
21
|
+
const details = [];
|
|
22
|
+
let allPassed = true;
|
|
23
|
+
for (const verifier of this.verifiers) {
|
|
24
|
+
const result = await verifier.verify(memory, context);
|
|
25
|
+
details.push(result);
|
|
26
|
+
if (!result.passed) {
|
|
27
|
+
allPassed = false;
|
|
28
|
+
if (this.failFast)
|
|
29
|
+
break;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
const evidence = details
|
|
33
|
+
.map((d) => `[${d.verifierName}] ${d.passed ? "PASS" : "FAIL"}: ${d.evidence}`)
|
|
34
|
+
.join("\n");
|
|
35
|
+
return {
|
|
36
|
+
passed: allPassed,
|
|
37
|
+
evidence,
|
|
38
|
+
verifierName: this.name,
|
|
39
|
+
details,
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
}
|
package/dist/config.d.ts
CHANGED
|
@@ -19,6 +19,23 @@ export declare const AgentConfigSchema: z.ZodObject<{
|
|
|
19
19
|
}, z.core.$strip>>>;
|
|
20
20
|
}, z.core.$strip>;
|
|
21
21
|
export type AgentConfig = z.infer<typeof AgentConfigSchema>;
|
|
22
|
+
export declare const PolicyRuleSchema: z.ZodObject<{
|
|
23
|
+
id: z.ZodString;
|
|
24
|
+
description: z.ZodString;
|
|
25
|
+
target: z.ZodEnum<{
|
|
26
|
+
artifact: "artifact";
|
|
27
|
+
task: "task";
|
|
28
|
+
both: "both";
|
|
29
|
+
}>;
|
|
30
|
+
pattern: z.ZodString;
|
|
31
|
+
action: z.ZodEnum<{
|
|
32
|
+
deny: "deny";
|
|
33
|
+
allow: "allow";
|
|
34
|
+
}>;
|
|
35
|
+
category: z.ZodString;
|
|
36
|
+
enabled: z.ZodDefault<z.ZodBoolean>;
|
|
37
|
+
}, z.core.$strip>;
|
|
38
|
+
export type PolicyRuleConfig = z.infer<typeof PolicyRuleSchema>;
|
|
22
39
|
export declare const MoltblockConfigSchema: z.ZodObject<{
|
|
23
40
|
agent: z.ZodOptional<z.ZodObject<{
|
|
24
41
|
bindings: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
@@ -28,6 +45,24 @@ export declare const MoltblockConfigSchema: z.ZodObject<{
|
|
|
28
45
|
api_key: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
29
46
|
}, z.core.$strip>>>;
|
|
30
47
|
}, z.core.$strip>>;
|
|
48
|
+
policy: z.ZodOptional<z.ZodObject<{
|
|
49
|
+
rules: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
50
|
+
id: z.ZodString;
|
|
51
|
+
description: z.ZodString;
|
|
52
|
+
target: z.ZodEnum<{
|
|
53
|
+
artifact: "artifact";
|
|
54
|
+
task: "task";
|
|
55
|
+
both: "both";
|
|
56
|
+
}>;
|
|
57
|
+
pattern: z.ZodString;
|
|
58
|
+
action: z.ZodEnum<{
|
|
59
|
+
deny: "deny";
|
|
60
|
+
allow: "allow";
|
|
61
|
+
}>;
|
|
62
|
+
category: z.ZodString;
|
|
63
|
+
enabled: z.ZodDefault<z.ZodBoolean>;
|
|
64
|
+
}, z.core.$strip>>>;
|
|
65
|
+
}, z.core.$strip>>;
|
|
31
66
|
}, z.core.$strip>;
|
|
32
67
|
export type MoltblockConfig = z.infer<typeof MoltblockConfigSchema>;
|
|
33
68
|
export declare const ModelBindingSchema: z.ZodObject<{
|
|
@@ -48,8 +83,28 @@ export declare function getConfigSource(): ConfigSource;
|
|
|
48
83
|
* Returns null if no file or parse error.
|
|
49
84
|
*/
|
|
50
85
|
export declare function loadMoltblockConfig(): MoltblockConfig | null;
|
|
86
|
+
/** Overrides for provider/model selection (e.g. from CLI flags). */
|
|
87
|
+
export interface BindingOverrides {
|
|
88
|
+
provider?: string;
|
|
89
|
+
model?: string;
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Auto-detect the best available provider from environment variables.
|
|
93
|
+
* Priority: explicit override > OPENAI_API_KEY > GOOGLE_API_KEY > MOLTBLOCK_ZAI_API_KEY/ZAI_API_KEY > local.
|
|
94
|
+
*/
|
|
95
|
+
export declare function detectProvider(overrideProvider?: string, overrideModel?: string): {
|
|
96
|
+
backend: string;
|
|
97
|
+
baseUrl: string;
|
|
98
|
+
model: string;
|
|
99
|
+
apiKey: string | null;
|
|
100
|
+
};
|
|
51
101
|
/**
|
|
52
102
|
* Model bindings for Code Entity. Load from moltblock.json if present, then env overrides.
|
|
53
|
-
* If no JSON,
|
|
103
|
+
* If no JSON, auto-detects provider from env vars. API keys from env win over JSON.
|
|
104
|
+
*/
|
|
105
|
+
export declare function defaultCodeEntityBindings(overrides?: BindingOverrides): Record<string, ModelBinding>;
|
|
106
|
+
/**
|
|
107
|
+
* Load custom policy rules from moltblock config.
|
|
108
|
+
* Returns empty array if no config or no rules defined.
|
|
54
109
|
*/
|
|
55
|
-
export declare function
|
|
110
|
+
export declare function loadPolicyRules(): PolicyRuleConfig[];
|