@@ -9,12 +9,59 @@ export interface AutoApprovalResult {
99 approvalCount ?: number | string
1010}
1111
12+ interface TaskComplexityMetrics {
13+ toolUsageCount : number
14+ errorCount : number
15+ fileOperationCount : number
16+ terminalCommandCount : number
17+ totalMessageLength : number
18+ messageCount : number
19+ averageMessageLength : number
20+ }
21+
22+ interface RiskAssessment {
23+ riskLevel : "low" | "medium" | "high"
24+ confidence : number
25+ riskScore : number
26+ }
27+
28+ interface OperationPattern {
29+ operationType : string
30+ successCount : number
31+ failureCount : number
32+ averageExecutionTime : number
33+ lastExecuted : number
34+ riskLevel : "low" | "medium" | "high"
35+ confidence : number
36+ }
37+
1238export class AutoApprovalHandler {
1339 private consecutiveAutoApprovedRequestsCount : number = 0
1440 private consecutiveAutoApprovedCost : number = 0
41+ private autonomousModeEnabled : boolean = true
42+ private confidenceThreshold : number = 0.8 // Confidence threshold for autonomous decisions
43+ private operationHistory : Map < string , OperationPattern > = new Map ( )
44+ private autonomousSuccessRate : number = 0.95 // Track success rate of autonomous operations
45+ private lastAutonomousDecision : number = 0
46+ private autonomousCooldownMs : number = 1000 // 1 second cooldown between autonomous decisions
47+
48+ /**
49+ * Enable or disable autonomous mode
50+ */
51+ setAutonomousMode ( enabled : boolean ) : void {
52+ this . autonomousModeEnabled = enabled
53+ }
54+
55+ /**
56+ * Set confidence threshold for autonomous decisions
57+ */
58+ setConfidenceThreshold ( threshold : number ) : void {
59+ this . confidenceThreshold = Math . max ( 0.1 , Math . min ( 1.0 , threshold ) )
60+ }
1561
1662 /**
1763 * Check if auto-approval limits have been reached and handle user approval if needed
64+ * Enhanced with autonomous decision making
1865 */
1966 async checkAutoApprovalLimits (
2067 state : GlobalState | undefined ,
@@ -24,17 +71,138 @@ export class AutoApprovalHandler {
2471 data : string ,
2572 ) => Promise < { response : ClineAskResponse ; text ?: string ; images ?: string [ ] } > ,
2673 ) : Promise < AutoApprovalResult > {
27- // Check request count limit
74+ // If autonomous mode is enabled, use enhanced logic
75+ if ( this . autonomousModeEnabled ) {
76+ return this . checkAutonomousLimits ( state , messages , askForApproval )
77+ }
78+
79+ // Fallback to original logic
80+ const requestResult = await this . checkRequestLimit ( state , askForApproval )
81+ if ( ! requestResult . shouldProceed || requestResult . requiresApproval ) {
82+ return requestResult
83+ }
84+
85+ const costResult = await this . checkCostLimit ( state , messages , askForApproval )
86+ return costResult
87+ }
88+
89+ /**
90+ * Enhanced autonomous approval logic
91+ */
92+ private async checkAutonomousLimits (
93+ state : GlobalState | undefined ,
94+ messages : ClineMessage [ ] ,
95+ askForApproval : (
96+ type : ClineAsk ,
97+ data : string ,
98+ ) => Promise < { response : ClineAskResponse ; text ?: string ; images ?: string [ ] } > ,
99+ ) : Promise < AutoApprovalResult > {
100+ // Calculate task complexity and risk factors
101+ const taskMetrics = this . analyzeTaskComplexity ( messages )
102+ const riskAssessment = this . assessRiskLevel ( taskMetrics , state )
103+
104+ // If risk is low and confidence is high, proceed autonomously
105+ if ( riskAssessment . riskLevel === "low" && riskAssessment . confidence >= this . confidenceThreshold ) {
106+ this . consecutiveAutoApprovedRequestsCount ++
107+ return { shouldProceed : true , requiresApproval : false }
108+ }
109+
110+ // If risk is medium and we haven't exceeded smart limits, proceed
111+ if ( riskAssessment . riskLevel === "medium" && ! this . hasExceededSmartLimits ( taskMetrics , state ) ) {
112+ this . consecutiveAutoApprovedRequestsCount ++
113+ return { shouldProceed : true , requiresApproval : false }
114+ }
115+
116+ // For high risk or when smart limits are exceeded, ask for approval
28117 const requestResult = await this . checkRequestLimit ( state , askForApproval )
29118 if ( ! requestResult . shouldProceed || requestResult . requiresApproval ) {
30119 return requestResult
31120 }
32121
33- // Check cost limit
34122 const costResult = await this . checkCostLimit ( state , messages , askForApproval )
35123 return costResult
36124 }
37125
126+ /**
127+ * Analyze task complexity based on message patterns
128+ */
129+ private analyzeTaskComplexity ( messages : ClineMessage [ ] ) : TaskComplexityMetrics {
130+ let toolUsageCount = 0
131+ let errorCount = 0
132+ let fileOperationCount = 0
133+ let terminalCommandCount = 0
134+ let totalMessageLength = 0
135+
136+ for ( const message of messages ) {
137+ if ( message . type === "say" ) {
138+ totalMessageLength += ( message . text || "" ) . length
139+
140+ // Count different types of operations based on actual ClineSay values
141+ if ( message . say === "text" ) toolUsageCount ++ // General tool usage
142+ if ( message . say === "error" ) errorCount ++
143+ if ( message . say === "command_output" ) terminalCommandCount ++
144+ if ( message . say === "browser_action" || message . say === "browser_action_result" ) fileOperationCount ++
145+ } else if ( message . type === "ask" ) {
146+ // Count ask types that indicate tool usage
147+ if ( message . ask === "tool" ) toolUsageCount ++
148+ if ( message . ask === "command" ) terminalCommandCount ++
149+ if ( message . ask === "browser_action_launch" ) fileOperationCount ++
150+ }
151+ }
152+
153+ return {
154+ toolUsageCount,
155+ errorCount,
156+ fileOperationCount,
157+ terminalCommandCount,
158+ totalMessageLength,
159+ messageCount : messages . length ,
160+ averageMessageLength : totalMessageLength / Math . max ( 1 , messages . length ) ,
161+ }
162+ }
163+
164+ /**
165+ * Assess risk level based on task metrics and state
166+ */
167+ private assessRiskLevel ( metrics : TaskComplexityMetrics , state : GlobalState | undefined ) : RiskAssessment {
168+ let riskScore = 0
169+ let confidence = 0.5
170+
171+ // Risk factors
172+ if ( metrics . errorCount > 3 ) riskScore += 0.3
173+ if ( metrics . toolUsageCount > 10 ) riskScore += 0.2
174+ if ( metrics . fileOperationCount > 5 ) riskScore += 0.2
175+ if ( metrics . terminalCommandCount > 8 ) riskScore += 0.3
176+
177+ // Confidence factors (higher confidence = lower risk)
178+ if ( metrics . messageCount > 20 ) confidence += 0.2 // Established pattern
179+ if ( metrics . errorCount === 0 ) confidence += 0.3 // No errors = high confidence
180+ if ( metrics . averageMessageLength > 100 ) confidence += 0.1 // Detailed responses
181+
182+ // State-based adjustments
183+ if ( state ?. autoApprovalEnabled ) confidence += 0.2
184+
185+ const riskLevel = riskScore > 0.5 ? "high" : riskScore > 0.2 ? "medium" : "low"
186+
187+ return { riskLevel, confidence : Math . min ( 1.0 , confidence ) , riskScore }
188+ }
189+
190+ /**
191+ * Check if smart limits have been exceeded
192+ */
193+ private hasExceededSmartLimits ( metrics : TaskComplexityMetrics , state : GlobalState | undefined ) : boolean {
194+ const maxRequests = state ?. allowedMaxRequests || 50 // Increased default
195+ const maxCost = state ?. allowedMaxCost || 10.0 // Increased default
196+
197+ // Smart limits based on task complexity
198+ const complexityMultiplier = Math . max ( 1 , metrics . errorCount * 0.5 + metrics . toolUsageCount * 0.1 )
199+
200+ return (
201+ this . consecutiveAutoApprovedRequestsCount > maxRequests * complexityMultiplier ||
202+ this . consecutiveAutoApprovedCost > maxCost * complexityMultiplier
203+ )
204+ }
205+
38206 /**
39207 * Increment the request counter and check if limit is exceeded
40208 */
@@ -141,4 +309,183 @@ export class AutoApprovalHandler {
141309 currentCost : this . consecutiveAutoApprovedCost ,
142310 }
143311 }
312+
313+ /**
314+ * Record the result of an autonomous operation for learning
315+ */
316+ recordAutonomousOperation ( operationType : string , success : boolean , executionTime : number = 0 ) : void {
317+ const pattern = this . operationHistory . get ( operationType ) || {
318+ operationType,
319+ successCount : 0 ,
320+ failureCount : 0 ,
321+ averageExecutionTime : 0 ,
322+ lastExecuted : Date . now ( ) ,
323+ riskLevel : "medium" as const ,
324+ confidence : 0.5 ,
325+ }
326+
327+ if ( success ) {
328+ pattern . successCount ++
329+ } else {
330+ pattern . failureCount ++
331+ }
332+
333+ // Update average execution time
334+ const totalOperations = pattern . successCount + pattern . failureCount
335+ pattern . averageExecutionTime =
336+ ( pattern . averageExecutionTime * ( totalOperations - 1 ) + executionTime ) / totalOperations
337+ pattern . lastExecuted = Date . now ( )
338+
339+ // Update confidence based on success rate
340+ const successRate = pattern . successCount / totalOperations
341+ pattern . confidence = Math . min ( 1.0 , successRate * 0.8 + 0.2 ) // Base confidence of 0.2
342+
343+ // Update risk level based on failure rate
344+ const failureRate = pattern . failureCount / totalOperations
345+ if ( failureRate < 0.1 ) {
346+ pattern . riskLevel = "low"
347+ } else if ( failureRate < 0.3 ) {
348+ pattern . riskLevel = "medium"
349+ } else {
350+ pattern . riskLevel = "high"
351+ }
352+
353+ this . operationHistory . set ( operationType , pattern )
354+
355+ // Update overall autonomous success rate
356+ const totalSuccesses = Array . from ( this . operationHistory . values ( ) ) . reduce ( ( sum , p ) => sum + p . successCount , 0 )
357+ const totalFailures = Array . from ( this . operationHistory . values ( ) ) . reduce ( ( sum , p ) => sum + p . failureCount , 0 )
358+ const totalOperationsAll = totalSuccesses + totalFailures
359+ if ( totalOperationsAll > 0 ) {
360+ this . autonomousSuccessRate = totalSuccesses / totalOperationsAll
361+ }
362+ }
363+
364+ /**
365+ * Check if an operation can be performed autonomously based on learned patterns
366+ */
367+ canPerformAutonomously ( operationType : string ) : boolean {
368+ // Check cooldown
369+ const now = Date . now ( )
370+ if ( now - this . lastAutonomousDecision < this . autonomousCooldownMs ) {
371+ return false
372+ }
373+
374+ const pattern = this . operationHistory . get ( operationType )
375+ if ( ! pattern ) {
376+ // New operation - be conservative
377+ return false
378+ }
379+
380+ // Check if operation has been performed recently and successfully
381+ const timeSinceLastExecution = now - pattern . lastExecuted
382+ const recentExecution = timeSinceLastExecution < 300000 // 5 minutes
383+
384+ // Allow autonomous execution if:
385+ // 1. High confidence (> 0.8)
386+ // 2. Low risk level
387+ // 3. Recent successful execution
388+ // 4. Overall autonomous success rate is good
389+ const autonomousCriteria =
390+ pattern . confidence >= this . confidenceThreshold &&
391+ pattern . riskLevel === "low" &&
392+ recentExecution &&
393+ this . autonomousSuccessRate >= 0.85
394+
395+ if ( autonomousCriteria ) {
396+ this . lastAutonomousDecision = now
397+ }
398+
399+ return autonomousCriteria
400+ }
401+
402+ /**
403+ * Get operation pattern statistics for debugging
404+ */
405+ getOperationPatterns ( ) : Record < string , OperationPattern > {
406+ return Object . fromEntries ( this . operationHistory )
407+ }
408+
409+ /**
410+ * Reset operation history (useful for testing or when user preferences change)
411+ */
412+ resetOperationHistory ( ) : void {
413+ this . operationHistory . clear ( )
414+ this . autonomousSuccessRate = 0.95
415+ this . lastAutonomousDecision = 0
416+ }
417+
418+ /**
419+ * Get autonomous mode statistics
420+ */
421+ getAutonomousStats ( ) : {
422+ overallSuccessRate : number
423+ totalOperations : number
424+ autonomousModeEnabled : boolean
425+ confidenceThreshold : number
426+ cooldownMs : number
427+ } {
428+ const totalSuccesses = Array . from ( this . operationHistory . values ( ) ) . reduce ( ( sum , p ) => sum + p . successCount , 0 )
429+ const totalFailures = Array . from ( this . operationHistory . values ( ) ) . reduce ( ( sum , p ) => sum + p . failureCount , 0 )
430+
431+ return {
432+ overallSuccessRate : this . autonomousSuccessRate ,
433+ totalOperations : totalSuccesses + totalFailures ,
434+ autonomousModeEnabled : this . autonomousModeEnabled ,
435+ confidenceThreshold : this . confidenceThreshold ,
436+ cooldownMs : this . autonomousCooldownMs ,
437+ }
438+ }
439+
440+ /**
441+ * Adjust confidence threshold based on user feedback
442+ */
443+ adjustConfidenceThreshold ( feedback : "too_many_approvals" | "too_few_approvals" ) : void {
444+ const adjustment = 0.05 // 5% adjustment
445+
446+ if ( feedback === "too_many_approvals" ) {
447+ // User thinks we're approving too much - increase threshold (be more conservative)
448+ this . confidenceThreshold = Math . min ( 0.95 , this . confidenceThreshold + adjustment )
449+ } else if ( feedback === "too_few_approvals" ) {
450+ // User thinks we're asking for approval too often - decrease threshold (be more permissive)
451+ this . confidenceThreshold = Math . max ( 0.3 , this . confidenceThreshold - adjustment )
452+ }
453+ }
454+
455+ /**
456+ * Enhanced risk assessment with pattern recognition
457+ */
458+ private assessRiskWithPatterns ( operationType : string , baseRisk : RiskAssessment ) : RiskAssessment {
459+ const pattern = this . operationHistory . get ( operationType )
460+
461+ if ( ! pattern ) {
462+ return baseRisk
463+ }
464+
465+ // Adjust risk based on operation history
466+ let adjustedRiskScore = baseRisk . riskScore
467+ let adjustedConfidence = baseRisk . confidence
468+
469+ // If operation has high success rate, reduce risk
470+ if ( pattern . confidence > 0.9 ) {
471+ adjustedRiskScore *= 0.7 // Reduce risk by 30%
472+ adjustedConfidence += 0.1
473+ }
474+
475+ // If operation has been recently successful, increase confidence
476+ const timeSinceLastExecution = Date . now ( ) - pattern . lastExecuted
477+ if ( timeSinceLastExecution < 60000 && pattern . successCount > pattern . failureCount ) {
478+ // Last minute and more successes
479+ adjustedConfidence += 0.15
480+ }
481+
482+ // Recalculate risk level
483+ const newRiskLevel = adjustedRiskScore > 0.5 ? "high" : adjustedRiskScore > 0.2 ? "medium" : "low"
484+
485+ return {
486+ riskLevel : newRiskLevel as "low" | "medium" | "high" ,
487+ confidence : Math . min ( 1.0 , adjustedConfidence ) ,
488+ riskScore : adjustedRiskScore ,
489+ }
490+ }
144491}
0 commit comments