0043edb882c6de055ea60f076080f0b921cd82af

Author
TheEdgeOfRage <git@theedgeofrage.com>
Committer
TheEdgeOfRage <git@theedgeofrage.com>
Date

Message

Add support for none llm review mode

Diff

 1diff --git a/README.md b/README.md
 2index 55c26ecae1b4958cb000ad86fb3d3f8ff7774d54..847e959b19117660a510c07973a31dae97887a0c 100644
 3--- a/README.md
 4+++ b/README.md
 5@@ -46,6 +46,16 @@ Pi reviewers accept `none`, `minimal`, `low`, `medium`, `high`, `xhigh`, and `ma
 6 
 7 `promptCacheKey` improves cache routing for Pi models that support it. It does not guarantee a cache hit.
 8 
 9+Disable LLM reviews. Requests that reach this stage ask for approval. Static rules, deterministic rules, and cached decisions still apply.
10+
11+```json
12+{
13+  "reviewer": {
14+    "kind": "none"
15+  }
16+}
17+```
18+
19 Use local llama.cpp. This backend does not use authentication.
20 
21 ```json
22diff --git a/src/core/config.ts b/src/core/config.ts
23index 8c585217cb6fe564de3c345e65bd68896317d13f..d9d0f6eb127d08f7f6ce0786393fa6ca0fbe7da8 100644
24--- a/src/core/config.ts
25+++ b/src/core/config.ts
26@@ -41,6 +41,8 @@ export function parseReviewerConfig(value: unknown): ReviewerConfig {
27       reasoningEffort: "minimal",
28     };
29   }
30+  if (reviewer.kind === "none") return { kind: "none" };
31+
32   const model = stringValue(reviewer.model);
33   if (!model) throw new Error("reviewer.model must be a non-empty string");
34   if (reviewer.kind === "llama.cpp") {
35@@ -53,7 +55,7 @@ export function parseReviewerConfig(value: unknown): ReviewerConfig {
36       enableThinking: booleanValue(reviewer.enableThinking, "reviewer.enableThinking", false),
37     };
38   }
39-  if (reviewer.kind !== "pi") throw new Error('reviewer.kind must be "pi" or "llama.cpp"');
40+  if (reviewer.kind !== "pi") throw new Error('reviewer.kind must be "none", "pi", or "llama.cpp"');
41 
42   const provider = stringValue(reviewer.provider);
43   if (!provider) throw new Error("reviewer.provider must be a non-empty string");
44diff --git a/src/core/review.ts b/src/core/review.ts
45index a66b6335d6f31834c54aaf066a86c3a80884e872..66acdb1732e00008133243f452969635aa6c4d3f 100644
46--- a/src/core/review.ts
47+++ b/src/core/review.ts
48@@ -68,6 +68,16 @@ export function createPolicyReviewer(
49 ): PolicyReviewer {
50   return {
51     async evaluate(request: PolicyRequest, context: PolicyContext): Promise<LLMEvaluationResult> {
52+      if (config.kind === "none") {
53+        return {
54+          decision: {
55+            decision: "ask",
56+            reason: "LLM reviews are disabled",
57+            category: "uncertain",
58+          },
59+        };
60+      }
61+
62       try {
63         const messages = [
64           { role: "system" as const, content: llmPolicyPrompt(externalDirectories) },
65diff --git a/src/core/types.ts b/src/core/types.ts
66index 49b4b1286a8cf6bd80f1719be72afe9e799ef24e..4a08e046b3c9f5c8c1526cb21316a009012f4598 100644
67--- a/src/core/types.ts
68+++ b/src/core/types.ts
69@@ -50,6 +50,9 @@ export type PolicyReviewer = {
70 export type PiReasoningEffort = "none" | "minimal" | "low" | "medium" | "high" | "xhigh" | "max";
71 
72 export type ReviewerConfig =
73+  | {
74+      kind: "none";
75+    }
76   | {
77       kind: "pi";
78       provider: string;