types.ts
2781 bytes
1export const DECISION_CATEGORIES = [
2 "read_only",
3 "build_test",
4 "git_local",
5 "git_remote",
6 "file_mutation",
7 "system",
8 "network",
9 "uncertain",
10 "dangerous",
11 "config_allow",
12 "web_read",
13 "empty",
14 "session_allow",
15 "external_directory",
16 "bash",
17 "read",
18 "write",
19 "edit",
20 "find",
21 "grep",
22 "ls",
23 "webfetch",
24] as const;
25
26export type DecisionCategory = (typeof DECISION_CATEGORIES)[number];
27
28const decisionCategorySet: ReadonlySet<string> = new Set(DECISION_CATEGORIES);
29
30export function isDecisionCategory(value: unknown): value is DecisionCategory {
31 return typeof value === "string" && decisionCategorySet.has(value);
32}
33
34export type Decision = {
35 decision: "allow" | "deny" | "ask";
36 reason: string;
37 category: DecisionCategory;
38};
39
40export type LLMEvaluationResult = {
41 decision: Decision;
42 source?: "llm" | "none";
43 rawResponse?: string;
44 error?: string;
45};
46
47export type PolicyReviewer = {
48 evaluate(request: PolicyRequest, context: PolicyContext): Promise<LLMEvaluationResult>;
49};
50
51export type PiReasoningEffort = "none" | "minimal" | "low" | "medium" | "high" | "xhigh" | "max";
52
53export type ClassifierReviewerConfig = {
54 kind: "classifier";
55 provider: string;
56 model: string;
57 askThreshold: number;
58};
59
60export type ReviewerConfig =
61 | ClassifierReviewerConfig
62 | {
63 kind: "none";
64 }
65 | {
66 kind: "pi";
67 provider: string;
68 model: string;
69 reasoningEffort?: PiReasoningEffort;
70 promptCacheKey?: string;
71 }
72 | {
73 kind: "llama.cpp";
74 baseUrl: string;
75 model: string;
76 enableThinking: boolean;
77 };
78
79export type CacheEntry = {
80 key: string;
81 toolName: string;
82 decision: Decision;
83 source: "llm";
84 createdAt: string;
85};
86
87export type DecisionCache = {
88 lookup(key: string): Promise<Decision | undefined>;
89 write(entry: CacheEntry): Promise<void>;
90};
91
92export type DecisionSource = "session" | "static" | "deterministic" | "cache" | "llm" | "none";
93
94export type AuditEntry = {
95 toolName: string;
96 inputSummary: string;
97 decision: Decision;
98 source: DecisionSource;
99 timingMs: number;
100 sessionId?: string;
101 rawResponse?: string;
102};
103
104export type DecisionAudit = {
105 record(entry: AuditEntry): Promise<void>;
106};
107
108export type PolicyEvaluation = {
109 decision: Decision;
110 source: DecisionSource;
111 rawResponse?: string;
112 error?: string;
113 approvalRequests?: PolicyRequest[];
114};
115
116export type PolicyRequest = {
117 toolName: string;
118 input: Record<string, unknown>;
119};
120
121export type PolicyContext = {
122 sessionId?: string;
123 cwd?: string;
124 signal?: AbortSignal;
125};
126
127export type PolicyPrecheck = {
128 source: Exclude<DecisionSource, "llm" | "cache" | "deterministic" | "none">;
129 decide(request: PolicyRequest, context: PolicyContext): Promise<Decision | undefined>;
130};