/ utils / classifierApprovals.ts
classifierApprovals.ts
 1  /**
 2   * Tracks which tool uses were auto-approved by classifiers.
 3   * Populated from useCanUseTool.ts and permissions.ts, read from UserToolSuccessMessage.tsx.
 4   */
 5  
 6  import { feature } from 'bun:bundle'
 7  import { createSignal } from './signal.js'
 8  
 9  type ClassifierApproval = {
10    classifier: 'bash' | 'auto-mode'
11    matchedRule?: string
12    reason?: string
13  }
14  
15  const CLASSIFIER_APPROVALS = new Map<string, ClassifierApproval>()
16  const CLASSIFIER_CHECKING = new Set<string>()
17  const classifierChecking = createSignal()
18  
19  export function setClassifierApproval(
20    toolUseID: string,
21    matchedRule: string,
22  ): void {
23    if (!feature('BASH_CLASSIFIER')) {
24      return
25    }
26    CLASSIFIER_APPROVALS.set(toolUseID, {
27      classifier: 'bash',
28      matchedRule,
29    })
30  }
31  
32  export function getClassifierApproval(toolUseID: string): string | undefined {
33    if (!feature('BASH_CLASSIFIER')) {
34      return undefined
35    }
36    const approval = CLASSIFIER_APPROVALS.get(toolUseID)
37    if (!approval || approval.classifier !== 'bash') return undefined
38    return approval.matchedRule
39  }
40  
41  export function setYoloClassifierApproval(
42    toolUseID: string,
43    reason: string,
44  ): void {
45    if (!feature('TRANSCRIPT_CLASSIFIER')) {
46      return
47    }
48    CLASSIFIER_APPROVALS.set(toolUseID, { classifier: 'auto-mode', reason })
49  }
50  
51  export function getYoloClassifierApproval(
52    toolUseID: string,
53  ): string | undefined {
54    if (!feature('TRANSCRIPT_CLASSIFIER')) {
55      return undefined
56    }
57    const approval = CLASSIFIER_APPROVALS.get(toolUseID)
58    if (!approval || approval.classifier !== 'auto-mode') return undefined
59    return approval.reason
60  }
61  
62  export function setClassifierChecking(toolUseID: string): void {
63    if (!feature('BASH_CLASSIFIER') && !feature('TRANSCRIPT_CLASSIFIER')) return
64    CLASSIFIER_CHECKING.add(toolUseID)
65    classifierChecking.emit()
66  }
67  
68  export function clearClassifierChecking(toolUseID: string): void {
69    if (!feature('BASH_CLASSIFIER') && !feature('TRANSCRIPT_CLASSIFIER')) return
70    CLASSIFIER_CHECKING.delete(toolUseID)
71    classifierChecking.emit()
72  }
73  
74  export const subscribeClassifierChecking = classifierChecking.subscribe
75  
76  export function isClassifierChecking(toolUseID: string): boolean {
77    return CLASSIFIER_CHECKING.has(toolUseID)
78  }
79  
80  export function deleteClassifierApproval(toolUseID: string): void {
81    CLASSIFIER_APPROVALS.delete(toolUseID)
82  }
83  
84  export function clearClassifierApprovals(): void {
85    CLASSIFIER_APPROVALS.clear()
86    CLASSIFIER_CHECKING.clear()
87    classifierChecking.emit()
88  }