From 25161a9f64d191ecb882220a6bf713e2f2b5a5aa Mon Sep 17 00:00:00 2001 From: evosoft-ie Date: Sun, 28 Dec 2025 10:38:42 +0000 Subject: [PATCH] Implement TypingMonitor to track typing events --- .../src/monitors/typingMonitor.ts | 66 +++++++++++++++++++ 1 file changed, 66 insertions(+) create mode 100644 vscode-extension/src/monitors/typingMonitor.ts diff --git a/vscode-extension/src/monitors/typingMonitor.ts b/vscode-extension/src/monitors/typingMonitor.ts new file mode 100644 index 0000000..0f505b1 --- /dev/null +++ b/vscode-extension/src/monitors/typingMonitor.ts @@ -0,0 +1,66 @@ +import * as vscode from 'vscode'; + +interface TypingEvent { + timestamp: number; + charactersAdded: number; + position: vscode.Position; + velocityScore: number; // chars/second +} + +export class TypingMonitor { + private events: TypingEvent[] = []; + private readonly WINDOW_SIZE = 5000; // 5 seconds + private readonly SUSPICIOUS_VELOCITY = 500; // chars/sec (humanly impossible) + + constructor(private context: vscode.ExtensionContext) { + // Listen to document changes + vscode.workspace.onDidChangeTextDocument(this.onDocumentChange, this); + } + + private onDocumentChange(event: vscode.TextDocumentChangeEvent) { + for (const change of event.contentChanges) { + const charsAdded = change.text.length; + const now = Date.now(); + + // Calculate velocity + const recentEvents = this.getRecentEvents(now); + const velocity = this.calculateVelocity(recentEvents, charsAdded); + + this.events.push({ + timestamp: now, + charactersAdded: charsAdded, + position: change.range.start, + velocityScore: velocity + }); + + // Cleanup old events + this.pruneEvents(now); + } + } + + private calculateVelocity(events: TypingEvent[], newChars: number): number { + if (events.length === 0) return 0; + + const timeSpan = Date.now() - events[0].timestamp; + const totalChars = events.reduce((sum, e) => sum + e.charactersAdded, newChars); + + return (totalChars / timeSpan) * 1000; // chars per second + } + + public getAnomalyScore(document: vscode.TextDocument): number { + // Return 0-1 score based on typing anomalies + const suspiciousEvents = this.events.filter( + e => e.velocityScore > this.SUSPICIOUS_VELOCITY + ); + + return Math.min(suspiciousEvents.length / 10, 1.0); + } + + private getRecentEvents(now: number): TypingEvent[] { + return this.events.filter(e => now - e.timestamp < this.WINDOW_SIZE); + } + + private pruneEvents(now: number) { + this.events = this.events.filter(e => now - e.timestamp < this.WINDOW_SIZE * 2); + } +}