bashbros 0.1.0 → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{chunk-SB4JS3GU.js → chunk-BW6XCOJH.js} +171 -21
- package/dist/chunk-BW6XCOJH.js.map +1 -0
- package/dist/chunk-FRMAIRQ2.js +89 -0
- package/dist/chunk-FRMAIRQ2.js.map +1 -0
- package/dist/{chunk-GD5VNHIN.js → chunk-QWZGB4V3.js} +4 -85
- package/dist/chunk-QWZGB4V3.js.map +1 -0
- package/dist/{chunk-4R4GV5V2.js → chunk-SQCP6IYB.js} +2 -2
- package/dist/{chunk-43W3RVEL.js → chunk-XCZMQRSX.js} +125 -10
- package/dist/chunk-XCZMQRSX.js.map +1 -0
- package/dist/chunk-YUMNBQAY.js +766 -0
- package/dist/chunk-YUMNBQAY.js.map +1 -0
- package/dist/cli.js +633 -29
- package/dist/cli.js.map +1 -1
- package/dist/{config-CZMIGNPF.js → config-JLLOTFLI.js} +2 -2
- package/dist/{db-EHQDB5OL.js → db-OBKEXRTP.js} +2 -2
- package/dist/{display-IN4NRJJS.js → display-6LZ2HBCU.js} +3 -3
- package/dist/engine-EGPAS2EX.js +10 -0
- package/dist/index.js +6 -4
- package/dist/index.js.map +1 -1
- package/dist/session-Y4MICATZ.js +15 -0
- package/dist/session-Y4MICATZ.js.map +1 -0
- package/dist/static/index.html +1873 -276
- package/package.json +1 -1
- package/dist/chunk-43W3RVEL.js.map +0 -1
- package/dist/chunk-CSRPOGHY.js +0 -354
- package/dist/chunk-CSRPOGHY.js.map +0 -1
- package/dist/chunk-GD5VNHIN.js.map +0 -1
- package/dist/chunk-SB4JS3GU.js.map +0 -1
- package/dist/engine-PKLXW6OF.js +0 -9
- /package/dist/{chunk-4R4GV5V2.js.map → chunk-SQCP6IYB.js.map} +0 -0
- /package/dist/{config-CZMIGNPF.js.map → config-JLLOTFLI.js.map} +0 -0
- /package/dist/{db-EHQDB5OL.js.map → db-OBKEXRTP.js.map} +0 -0
- /package/dist/{display-IN4NRJJS.js.map → display-6LZ2HBCU.js.map} +0 -0
- /package/dist/{engine-PKLXW6OF.js.map → engine-EGPAS2EX.js.map} +0 -0
package/package.json
CHANGED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/integration/bashgym.ts","../src/hooks/claude-code.ts","../src/core.ts","../src/bro/profiler.ts","../src/bro/router.ts","../src/bro/suggester.ts","../src/bro/worker.ts","../src/bro/bro.ts","../src/observability/metrics.ts","../src/observability/cost.ts","../src/observability/report.ts","../src/safety/undo-stack.ts","../src/policy/loop-detector.ts"],"sourcesContent":["/**\r\n * Bashgym Integration for Bashbros\r\n *\r\n * Provides integration between bashbros (security middleware + AI sidekick) and\r\n * bashgym (self-improving agent training) through a shared directory protocol.\r\n *\r\n * Key features:\r\n * - Trace export to shared directory\r\n * - Settings synchronization\r\n * - Model update watcher for hot-swap\r\n *\r\n * Data Flow:\r\n * bashbros captures traces -> bashgym trains -> GGUF to Ollama -> bashbros sidekick improves\r\n */\r\n\r\nimport { existsSync, mkdirSync, writeFileSync, readFileSync, watch, FSWatcher } from 'fs'\r\nimport { join } from 'path'\r\nimport { homedir } from 'os'\r\nimport { EventEmitter } from 'events'\r\nimport type { CommandResult, PolicyViolation } from '../types.js'\r\n\r\n// ============================================================================\r\n// Types\r\n// ============================================================================\r\n\r\nexport type CaptureMode = 'everything' | 'successful_only' | 'sidekick_curated'\r\nexport type TrainingTrigger = 'manual' | 'quality_based' | 'scheduled'\r\n\r\nexport interface IntegrationSettings {\r\n version: string\r\n updated_at: string | null\r\n updated_by: string | null\r\n\r\n integration: {\r\n enabled: boolean\r\n linked_at: string | null\r\n }\r\n\r\n capture: {\r\n mode: CaptureMode\r\n auto_stream: boolean\r\n }\r\n\r\n training: {\r\n auto_enabled: boolean\r\n quality_threshold: number\r\n trigger: TrainingTrigger\r\n }\r\n\r\n security: {\r\n bashbros_primary: boolean\r\n policy_path: string | null\r\n }\r\n\r\n model_sync: {\r\n auto_export_ollama: boolean\r\n ollama_model_name: string\r\n notify_on_update: boolean\r\n }\r\n}\r\n\r\nexport interface TraceData {\r\n version: string\r\n metadata: {\r\n user_initial_prompt: string\r\n source_tool: string\r\n task_id?: string\r\n verification_passed: boolean\r\n capture_mode: CaptureMode\r\n session_id: string\r\n }\r\n trace: TraceStep[]\r\n bashbros_extensions: {\r\n security_events: SecurityEvent[]\r\n sidekick_annotations: SidekickAnnotations\r\n }\r\n}\r\n\r\nexport interface TraceStep {\r\n tool_name: string\r\n command: string\r\n output: string\r\n success: boolean\r\n exit_code?: number\r\n timestamp: string\r\n cwd?: string\r\n}\r\n\r\nexport interface SecurityEvent {\r\n type: string\r\n timestamp: string\r\n command?: string\r\n violation?: PolicyViolation\r\n}\r\n\r\nexport interface SidekickAnnotations {\r\n teachable_moment: boolean\r\n complexity: 'easy' | 'medium' | 'hard'\r\n tags?: string[]\r\n}\r\n\r\nexport interface ModelManifest {\r\n latest: string\r\n versions: ModelVersion[]\r\n rollback_available: boolean\r\n}\r\n\r\nexport interface ModelVersion {\r\n version: string\r\n created: string\r\n traces_used: number\r\n quality_avg: number\r\n gguf_path: string | null\r\n}\r\n\r\nexport interface BashgymStatus {\r\n heartbeat: string\r\n version: string\r\n pending_traces: number\r\n processed_traces: number\r\n model_version: string | null\r\n}\r\n\r\n// ============================================================================\r\n// Events\r\n// ============================================================================\r\n\r\nexport interface BashgymIntegrationEvents {\r\n 'model:updated': (version: string, manifest: ModelManifest) => void\r\n 'settings:changed': (settings: IntegrationSettings) => void\r\n 'trace:exported': (filename: string) => void\r\n 'connected': () => void\r\n 'disconnected': () => void\r\n}\r\n\r\n// ============================================================================\r\n// Integration Class\r\n// ============================================================================\r\n\r\nconst DEFAULT_SETTINGS: IntegrationSettings = {\r\n version: '1.0',\r\n updated_at: null,\r\n updated_by: null,\r\n integration: {\r\n enabled: false,\r\n linked_at: null,\r\n },\r\n capture: {\r\n mode: 'successful_only',\r\n auto_stream: true,\r\n },\r\n training: {\r\n auto_enabled: false,\r\n quality_threshold: 50,\r\n trigger: 'quality_based',\r\n },\r\n security: {\r\n bashbros_primary: true,\r\n policy_path: null,\r\n },\r\n model_sync: {\r\n auto_export_ollama: true,\r\n ollama_model_name: 'bashgym-sidekick',\r\n notify_on_update: true,\r\n },\r\n}\r\n\r\nexport class BashgymIntegration extends EventEmitter {\r\n private integrationDir: string\r\n private settings: IntegrationSettings | null = null\r\n private manifest: ModelManifest | null = null\r\n private settingsWatcher: FSWatcher | null = null\r\n private modelWatcher: FSWatcher | null = null\r\n private sessionId: string\r\n private traceBuffer: TraceStep[] = []\r\n private securityEvents: SecurityEvent[] = []\r\n private currentPrompt: string = ''\r\n\r\n // Directory paths\r\n private tracesDir: string\r\n private pendingDir: string\r\n private modelsDir: string\r\n private configDir: string\r\n private statusDir: string\r\n\r\n constructor(integrationDir?: string) {\r\n super()\r\n\r\n this.integrationDir = integrationDir || join(homedir(), '.bashgym', 'integration')\r\n this.tracesDir = join(this.integrationDir, 'traces')\r\n this.pendingDir = join(this.tracesDir, 'pending')\r\n this.modelsDir = join(this.integrationDir, 'models')\r\n this.configDir = join(this.integrationDir, 'config')\r\n this.statusDir = join(this.integrationDir, 'status')\r\n\r\n this.sessionId = `bashbros-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`\r\n }\r\n\r\n /**\r\n * Initialize the integration\r\n */\r\n async initialize(): Promise<boolean> {\r\n // Check if bashgym integration directory exists\r\n if (!existsSync(this.integrationDir)) {\r\n return false\r\n }\r\n\r\n // Load settings\r\n this.settings = this.loadSettings()\r\n if (!this.settings?.integration.enabled) {\r\n return false\r\n }\r\n\r\n // Load model manifest\r\n this.manifest = this.loadManifest()\r\n\r\n // Start watching for changes\r\n this.startWatching()\r\n\r\n // Update bashbros status\r\n this.updateStatus()\r\n\r\n this.emit('connected')\r\n return true\r\n }\r\n\r\n /**\r\n * Check if bashgym is available\r\n */\r\n isAvailable(): boolean {\r\n return existsSync(this.integrationDir) && existsSync(this.configDir)\r\n }\r\n\r\n /**\r\n * Check if integration is linked\r\n */\r\n isLinked(): boolean {\r\n const settings = this.getSettings()\r\n return !!(settings?.integration.enabled && settings.integration.linked_at !== null)\r\n }\r\n\r\n // =========================================================================\r\n // Settings Management\r\n // =========================================================================\r\n\r\n getSettings(): IntegrationSettings | null {\r\n if (!this.settings) {\r\n this.settings = this.loadSettings()\r\n }\r\n return this.settings\r\n }\r\n\r\n private loadSettings(): IntegrationSettings | null {\r\n const settingsPath = join(this.configDir, 'settings.json')\r\n\r\n if (!existsSync(settingsPath)) {\r\n return null\r\n }\r\n\r\n try {\r\n const content = readFileSync(settingsPath, 'utf-8')\r\n return JSON.parse(content) as IntegrationSettings\r\n } catch {\r\n return null\r\n }\r\n }\r\n\r\n updateSettings(updates: Partial<IntegrationSettings>): void {\r\n const current = this.getSettings() || { ...DEFAULT_SETTINGS }\r\n\r\n // Deep merge updates\r\n const updated: IntegrationSettings = {\r\n ...current,\r\n ...updates,\r\n updated_at: new Date().toISOString(),\r\n updated_by: 'bashbros',\r\n }\r\n\r\n // Write to file\r\n const settingsPath = join(this.configDir, 'settings.json')\r\n writeFileSync(settingsPath, JSON.stringify(updated, null, 2))\r\n\r\n this.settings = updated\r\n this.emit('settings:changed', updated)\r\n }\r\n\r\n // =========================================================================\r\n // Trace Export\r\n // =========================================================================\r\n\r\n /**\r\n * Start a new trace session\r\n */\r\n startSession(prompt: string): void {\r\n this.currentPrompt = prompt\r\n this.traceBuffer = []\r\n this.securityEvents = []\r\n }\r\n\r\n /**\r\n * Add a step to the current trace\r\n */\r\n addStep(step: Omit<TraceStep, 'timestamp'>): void {\r\n this.traceBuffer.push({\r\n ...step,\r\n timestamp: new Date().toISOString(),\r\n })\r\n }\r\n\r\n /**\r\n * Add a command result to the trace\r\n */\r\n addCommandResult(result: CommandResult): void {\r\n this.addStep({\r\n tool_name: 'Bash',\r\n command: result.command,\r\n output: result.output || '',\r\n success: result.allowed && !result.error,\r\n exit_code: result.exitCode,\r\n cwd: process.cwd(),\r\n })\r\n\r\n // Track security events\r\n if (result.violations.length > 0) {\r\n this.securityEvents.push({\r\n type: 'violation',\r\n timestamp: new Date().toISOString(),\r\n command: result.command,\r\n violation: result.violations[0],\r\n })\r\n }\r\n }\r\n\r\n /**\r\n * Add a file operation to the trace\r\n */\r\n addFileOperation(operation: 'Read' | 'Write' | 'Edit', path: string, success: boolean, output?: string): void {\r\n this.addStep({\r\n tool_name: operation,\r\n command: path,\r\n output: output || '',\r\n success,\r\n })\r\n }\r\n\r\n /**\r\n * End the session and export the trace\r\n */\r\n async endSession(verificationPassed: boolean = false): Promise<string | null> {\r\n if (!this.currentPrompt || this.traceBuffer.length === 0) {\r\n return null\r\n }\r\n\r\n const settings = this.getSettings()\r\n if (!settings?.integration.enabled) {\r\n return null\r\n }\r\n\r\n // Check capture mode\r\n if (settings.capture.mode === 'successful_only' && !verificationPassed) {\r\n // Don't export failed traces\r\n this.clearSession()\r\n return null\r\n }\r\n\r\n // Build trace data\r\n const traceData: TraceData = {\r\n version: '1.0',\r\n metadata: {\r\n user_initial_prompt: this.currentPrompt,\r\n source_tool: 'bashbros',\r\n session_id: this.sessionId,\r\n verification_passed: verificationPassed,\r\n capture_mode: settings.capture.mode,\r\n },\r\n trace: this.traceBuffer,\r\n bashbros_extensions: {\r\n security_events: this.securityEvents,\r\n sidekick_annotations: {\r\n teachable_moment: this.determineTeachableMoment(),\r\n complexity: this.determineComplexity(),\r\n },\r\n },\r\n }\r\n\r\n // Export to pending directory\r\n const filename = `${Date.now()}-${this.sessionId.slice(-8)}.json`\r\n const filepath = join(this.pendingDir, filename)\r\n\r\n try {\r\n // Ensure directory exists\r\n if (!existsSync(this.pendingDir)) {\r\n mkdirSync(this.pendingDir, { recursive: true })\r\n }\r\n\r\n writeFileSync(filepath, JSON.stringify(traceData, null, 2))\r\n this.emit('trace:exported', filename)\r\n\r\n this.clearSession()\r\n return filename\r\n } catch (error) {\r\n console.error('Failed to export trace:', error)\r\n return null\r\n }\r\n }\r\n\r\n private clearSession(): void {\r\n this.currentPrompt = ''\r\n this.traceBuffer = []\r\n this.securityEvents = []\r\n this.sessionId = `bashbros-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`\r\n }\r\n\r\n private determineTeachableMoment(): boolean {\r\n // Heuristics for identifying teachable moments\r\n // - Session has multiple steps\r\n // - Includes error recovery\r\n // - Uses diverse tools\r\n const hasMultipleSteps = this.traceBuffer.length >= 3\r\n const hasErrorRecovery = this.traceBuffer.some((s, i) =>\r\n !s.success && i < this.traceBuffer.length - 1 && this.traceBuffer[i + 1].success\r\n )\r\n const toolNames = new Set(this.traceBuffer.map(s => s.tool_name))\r\n const hasDiverseTools = toolNames.size >= 2\r\n\r\n return hasMultipleSteps && (hasErrorRecovery || hasDiverseTools)\r\n }\r\n\r\n private determineComplexity(): 'easy' | 'medium' | 'hard' {\r\n const stepCount = this.traceBuffer.length\r\n const toolCount = new Set(this.traceBuffer.map(s => s.tool_name)).size\r\n const hasErrors = this.traceBuffer.some(s => !s.success)\r\n\r\n if (stepCount <= 3 && toolCount <= 2 && !hasErrors) {\r\n return 'easy'\r\n }\r\n\r\n if (stepCount >= 10 || toolCount >= 4 || this.securityEvents.length > 0) {\r\n return 'hard'\r\n }\r\n\r\n return 'medium'\r\n }\r\n\r\n // =========================================================================\r\n // Model Management\r\n // =========================================================================\r\n\r\n /**\r\n * Get current model version\r\n */\r\n getCurrentModelVersion(): string | null {\r\n const manifest = this.loadManifest()\r\n return manifest?.latest || null\r\n }\r\n\r\n /**\r\n * Get model manifest\r\n */\r\n getModelManifest(): ModelManifest | null {\r\n return this.manifest || this.loadManifest()\r\n }\r\n\r\n private loadManifest(): ModelManifest | null {\r\n const manifestPath = join(this.modelsDir, 'manifest.json')\r\n\r\n if (!existsSync(manifestPath)) {\r\n return null\r\n }\r\n\r\n try {\r\n const content = readFileSync(manifestPath, 'utf-8')\r\n return JSON.parse(content) as ModelManifest\r\n } catch {\r\n return null\r\n }\r\n }\r\n\r\n /**\r\n * Get path to latest GGUF model\r\n */\r\n getLatestModelPath(): string | null {\r\n const latestPath = join(this.modelsDir, 'latest', 'sidekick.gguf')\r\n\r\n if (existsSync(latestPath)) {\r\n return latestPath\r\n }\r\n\r\n return null\r\n }\r\n\r\n /**\r\n * Get Ollama model name for sidekick\r\n */\r\n getOllamaModelName(): string {\r\n const settings = this.getSettings()\r\n return settings?.model_sync.ollama_model_name || 'bashgym-sidekick'\r\n }\r\n\r\n // =========================================================================\r\n // File Watching\r\n // =========================================================================\r\n\r\n private startWatching(): void {\r\n // Watch settings file\r\n const settingsPath = join(this.configDir, 'settings.json')\r\n if (existsSync(settingsPath)) {\r\n try {\r\n this.settingsWatcher = watch(settingsPath, (eventType) => {\r\n if (eventType === 'change') {\r\n const newSettings = this.loadSettings()\r\n if (newSettings) {\r\n this.settings = newSettings\r\n this.emit('settings:changed', newSettings)\r\n }\r\n }\r\n })\r\n } catch {\r\n // Watching may not be supported\r\n }\r\n }\r\n\r\n // Watch model manifest\r\n const manifestPath = join(this.modelsDir, 'manifest.json')\r\n if (existsSync(manifestPath)) {\r\n try {\r\n this.modelWatcher = watch(manifestPath, (eventType) => {\r\n if (eventType === 'change') {\r\n const oldVersion = this.manifest?.latest\r\n const newManifest = this.loadManifest()\r\n\r\n if (newManifest && newManifest.latest !== oldVersion) {\r\n this.manifest = newManifest\r\n this.emit('model:updated', newManifest.latest, newManifest)\r\n }\r\n }\r\n })\r\n } catch {\r\n // Watching may not be supported\r\n }\r\n }\r\n }\r\n\r\n stopWatching(): void {\r\n if (this.settingsWatcher) {\r\n this.settingsWatcher.close()\r\n this.settingsWatcher = null\r\n }\r\n\r\n if (this.modelWatcher) {\r\n this.modelWatcher.close()\r\n this.modelWatcher = null\r\n }\r\n }\r\n\r\n // =========================================================================\r\n // Status Management\r\n // =========================================================================\r\n\r\n private updateStatus(): void {\r\n const statusPath = join(this.statusDir, 'bashbros.json')\r\n\r\n const status = {\r\n heartbeat: new Date().toISOString(),\r\n version: '1.0',\r\n session_id: this.sessionId,\r\n active: true,\r\n }\r\n\r\n try {\r\n if (!existsSync(this.statusDir)) {\r\n mkdirSync(this.statusDir, { recursive: true })\r\n }\r\n writeFileSync(statusPath, JSON.stringify(status, null, 2))\r\n } catch {\r\n // Status update failed - non-critical\r\n }\r\n }\r\n\r\n /**\r\n * Check if bashgym is actively running\r\n */\r\n isBashgymRunning(): boolean {\r\n const statusPath = join(this.statusDir, 'bashgym.json')\r\n\r\n if (!existsSync(statusPath)) {\r\n return false\r\n }\r\n\r\n try {\r\n const content = readFileSync(statusPath, 'utf-8')\r\n const status = JSON.parse(content) as BashgymStatus\r\n\r\n // Check if heartbeat is recent (within 5 minutes)\r\n const heartbeat = new Date(status.heartbeat)\r\n const age = Date.now() - heartbeat.getTime()\r\n\r\n return age < 5 * 60 * 1000\r\n } catch {\r\n return false\r\n }\r\n }\r\n\r\n // =========================================================================\r\n // Cleanup\r\n // =========================================================================\r\n\r\n dispose(): void {\r\n this.stopWatching()\r\n this.emit('disconnected')\r\n }\r\n}\r\n\r\n// ============================================================================\r\n// Singleton Instance\r\n// ============================================================================\r\n\r\nlet _integration: BashgymIntegration | null = null\r\n\r\nexport function getBashgymIntegration(): BashgymIntegration {\r\n if (!_integration) {\r\n _integration = new BashgymIntegration()\r\n }\r\n return _integration\r\n}\r\n\r\nexport function resetBashgymIntegration(): void {\r\n if (_integration) {\r\n _integration.dispose()\r\n }\r\n _integration = null\r\n}\r\n","/**\r\n * Claude Code Hook Integration\r\n * Seamlessly integrate BashBros with Claude Code\r\n */\r\n\r\nimport { existsSync, readFileSync, writeFileSync, mkdirSync } from 'fs'\r\nimport { join } from 'path'\r\nimport { homedir } from 'os'\r\n\r\nexport interface ClaudeSettings {\r\n hooks?: {\r\n PreToolUse?: HookConfig[]\r\n PostToolUse?: HookConfig[]\r\n SessionEnd?: HookConfig[]\r\n }\r\n [key: string]: unknown\r\n}\r\n\r\ninterface HookConfig {\r\n matcher?: string\r\n hooks: { type: string; command: string }[]\r\n}\r\n\r\nconst CLAUDE_SETTINGS_PATH = join(homedir(), '.claude', 'settings.json')\r\nconst CLAUDE_DIR = join(homedir(), '.claude')\r\n\r\nconst BASHBROS_HOOK_MARKER = '# bashbros-managed'\r\n\r\nexport class ClaudeCodeHooks {\r\n /**\r\n * Check if Claude Code is installed\r\n */\r\n static isClaudeInstalled(): boolean {\r\n return existsSync(CLAUDE_DIR)\r\n }\r\n\r\n /**\r\n * Load current Claude settings\r\n */\r\n static loadSettings(): ClaudeSettings {\r\n if (!existsSync(CLAUDE_SETTINGS_PATH)) {\r\n return {}\r\n }\r\n\r\n try {\r\n const content = readFileSync(CLAUDE_SETTINGS_PATH, 'utf-8')\r\n return JSON.parse(content)\r\n } catch {\r\n return {}\r\n }\r\n }\r\n\r\n /**\r\n * Save Claude settings\r\n */\r\n static saveSettings(settings: ClaudeSettings): void {\r\n if (!existsSync(CLAUDE_DIR)) {\r\n mkdirSync(CLAUDE_DIR, { recursive: true })\r\n }\r\n\r\n writeFileSync(\r\n CLAUDE_SETTINGS_PATH,\r\n JSON.stringify(settings, null, 2),\r\n 'utf-8'\r\n )\r\n }\r\n\r\n /**\r\n * Install BashBros hooks into Claude Code\r\n */\r\n static install(): { success: boolean; message: string } {\r\n if (!this.isClaudeInstalled()) {\r\n return {\r\n success: false,\r\n message: 'Claude Code not found. Install Claude Code first.'\r\n }\r\n }\r\n\r\n const settings = this.loadSettings()\r\n\r\n // Initialize hooks if not present\r\n if (!settings.hooks) {\r\n settings.hooks = {}\r\n }\r\n\r\n // Check if already installed\r\n if (this.isInstalled(settings)) {\r\n return {\r\n success: true,\r\n message: 'BashBros hooks already installed.'\r\n }\r\n }\r\n\r\n // Add PreToolUse hook for Bash commands\r\n const preToolUseHook: HookConfig = {\r\n matcher: 'Bash',\r\n hooks: [{\r\n type: 'command',\r\n command: `bashbros gate \"$TOOL_INPUT\" ${BASHBROS_HOOK_MARKER}`\r\n }]\r\n }\r\n\r\n // Add PostToolUse hook for metrics\r\n const postToolUseHook: HookConfig = {\r\n matcher: 'Bash',\r\n hooks: [{\r\n type: 'command',\r\n command: `bashbros record \"$TOOL_INPUT\" \"$TOOL_OUTPUT\" ${BASHBROS_HOOK_MARKER}`\r\n }]\r\n }\r\n\r\n // Add SessionEnd hook for reports\r\n const sessionEndHook: HookConfig = {\r\n hooks: [{\r\n type: 'command',\r\n command: `bashbros session-end ${BASHBROS_HOOK_MARKER}`\r\n }]\r\n }\r\n\r\n // Merge with existing hooks\r\n settings.hooks.PreToolUse = [\r\n ...(settings.hooks.PreToolUse || []),\r\n preToolUseHook\r\n ]\r\n\r\n settings.hooks.PostToolUse = [\r\n ...(settings.hooks.PostToolUse || []),\r\n postToolUseHook\r\n ]\r\n\r\n settings.hooks.SessionEnd = [\r\n ...(settings.hooks.SessionEnd || []),\r\n sessionEndHook\r\n ]\r\n\r\n this.saveSettings(settings)\r\n\r\n return {\r\n success: true,\r\n message: 'BashBros hooks installed successfully.'\r\n }\r\n }\r\n\r\n /**\r\n * Uninstall BashBros hooks from Claude Code\r\n */\r\n static uninstall(): { success: boolean; message: string } {\r\n if (!this.isClaudeInstalled()) {\r\n return {\r\n success: false,\r\n message: 'Claude Code not found.'\r\n }\r\n }\r\n\r\n const settings = this.loadSettings()\r\n\r\n if (!settings.hooks) {\r\n return {\r\n success: true,\r\n message: 'No hooks to uninstall.'\r\n }\r\n }\r\n\r\n // Remove BashBros hooks\r\n const filterHooks = (hooks: HookConfig[] | undefined): HookConfig[] => {\r\n if (!hooks) return []\r\n return hooks.filter(h =>\r\n !h.hooks.some(hook => hook.command.includes(BASHBROS_HOOK_MARKER))\r\n )\r\n }\r\n\r\n settings.hooks.PreToolUse = filterHooks(settings.hooks.PreToolUse)\r\n settings.hooks.PostToolUse = filterHooks(settings.hooks.PostToolUse)\r\n settings.hooks.SessionEnd = filterHooks(settings.hooks.SessionEnd)\r\n\r\n // Clean up empty arrays\r\n if (settings.hooks.PreToolUse?.length === 0) delete settings.hooks.PreToolUse\r\n if (settings.hooks.PostToolUse?.length === 0) delete settings.hooks.PostToolUse\r\n if (settings.hooks.SessionEnd?.length === 0) delete settings.hooks.SessionEnd\r\n if (Object.keys(settings.hooks).length === 0) delete settings.hooks\r\n\r\n this.saveSettings(settings)\r\n\r\n return {\r\n success: true,\r\n message: 'BashBros hooks uninstalled successfully.'\r\n }\r\n }\r\n\r\n /**\r\n * Check if BashBros hooks are installed\r\n */\r\n static isInstalled(settings?: ClaudeSettings): boolean {\r\n const s = settings || this.loadSettings()\r\n\r\n if (!s.hooks) return false\r\n\r\n const hasMarker = (hooks: HookConfig[] | undefined): boolean => {\r\n if (!hooks) return false\r\n return hooks.some(h =>\r\n h.hooks.some(hook => hook.command.includes(BASHBROS_HOOK_MARKER))\r\n )\r\n }\r\n\r\n return hasMarker(s.hooks.PreToolUse) ||\r\n hasMarker(s.hooks.PostToolUse) ||\r\n hasMarker(s.hooks.SessionEnd)\r\n }\r\n\r\n /**\r\n * Get hook status\r\n */\r\n static getStatus(): {\r\n claudeInstalled: boolean\r\n hooksInstalled: boolean\r\n hooks: string[]\r\n } {\r\n const claudeInstalled = this.isClaudeInstalled()\r\n const settings = claudeInstalled ? this.loadSettings() : {}\r\n const hooksInstalled = this.isInstalled(settings)\r\n\r\n const hooks: string[] = []\r\n if (settings.hooks?.PreToolUse) hooks.push('PreToolUse (gate)')\r\n if (settings.hooks?.PostToolUse) hooks.push('PostToolUse (record)')\r\n if (settings.hooks?.SessionEnd) hooks.push('SessionEnd (report)')\r\n\r\n return {\r\n claudeInstalled,\r\n hooksInstalled,\r\n hooks\r\n }\r\n }\r\n}\r\n\r\n/**\r\n * Gate command - called by PreToolUse hook\r\n * Returns exit code 0 to allow, non-zero to block\r\n */\r\nexport async function gateCommand(command: string): Promise<{\r\n allowed: boolean\r\n reason?: string\r\n riskScore?: number\r\n}> {\r\n // Dynamic import to avoid circular deps\r\n const { PolicyEngine } = await import('../policy/engine.js')\r\n const { RiskScorer } = await import('../policy/risk-scorer.js')\r\n const { loadConfig } = await import('../config.js')\r\n\r\n const config = loadConfig()\r\n const engine = new PolicyEngine(config)\r\n const scorer = new RiskScorer()\r\n\r\n const violations = engine.validate(command)\r\n const risk = scorer.score(command)\r\n\r\n if (violations.length > 0) {\r\n return {\r\n allowed: false,\r\n reason: violations[0].message,\r\n riskScore: risk.score\r\n }\r\n }\r\n\r\n // Block critical risk commands\r\n if (risk.level === 'critical') {\r\n return {\r\n allowed: false,\r\n reason: `Critical risk: ${risk.factors.join(', ')}`,\r\n riskScore: risk.score\r\n }\r\n }\r\n\r\n return {\r\n allowed: true,\r\n riskScore: risk.score\r\n }\r\n}\r\n","import * as pty from 'node-pty'\r\nimport { EventEmitter } from 'events'\r\nimport type { BashBrosConfig, CommandResult, PolicyViolation } from './types.js'\r\nimport { PolicyEngine } from './policy/engine.js'\r\nimport { AuditLogger } from './audit.js'\r\nimport { loadConfig } from './config.js'\r\n\r\nexport interface BashBrosEvents {\r\n command: (command: string) => void\r\n allowed: (result: CommandResult) => void\r\n blocked: (command: string, violations: PolicyViolation[]) => void\r\n output: (data: string) => void\r\n error: (error: Error) => void\r\n}\r\n\r\nexport class BashBros extends EventEmitter {\r\n private config: BashBrosConfig\r\n private policy: PolicyEngine\r\n private audit: AuditLogger\r\n private ptyProcess: pty.IPty | null = null\r\n private shell: string\r\n private pendingCommand: string = ''\r\n private commandStartTime: number = 0\r\n\r\n constructor(configPath?: string) {\r\n super()\r\n this.config = loadConfig(configPath)\r\n this.policy = new PolicyEngine(this.config)\r\n this.audit = new AuditLogger(this.config.audit)\r\n this.shell = process.platform === 'win32' ? 'powershell.exe' : 'bash'\r\n }\r\n\r\n start(): void {\r\n this.ptyProcess = pty.spawn(this.shell, [], {\r\n name: 'xterm-color',\r\n cols: 80,\r\n rows: 30,\r\n cwd: process.cwd(),\r\n env: process.env as { [key: string]: string }\r\n })\r\n\r\n this.ptyProcess.onData((data: string) => {\r\n this.emit('output', data)\r\n })\r\n\r\n this.ptyProcess.onExit(({ exitCode }) => {\r\n this.emit('exit', exitCode)\r\n })\r\n }\r\n\r\n execute(command: string): CommandResult {\r\n const startTime = Date.now()\r\n const violations = this.policy.validate(command)\r\n\r\n if (violations.length > 0) {\r\n const result: CommandResult = {\r\n command,\r\n allowed: false,\r\n duration: Date.now() - startTime,\r\n violations\r\n }\r\n\r\n this.audit.log({\r\n timestamp: new Date(),\r\n command,\r\n allowed: false,\r\n violations,\r\n duration: result.duration,\r\n agent: this.config.agent\r\n })\r\n\r\n this.emit('blocked', command, violations)\r\n return result\r\n }\r\n\r\n // Command is allowed - execute it\r\n this.commandStartTime = startTime\r\n this.pendingCommand = command\r\n\r\n if (this.ptyProcess) {\r\n this.ptyProcess.write(command + '\\r')\r\n }\r\n\r\n const result: CommandResult = {\r\n command,\r\n allowed: true,\r\n duration: Date.now() - startTime,\r\n violations: []\r\n }\r\n\r\n this.audit.log({\r\n timestamp: new Date(),\r\n command,\r\n allowed: true,\r\n violations: [],\r\n duration: result.duration,\r\n agent: this.config.agent\r\n })\r\n\r\n this.emit('allowed', result)\r\n return result\r\n }\r\n\r\n validateOnly(command: string): PolicyViolation[] {\r\n return this.policy.validate(command)\r\n }\r\n\r\n isAllowed(command: string): boolean {\r\n return this.policy.isAllowed(command)\r\n }\r\n\r\n resize(cols: number, rows: number): void {\r\n if (this.ptyProcess) {\r\n this.ptyProcess.resize(cols, rows)\r\n }\r\n }\r\n\r\n write(data: string): void {\r\n if (this.ptyProcess) {\r\n this.ptyProcess.write(data)\r\n }\r\n }\r\n\r\n stop(): void {\r\n if (this.ptyProcess) {\r\n this.ptyProcess.kill()\r\n this.ptyProcess = null\r\n }\r\n }\r\n\r\n getConfig(): BashBrosConfig {\r\n return this.config\r\n }\r\n}\r\n","import { execFileSync, execSync } from 'child_process'\nimport { existsSync, readFileSync, realpathSync } from 'fs'\nimport { homedir, platform, arch, cpus, totalmem } from 'os'\nimport { join } from 'path'\n\nexport interface SystemProfile {\n // System basics\n platform: string\n arch: string\n shell: string\n cpuCores: number\n memoryGB: number\n\n // Languages & runtimes\n python: VersionInfo | null\n node: VersionInfo | null\n rust: VersionInfo | null\n go: VersionInfo | null\n java: VersionInfo | null\n ruby: VersionInfo | null\n\n // Package managers\n npm: VersionInfo | null\n pnpm: VersionInfo | null\n yarn: VersionInfo | null\n pip: VersionInfo | null\n cargo: VersionInfo | null\n brew: VersionInfo | null\n\n // Dev tools\n git: VersionInfo | null\n docker: VersionInfo | null\n kubectl: VersionInfo | null\n aws: VersionInfo | null\n gcloud: VersionInfo | null\n\n // AI tools\n claude: boolean\n clawdbot: boolean\n aider: boolean\n ollama: OllamaInfo | null\n\n // Project context (updated per-project)\n projectType: string | null\n projectDeps: string[]\n envVars: string[] // Names only, not values\n\n // User patterns (learned over time)\n commonCommands: CommandPattern[]\n workingHours: string | null\n preferredEditor: string | null\n\n // Last updated\n timestamp: Date\n}\n\nexport interface VersionInfo {\n version: string\n path: string\n}\n\nexport interface OllamaInfo {\n version: string\n models: string[]\n}\n\nexport interface CommandPattern {\n command: string\n frequency: number\n lastUsed: Date\n}\n\n// Allowlist of safe commands to probe\nconst SAFE_VERSION_COMMANDS: Record<string, string[]> = {\n python: ['--version'],\n python3: ['--version'],\n node: ['--version'],\n rustc: ['--version'],\n go: ['version'],\n java: ['-version'],\n ruby: ['--version'],\n npm: ['--version'],\n pnpm: ['--version'],\n yarn: ['--version'],\n pip: ['--version'],\n pip3: ['--version'],\n cargo: ['--version'],\n brew: ['--version'],\n git: ['--version'],\n docker: ['--version'],\n kubectl: ['version', '--client', '--short'],\n aws: ['--version'],\n gcloud: ['--version'],\n ollama: ['--version'],\n code: ['--version'],\n cursor: ['--version'],\n vim: ['--version'],\n nvim: ['--version'],\n nano: ['--version'],\n emacs: ['--version']\n}\n\nexport class SystemProfiler {\n private profile: SystemProfile | null = null\n private profilePath: string\n\n constructor() {\n this.profilePath = join(homedir(), '.bashbros', 'system-profile.json')\n }\n\n async scan(): Promise<SystemProfile> {\n const profile: SystemProfile = {\n platform: platform(),\n arch: arch(),\n shell: this.detectShell(),\n cpuCores: cpus().length,\n memoryGB: Math.round(totalmem() / (1024 ** 3)),\n\n python: this.getVersionSafe('python') || this.getVersionSafe('python3'),\n node: this.getVersionSafe('node'),\n rust: this.getVersionSafe('rustc'),\n go: this.getVersionSafe('go'),\n java: this.getVersionSafe('java'),\n ruby: this.getVersionSafe('ruby'),\n\n npm: this.getVersionSafe('npm'),\n pnpm: this.getVersionSafe('pnpm'),\n yarn: this.getVersionSafe('yarn'),\n pip: this.getVersionSafe('pip') || this.getVersionSafe('pip3'),\n cargo: this.getVersionSafe('cargo'),\n brew: this.getVersionSafe('brew'),\n\n git: this.getVersionSafe('git'),\n docker: this.getVersionSafe('docker'),\n kubectl: this.getVersionSafe('kubectl'),\n aws: this.getVersionSafe('aws'),\n gcloud: this.getVersionSafe('gcloud'),\n\n claude: this.commandExists('claude'),\n clawdbot: this.commandExists('clawdbot'),\n aider: this.commandExists('aider'),\n ollama: this.getOllamaInfo(),\n\n projectType: null,\n projectDeps: [],\n envVars: this.getEnvVarNames(),\n\n commonCommands: [],\n workingHours: null,\n preferredEditor: this.detectEditor(),\n\n timestamp: new Date()\n }\n\n this.profile = profile\n this.save()\n\n return profile\n }\n\n scanProject(projectPath: string): Partial<SystemProfile> {\n // SECURITY: Resolve symlinks and validate path\n let resolvedPath: string\n try {\n resolvedPath = realpathSync(projectPath)\n } catch {\n resolvedPath = projectPath\n }\n\n const updates: Partial<SystemProfile> = {\n projectType: this.detectProjectType(resolvedPath),\n projectDeps: this.detectDependencies(resolvedPath)\n }\n\n if (this.profile) {\n this.profile = { ...this.profile, ...updates }\n this.save()\n }\n\n return updates\n }\n\n private detectShell(): string {\n if (platform() === 'win32') {\n return process.env.COMSPEC || 'cmd.exe'\n }\n return process.env.SHELL || '/bin/bash'\n }\n\n /**\n * SECURITY FIX: Use execFileSync with array args instead of string concatenation\n */\n private getVersionSafe(cmd: string): VersionInfo | null {\n const args = SAFE_VERSION_COMMANDS[cmd]\n if (!args) {\n return null // Only allow whitelisted commands\n }\n\n try {\n // SECURITY: Use execFileSync with explicit args array\n const output = execFileSync(cmd, args, {\n encoding: 'utf-8',\n timeout: 5000,\n stdio: ['pipe', 'pipe', 'pipe'],\n windowsHide: true\n }).trim()\n\n const version = this.parseVersion(output)\n const path = this.getCommandPathSafe(cmd)\n\n return { version, path }\n } catch {\n return null\n }\n }\n\n private parseVersion(output: string): string {\n // Extract version number from various formats\n const match = output.match(/(\\d+\\.\\d+(?:\\.\\d+)?(?:-[\\w.]+)?)/i)\n return match ? match[1] : output.split('\\n')[0].slice(0, 50)\n }\n\n /**\n * SECURITY FIX: Use execFileSync for which/where command\n */\n private getCommandPathSafe(cmd: string): string {\n try {\n const whichCmd = platform() === 'win32' ? 'where' : 'which'\n // SECURITY: Use execFileSync with array args\n const result = execFileSync(whichCmd, [cmd], {\n encoding: 'utf-8',\n timeout: 3000,\n stdio: ['pipe', 'pipe', 'pipe'],\n windowsHide: true\n }).trim().split('\\n')[0]\n\n return result\n } catch {\n return cmd\n }\n }\n\n private commandExists(cmd: string): boolean {\n try {\n const whichCmd = platform() === 'win32' ? 'where' : 'which'\n // SECURITY: Use execFileSync with array args\n execFileSync(whichCmd, [cmd], {\n stdio: 'pipe',\n timeout: 3000,\n windowsHide: true\n })\n return true\n } catch {\n return false\n }\n }\n\n private getOllamaInfo(): OllamaInfo | null {\n try {\n // SECURITY: Use execFileSync with array args\n const version = execFileSync('ollama', ['--version'], {\n encoding: 'utf-8',\n timeout: 5000,\n windowsHide: true\n }).trim()\n\n let models: string[] = []\n try {\n const modelList = execFileSync('ollama', ['list'], {\n encoding: 'utf-8',\n timeout: 10000,\n windowsHide: true\n })\n models = modelList\n .split('\\n')\n .slice(1) // Skip header\n .map(line => line.split(/\\s+/)[0])\n .filter(Boolean)\n } catch {\n // Ollama might not have models or not be running\n }\n\n return { version, models }\n } catch {\n return null\n }\n }\n\n private getEnvVarNames(): string[] {\n // Return environment variable names (not values) for context\n // Only include safe, non-sensitive variable names\n const safePatterns = [\n /^PATH$/i,\n /^HOME$/i,\n /^USER$/i,\n /^SHELL$/i,\n /^TERM$/i,\n /^LANG$/i,\n /^NODE_VERSION$/i,\n /^PYTHON.*VERSION$/i,\n /^JAVA_HOME$/i,\n /^GOPATH$/i,\n /^EDITOR$/i,\n /^VISUAL$/i\n ]\n\n return Object.keys(process.env).filter(key =>\n safePatterns.some(pattern => pattern.test(key))\n )\n }\n\n private detectEditor(): string | null {\n const editor = process.env.EDITOR || process.env.VISUAL\n\n if (editor) return editor\n\n // Check for common editors\n const editors = ['code', 'cursor', 'vim', 'nvim', 'nano', 'emacs']\n for (const ed of editors) {\n if (this.commandExists(ed)) return ed\n }\n\n return null\n }\n\n private detectProjectType(projectPath: string): string | null {\n const checks: [string, string][] = [\n ['package.json', 'node'],\n ['pyproject.toml', 'python'],\n ['requirements.txt', 'python'],\n ['Cargo.toml', 'rust'],\n ['go.mod', 'go'],\n ['pom.xml', 'java'],\n ['build.gradle', 'java'],\n ['Gemfile', 'ruby'],\n ['composer.json', 'php']\n ]\n\n for (const [file, type] of checks) {\n const filePath = join(projectPath, file)\n // SECURITY: Check file exists without following symlinks first\n if (existsSync(filePath)) {\n try {\n // Verify it resolves to expected location\n const realPath = realpathSync(filePath)\n if (realPath.startsWith(realpathSync(projectPath))) {\n return type\n }\n } catch {\n // Skip if can't resolve\n }\n }\n }\n\n return null\n }\n\n private detectDependencies(projectPath: string): string[] {\n const deps: string[] = []\n\n // Check package.json\n const pkgPath = join(projectPath, 'package.json')\n if (existsSync(pkgPath)) {\n try {\n // SECURITY: Verify path resolves within project\n const realPkgPath = realpathSync(pkgPath)\n if (realPkgPath.startsWith(realpathSync(projectPath))) {\n const pkg = JSON.parse(readFileSync(realPkgPath, 'utf-8'))\n deps.push(...Object.keys(pkg.dependencies || {}))\n deps.push(...Object.keys(pkg.devDependencies || {}))\n }\n } catch { /* ignore */ }\n }\n\n // Check requirements.txt\n const reqPath = join(projectPath, 'requirements.txt')\n if (existsSync(reqPath)) {\n try {\n // SECURITY: Verify path resolves within project\n const realReqPath = realpathSync(reqPath)\n if (realReqPath.startsWith(realpathSync(projectPath))) {\n const reqs = readFileSync(realReqPath, 'utf-8')\n const packages = reqs.split('\\n')\n .map(line => line.split(/[=<>]/)[0].trim())\n .filter(Boolean)\n deps.push(...packages)\n }\n } catch { /* ignore */ }\n }\n\n return deps.slice(0, 100) // Limit to top 100\n }\n\n load(): SystemProfile | null {\n if (existsSync(this.profilePath)) {\n try {\n const data = readFileSync(this.profilePath, 'utf-8')\n this.profile = JSON.parse(data)\n return this.profile\n } catch {\n return null\n }\n }\n return null\n }\n\n private save(): void {\n try {\n const { writeFileSync, mkdirSync, chmodSync } = require('fs')\n const dir = join(homedir(), '.bashbros')\n if (!existsSync(dir)) {\n mkdirSync(dir, { recursive: true, mode: 0o700 }) // SECURITY: Restrict directory permissions\n }\n const filePath = this.profilePath\n writeFileSync(filePath, JSON.stringify(this.profile, null, 2))\n\n // SECURITY: Restrict file permissions (owner read/write only)\n try {\n chmodSync(filePath, 0o600)\n } catch {\n // Windows doesn't support chmod the same way\n }\n } catch { /* ignore */ }\n }\n\n get(): SystemProfile | null {\n return this.profile\n }\n\n toContext(): string {\n if (!this.profile) return 'System profile not available.'\n\n const p = this.profile\n const lines: string[] = [\n `## System Context`,\n `- Platform: ${p.platform} (${p.arch})`,\n `- Shell: ${p.shell}`,\n `- CPU: ${p.cpuCores} cores, RAM: ${p.memoryGB}GB`,\n ''\n ]\n\n if (p.python) lines.push(`- Python: ${p.python.version}`)\n if (p.node) lines.push(`- Node: ${p.node.version}`)\n if (p.rust) lines.push(`- Rust: ${p.rust.version}`)\n if (p.go) lines.push(`- Go: ${p.go.version}`)\n\n if (p.git) lines.push(`- Git: ${p.git.version}`)\n if (p.docker) lines.push(`- Docker: ${p.docker.version}`)\n\n if (p.ollama) {\n lines.push(`- Ollama: ${p.ollama.version}`)\n if (p.ollama.models.length > 0) {\n lines.push(` Models: ${p.ollama.models.join(', ')}`)\n }\n }\n\n if (p.projectType) {\n lines.push('')\n lines.push(`## Project: ${p.projectType}`)\n if (p.projectDeps.length > 0) {\n lines.push(`Dependencies: ${p.projectDeps.slice(0, 20).join(', ')}`)\n }\n }\n\n return lines.join('\\n')\n }\n}\n","import type { SystemProfile } from './profiler.js'\r\n\r\nexport type RouteDecision = 'bro' | 'main' | 'both'\r\n\r\nexport interface RoutingRule {\r\n pattern: RegExp\r\n route: RouteDecision\r\n reason: string\r\n}\r\n\r\nexport interface RoutingResult {\r\n decision: RouteDecision\r\n reason: string\r\n confidence: number\r\n}\r\n\r\nexport class TaskRouter {\r\n private rules: RoutingRule[]\r\n private profile: SystemProfile | null\r\n\r\n constructor(profile: SystemProfile | null = null) {\r\n this.profile = profile\r\n this.rules = this.buildDefaultRules()\r\n }\r\n\r\n private buildDefaultRules(): RoutingRule[] {\r\n return [\r\n // Simple file operations → Bash Bro\r\n { pattern: /^ls\\b/, route: 'bro', reason: 'Simple file listing' },\r\n { pattern: /^cat\\s+\\S+$/, route: 'bro', reason: 'Simple file read' },\r\n { pattern: /^head\\b/, route: 'bro', reason: 'File head' },\r\n { pattern: /^tail\\b/, route: 'bro', reason: 'File tail' },\r\n { pattern: /^wc\\b/, route: 'bro', reason: 'Word count' },\r\n { pattern: /^pwd$/, route: 'bro', reason: 'Print directory' },\r\n { pattern: /^cd\\s+/, route: 'bro', reason: 'Change directory' },\r\n { pattern: /^mkdir\\s+/, route: 'bro', reason: 'Create directory' },\r\n { pattern: /^touch\\s+/, route: 'bro', reason: 'Create file' },\r\n { pattern: /^cp\\s+/, route: 'bro', reason: 'Copy file' },\r\n { pattern: /^mv\\s+/, route: 'bro', reason: 'Move file' },\r\n { pattern: /^rm\\s+(?!-rf)/, route: 'bro', reason: 'Remove file (safe)' },\r\n\r\n // Simple searches → Bash Bro\r\n { pattern: /^grep\\s+-[ril]*\\s+['\"]?\\w+['\"]?\\s+\\S+$/, route: 'bro', reason: 'Simple grep' },\r\n { pattern: /^find\\s+\\.\\s+-name\\s+/, route: 'bro', reason: 'Simple find' },\r\n { pattern: /^which\\s+/, route: 'bro', reason: 'Which command' },\r\n\r\n // Git simple operations → Bash Bro\r\n { pattern: /^git\\s+status$/, route: 'bro', reason: 'Git status' },\r\n { pattern: /^git\\s+branch$/, route: 'bro', reason: 'Git branch list' },\r\n { pattern: /^git\\s+log\\s+--oneline/, route: 'bro', reason: 'Git log' },\r\n { pattern: /^git\\s+diff$/, route: 'bro', reason: 'Git diff' },\r\n { pattern: /^git\\s+add\\s+/, route: 'bro', reason: 'Git add' },\r\n\r\n // Package info → Bash Bro\r\n { pattern: /^npm\\s+list/, route: 'bro', reason: 'NPM list' },\r\n { pattern: /^pip\\s+list/, route: 'bro', reason: 'Pip list' },\r\n { pattern: /^pip\\s+show\\s+/, route: 'bro', reason: 'Pip show' },\r\n\r\n // Environment checks → Bash Bro\r\n { pattern: /^python\\s+--version/, route: 'bro', reason: 'Python version' },\r\n { pattern: /^node\\s+--version/, route: 'bro', reason: 'Node version' },\r\n { pattern: /^npm\\s+--version/, route: 'bro', reason: 'NPM version' },\r\n { pattern: /^env$/, route: 'bro', reason: 'Environment vars' },\r\n { pattern: /^echo\\s+\\$\\w+$/, route: 'bro', reason: 'Echo env var' },\r\n\r\n // Complex operations → Main agent\r\n { pattern: /refactor/i, route: 'main', reason: 'Refactoring requires reasoning' },\r\n { pattern: /implement/i, route: 'main', reason: 'Implementation requires reasoning' },\r\n { pattern: /explain/i, route: 'main', reason: 'Explanation requires reasoning' },\r\n { pattern: /debug/i, route: 'main', reason: 'Debugging requires reasoning' },\r\n { pattern: /fix\\s+/i, route: 'main', reason: 'Fixing requires reasoning' },\r\n { pattern: /why/i, route: 'main', reason: 'Explanation required' },\r\n { pattern: /how\\s+(do|can|should)/i, route: 'main', reason: 'Guidance required' },\r\n\r\n // Git complex → Main agent\r\n { pattern: /^git\\s+rebase/, route: 'main', reason: 'Rebase needs oversight' },\r\n { pattern: /^git\\s+merge/, route: 'main', reason: 'Merge needs oversight' },\r\n { pattern: /^git\\s+reset/, route: 'main', reason: 'Reset needs oversight' },\r\n\r\n // Parallel tasks → Both\r\n { pattern: /^(npm|yarn|pnpm)\\s+(test|run\\s+test)/, route: 'both', reason: 'Tests can run in background' },\r\n { pattern: /^pytest/, route: 'both', reason: 'Tests can run in background' },\r\n { pattern: /^(npm|yarn|pnpm)\\s+run\\s+build/, route: 'both', reason: 'Build can run in background' },\r\n { pattern: /^docker\\s+build/, route: 'both', reason: 'Docker build can run in background' },\r\n ]\r\n }\r\n\r\n route(command: string): RoutingResult {\r\n // Check rules in order\r\n for (const rule of this.rules) {\r\n if (rule.pattern.test(command)) {\r\n return {\r\n decision: rule.route,\r\n reason: rule.reason,\r\n confidence: 0.9\r\n }\r\n }\r\n }\r\n\r\n // Default: if it looks simple, route to bro\r\n if (this.looksSimple(command)) {\r\n return {\r\n decision: 'bro',\r\n reason: 'Appears to be a simple command',\r\n confidence: 0.6\r\n }\r\n }\r\n\r\n // Default to main agent for complex/unknown\r\n return {\r\n decision: 'main',\r\n reason: 'Complex or unknown command',\r\n confidence: 0.5\r\n }\r\n }\r\n\r\n private looksSimple(command: string): boolean {\r\n // Heuristics for simple commands\r\n const words = command.split(/\\s+/)\r\n\r\n // Very short commands are usually simple\r\n if (words.length <= 3) return true\r\n\r\n // No pipes, redirects, or logic operators\r\n if (/[|><&;]/.test(command)) return false\r\n\r\n // No subshells\r\n if (/[$`(]/.test(command)) return false\r\n\r\n return true\r\n }\r\n\r\n addRule(pattern: RegExp, route: RouteDecision, reason: string): void {\r\n this.rules.unshift({ pattern, route, reason }) // Add to front for priority\r\n }\r\n\r\n updateProfile(profile: SystemProfile): void {\r\n this.profile = profile\r\n\r\n // Add project-specific rules based on profile\r\n if (profile.projectType === 'python') {\r\n this.addRule(/^python\\s+-c\\s+/, 'bro', 'Simple Python one-liner')\r\n this.addRule(/^pip\\s+install\\s+/, 'bro', 'Pip install')\r\n }\r\n\r\n if (profile.projectType === 'node') {\r\n this.addRule(/^npx\\s+/, 'bro', 'NPX command')\r\n this.addRule(/^npm\\s+install\\s+/, 'bro', 'NPM install')\r\n }\r\n }\r\n}\r\n","import type { SystemProfile } from './profiler.js'\r\nimport type { AuditEntry } from '../types.js'\r\n\r\nexport interface Suggestion {\r\n command: string\r\n description: string\r\n confidence: number\r\n source: 'pattern' | 'history' | 'context' | 'model'\r\n}\r\n\r\nexport class CommandSuggester {\r\n private history: AuditEntry[] = []\r\n private profile: SystemProfile | null = null\r\n private patterns: Map<string, string[]> = new Map()\r\n\r\n constructor(profile: SystemProfile | null = null) {\r\n this.profile = profile\r\n this.initPatterns()\r\n }\r\n\r\n private initPatterns(): void {\r\n // Common command sequences\r\n this.patterns.set('git status', ['git add .', 'git diff', 'git stash'])\r\n this.patterns.set('git add', ['git commit -m \"\"', 'git status'])\r\n this.patterns.set('git commit', ['git push', 'git log --oneline -5'])\r\n this.patterns.set('git pull', ['git status', 'git log --oneline -5'])\r\n this.patterns.set('git checkout', ['git status', 'git branch'])\r\n\r\n this.patterns.set('npm install', ['npm run build', 'npm test', 'npm start'])\r\n this.patterns.set('npm test', ['npm run build', 'git add .'])\r\n this.patterns.set('npm run build', ['npm start', 'npm test'])\r\n\r\n this.patterns.set('pip install', ['pip freeze', 'python -m pytest'])\r\n this.patterns.set('pytest', ['git add .', 'python -m pytest -v'])\r\n\r\n this.patterns.set('docker build', ['docker run', 'docker images'])\r\n this.patterns.set('docker run', ['docker ps', 'docker logs'])\r\n\r\n this.patterns.set('cd', ['ls', 'ls -la', 'git status'])\r\n this.patterns.set('mkdir', ['cd', 'touch'])\r\n this.patterns.set('ls', ['cd', 'cat', 'vim'])\r\n }\r\n\r\n suggest(context: SuggestionContext): Suggestion[] {\r\n const suggestions: Suggestion[] = []\r\n\r\n // 1. Pattern-based suggestions\r\n if (context.lastCommand) {\r\n const patternSuggestions = this.suggestFromPatterns(context.lastCommand)\r\n suggestions.push(...patternSuggestions)\r\n }\r\n\r\n // 2. History-based suggestions\r\n const historySuggestions = this.suggestFromHistory(context)\r\n suggestions.push(...historySuggestions)\r\n\r\n // 3. Context-based suggestions\r\n const contextSuggestions = this.suggestFromContext(context)\r\n suggestions.push(...contextSuggestions)\r\n\r\n // Dedupe and sort by confidence\r\n const unique = this.dedupeAndRank(suggestions)\r\n\r\n return unique.slice(0, 5) // Top 5\r\n }\r\n\r\n private suggestFromPatterns(lastCommand: string): Suggestion[] {\r\n const suggestions: Suggestion[] = []\r\n\r\n // Find matching pattern key\r\n for (const [key, commands] of this.patterns) {\r\n if (lastCommand.startsWith(key)) {\r\n for (const cmd of commands) {\r\n suggestions.push({\r\n command: cmd,\r\n description: `Common follow-up to \"${key}\"`,\r\n confidence: 0.8,\r\n source: 'pattern'\r\n })\r\n }\r\n break\r\n }\r\n }\r\n\r\n return suggestions\r\n }\r\n\r\n private suggestFromHistory(context: SuggestionContext): Suggestion[] {\r\n if (this.history.length < 3) return []\r\n\r\n const suggestions: Suggestion[] = []\r\n\r\n // Find commands that often follow the current context\r\n const recentCommands = this.history.slice(-20)\r\n const following = new Map<string, number>()\r\n\r\n for (let i = 0; i < recentCommands.length - 1; i++) {\r\n const current = recentCommands[i].command\r\n const next = recentCommands[i + 1].command\r\n\r\n if (context.lastCommand && current.startsWith(context.lastCommand.split(' ')[0])) {\r\n const count = following.get(next) || 0\r\n following.set(next, count + 1)\r\n }\r\n }\r\n\r\n // Convert to suggestions\r\n for (const [cmd, count] of following) {\r\n if (count >= 2) {\r\n suggestions.push({\r\n command: cmd,\r\n description: 'Based on your history',\r\n confidence: Math.min(0.9, 0.5 + count * 0.1),\r\n source: 'history'\r\n })\r\n }\r\n }\r\n\r\n return suggestions\r\n }\r\n\r\n private suggestFromContext(context: SuggestionContext): Suggestion[] {\r\n const suggestions: Suggestion[] = []\r\n\r\n // Project-type specific suggestions\r\n if (context.projectType === 'node' && context.cwd) {\r\n if (context.files?.includes('package.json')) {\r\n suggestions.push({\r\n command: 'npm install',\r\n description: 'Install dependencies',\r\n confidence: 0.7,\r\n source: 'context'\r\n })\r\n }\r\n }\r\n\r\n if (context.projectType === 'python' && context.cwd) {\r\n if (context.files?.includes('requirements.txt')) {\r\n suggestions.push({\r\n command: 'pip install -r requirements.txt',\r\n description: 'Install dependencies',\r\n confidence: 0.7,\r\n source: 'context'\r\n })\r\n }\r\n }\r\n\r\n // Error-based suggestions\r\n if (context.lastError) {\r\n if (context.lastError.includes('ModuleNotFoundError')) {\r\n const match = context.lastError.match(/No module named '(\\w+)'/)\r\n if (match) {\r\n suggestions.push({\r\n command: `pip install ${match[1]}`,\r\n description: `Install missing module`,\r\n confidence: 0.9,\r\n source: 'context'\r\n })\r\n }\r\n }\r\n\r\n if (context.lastError.includes('Cannot find module')) {\r\n suggestions.push({\r\n command: 'npm install',\r\n description: 'Install missing dependencies',\r\n confidence: 0.85,\r\n source: 'context'\r\n })\r\n }\r\n }\r\n\r\n return suggestions\r\n }\r\n\r\n private dedupeAndRank(suggestions: Suggestion[]): Suggestion[] {\r\n const seen = new Set<string>()\r\n const unique: Suggestion[] = []\r\n\r\n // Sort by confidence first\r\n suggestions.sort((a, b) => b.confidence - a.confidence)\r\n\r\n for (const s of suggestions) {\r\n if (!seen.has(s.command)) {\r\n seen.add(s.command)\r\n unique.push(s)\r\n }\r\n }\r\n\r\n return unique\r\n }\r\n\r\n recordCommand(entry: AuditEntry): void {\r\n this.history.push(entry)\r\n // Keep last 100 commands\r\n if (this.history.length > 100) {\r\n this.history = this.history.slice(-100)\r\n }\r\n }\r\n\r\n updateProfile(profile: SystemProfile): void {\r\n this.profile = profile\r\n }\r\n}\r\n\r\nexport interface SuggestionContext {\r\n lastCommand?: string\r\n lastOutput?: string\r\n lastError?: string\r\n cwd?: string\r\n projectType?: string\r\n files?: string[]\r\n}\r\n","import { spawn, ChildProcess } from 'child_process'\nimport { EventEmitter } from 'events'\n\nexport interface BackgroundTask {\n id: string\n command: string\n status: 'running' | 'completed' | 'failed' | 'cancelled'\n startTime: Date\n endTime?: Date\n output: string[]\n exitCode?: number\n}\n\n// Maximum tasks to keep in history\nconst MAX_TASK_HISTORY = 100\n\n/**\n * Safely parse a command string into executable parts.\n * Prevents shell injection by NOT using shell: true\n */\nfunction parseCommand(command: string): { cmd: string; args: string[] } {\n // Handle quoted strings properly\n const tokens: string[] = []\n let current = ''\n let inQuote: string | null = null\n\n for (let i = 0; i < command.length; i++) {\n const char = command[i]\n\n if (inQuote) {\n if (char === inQuote) {\n inQuote = null\n } else {\n current += char\n }\n } else if (char === '\"' || char === \"'\") {\n inQuote = char\n } else if (char === ' ' || char === '\\t') {\n if (current) {\n tokens.push(current)\n current = ''\n }\n } else {\n current += char\n }\n }\n\n if (current) {\n tokens.push(current)\n }\n\n return {\n cmd: tokens[0] || '',\n args: tokens.slice(1)\n }\n}\n\n/**\n * Validate command doesn't contain dangerous shell metacharacters\n */\nfunction validateCommand(command: string): { valid: boolean; reason?: string } {\n // Block shell metacharacters that could enable injection\n const dangerousPatterns = [\n /[;&|`$]/, // Shell operators and command substitution\n /\\$\\(/, // Command substitution\n />\\s*>/, // Append redirect\n />\\s*\\//, // Redirect to absolute path\n /<\\s*\\//, // Input from absolute path\n /\\|\\s*\\w+/, // Pipe to command\n ]\n\n for (const pattern of dangerousPatterns) {\n if (pattern.test(command)) {\n return {\n valid: false,\n reason: `Command contains potentially dangerous pattern: ${pattern.source}`\n }\n }\n }\n\n return { valid: true }\n}\n\nexport class BackgroundWorker extends EventEmitter {\n private tasks: Map<string, BackgroundTask> = new Map()\n private processes: Map<string, ChildProcess> = new Map()\n private taskIdCounter = 0\n\n spawn(command: string, cwd?: string): BackgroundTask {\n // Validate command first\n const validation = validateCommand(command)\n if (!validation.valid) {\n throw new Error(`Security: ${validation.reason}`)\n }\n\n const id = `task_${++this.taskIdCounter}`\n\n const task: BackgroundTask = {\n id,\n command,\n status: 'running',\n startTime: new Date(),\n output: []\n }\n\n this.tasks.set(id, task)\n\n // Parse command safely\n const { cmd, args } = parseCommand(command)\n\n if (!cmd) {\n task.status = 'failed'\n task.endTime = new Date()\n task.output.push('Error: Empty command')\n return task\n }\n\n // SECURITY FIX: Use shell: false to prevent injection\n const proc = spawn(cmd, args, {\n cwd: cwd || process.cwd(),\n shell: false, // CRITICAL: Never use shell: true\n stdio: ['pipe', 'pipe', 'pipe'],\n env: process.env\n })\n\n this.processes.set(id, proc)\n\n proc.stdout?.on('data', (data: Buffer) => {\n const line = data.toString()\n task.output.push(line)\n this.emit('output', { taskId: id, data: line, stream: 'stdout' })\n })\n\n proc.stderr?.on('data', (data: Buffer) => {\n const line = data.toString()\n task.output.push(line)\n this.emit('output', { taskId: id, data: line, stream: 'stderr' })\n })\n\n proc.on('close', (code: number | null) => {\n task.status = code === 0 ? 'completed' : 'failed'\n task.endTime = new Date()\n task.exitCode = code ?? undefined\n this.processes.delete(id)\n\n this.emit('complete', {\n taskId: id,\n exitCode: code,\n duration: task.endTime.getTime() - task.startTime.getTime()\n })\n\n // Notify user\n this.notifyCompletion(task)\n\n // Cleanup old tasks\n this.cleanupOldTasks()\n })\n\n proc.on('error', (error: Error) => {\n task.status = 'failed'\n task.endTime = new Date()\n task.output.push(`Error: ${error.message}`)\n this.processes.delete(id)\n\n this.emit('error', { taskId: id, error })\n })\n\n this.emit('started', { taskId: id, command })\n\n return task\n }\n\n cancel(taskId: string): boolean {\n const proc = this.processes.get(taskId)\n const task = this.tasks.get(taskId)\n\n if (proc && task) {\n proc.kill('SIGTERM')\n task.status = 'cancelled'\n task.endTime = new Date()\n this.processes.delete(taskId)\n return true\n }\n\n return false\n }\n\n getTask(taskId: string): BackgroundTask | undefined {\n return this.tasks.get(taskId)\n }\n\n getRunningTasks(): BackgroundTask[] {\n return Array.from(this.tasks.values()).filter(t => t.status === 'running')\n }\n\n getAllTasks(): BackgroundTask[] {\n return Array.from(this.tasks.values())\n }\n\n getRecentTasks(limit: number = 10): BackgroundTask[] {\n return Array.from(this.tasks.values())\n .sort((a, b) => b.startTime.getTime() - a.startTime.getTime())\n .slice(0, limit)\n }\n\n private cleanupOldTasks(): void {\n // Remove completed tasks beyond limit\n const tasks = Array.from(this.tasks.entries())\n .filter(([_, t]) => t.status !== 'running')\n .sort((a, b) => b[1].startTime.getTime() - a[1].startTime.getTime())\n\n if (tasks.length > MAX_TASK_HISTORY) {\n const toRemove = tasks.slice(MAX_TASK_HISTORY)\n for (const [id] of toRemove) {\n this.tasks.delete(id)\n }\n }\n }\n\n private notifyCompletion(task: BackgroundTask): void {\n const duration = task.endTime\n ? Math.round((task.endTime.getTime() - task.startTime.getTime()) / 1000)\n : 0\n\n const icon = task.status === 'completed' ? '✓' : '✗'\n const status = task.status === 'completed' ? 'completed' : 'failed'\n\n console.log(`\\n🤝 Bash Bro: Background task ${icon} ${status}`)\n console.log(` Command: ${task.command}`)\n console.log(` Duration: ${duration}s`)\n\n if (task.status === 'failed' && task.output.length > 0) {\n const lastLines = task.output.slice(-3).join('').trim()\n if (lastLines) {\n console.log(` Last output: ${lastLines.slice(0, 100)}`)\n }\n }\n\n console.log()\n }\n\n formatStatus(): string {\n const running = this.getRunningTasks()\n\n if (running.length === 0) {\n return 'No background tasks running.'\n }\n\n const lines = ['Background tasks:']\n for (const task of running) {\n const elapsed = Math.round((Date.now() - task.startTime.getTime()) / 1000)\n lines.push(` [${task.id}] ${task.command} (${elapsed}s)`)\n }\n\n return lines.join('\\n')\n }\n}\n","import { execFileSync } from 'child_process'\nimport { EventEmitter } from 'events'\nimport type { BashBrosConfig } from '../types.js'\nimport { SystemProfiler, SystemProfile } from './profiler.js'\nimport { TaskRouter, RoutingResult } from './router.js'\nimport { CommandSuggester, Suggestion, SuggestionContext } from './suggester.js'\nimport { BackgroundWorker, BackgroundTask } from './worker.js'\nimport { OllamaClient } from './ollama.js'\nimport { getBashgymIntegration, type ModelManifest } from '../integration/bashgym.js'\n\nexport interface BroConfig {\n modelEndpoint?: string // Ollama endpoint (default: http://localhost:11434)\n modelName?: string // e.g., 'qwen2.5-coder:7b'\n enableSuggestions?: boolean\n enableRouting?: boolean\n enableBackground?: boolean\n enableOllama?: boolean // Use Ollama for AI features\n enableBashgymIntegration?: boolean // Enable bashgym integration for model hot-swap\n}\n\n// Allowlist of commands that can be executed directly\nconst SAFE_COMMANDS = new Set([\n 'ls', 'dir', 'cat', 'head', 'tail', 'grep', 'find', 'wc',\n 'pwd', 'cd', 'mkdir', 'touch', 'cp', 'mv', 'rm',\n 'git', 'npm', 'npx', 'pnpm', 'yarn', 'node', 'python', 'python3',\n 'pip', 'pip3', 'pytest', 'cargo', 'go', 'rustc',\n 'docker', 'kubectl', 'echo', 'which', 'where', 'type',\n 'date', 'whoami', 'hostname', 'env', 'printenv'\n])\n\n/**\n * Parse command into executable and arguments safely\n */\nfunction parseCommandSafe(command: string): { cmd: string; args: string[] } | null {\n const tokens: string[] = []\n let current = ''\n let inQuote: string | null = null\n\n for (let i = 0; i < command.length; i++) {\n const char = command[i]\n\n if (inQuote) {\n if (char === inQuote) {\n inQuote = null\n } else {\n current += char\n }\n } else if (char === '\"' || char === \"'\") {\n inQuote = char\n } else if (char === ' ' || char === '\\t') {\n if (current) {\n tokens.push(current)\n current = ''\n }\n } else {\n current += char\n }\n }\n\n if (current) {\n tokens.push(current)\n }\n\n if (tokens.length === 0) {\n return null\n }\n\n const cmd = tokens[0]\n\n // SECURITY: Only allow whitelisted commands\n if (!SAFE_COMMANDS.has(cmd)) {\n return null\n }\n\n return {\n cmd,\n args: tokens.slice(1)\n }\n}\n\n/**\n * Validate command doesn't contain shell injection patterns\n */\nfunction validateCommandSafety(command: string): { safe: boolean; reason?: string } {\n const dangerousPatterns = [\n /[;&|`]/, // Shell operators\n /\\$\\(/, // Command substitution\n /\\$\\{/, // Variable expansion\n />\\s*>/, // Append redirect\n /[<>]\\s*\\//, // Redirect to/from absolute path\n /\\|\\s*\\w+/, // Pipe to command\n /\\\\x[0-9a-f]/i, // Hex escapes\n /\\\\[0-7]{3}/, // Octal escapes\n ]\n\n for (const pattern of dangerousPatterns) {\n if (pattern.test(command)) {\n return { safe: false, reason: `Contains dangerous pattern` }\n }\n }\n\n return { safe: true }\n}\n\nexport class BashBro extends EventEmitter {\n private profiler: SystemProfiler\n private router: TaskRouter\n private suggester: CommandSuggester\n private worker: BackgroundWorker\n private ollama: OllamaClient | null = null\n private profile: SystemProfile | null = null\n private config: BroConfig\n private ollamaAvailable: boolean = false\n private bashgymModelVersion: string | null = null\n\n constructor(config: BroConfig = {}) {\n super()\n\n this.config = {\n enableSuggestions: true,\n enableRouting: true,\n enableBackground: true,\n enableOllama: true,\n enableBashgymIntegration: true,\n ...config\n }\n\n this.profiler = new SystemProfiler()\n this.router = new TaskRouter()\n this.suggester = new CommandSuggester()\n this.worker = new BackgroundWorker()\n\n // Initialize Ollama client if enabled\n if (this.config.enableOllama) {\n this.ollama = new OllamaClient({\n host: this.config.modelEndpoint,\n model: this.config.modelName\n })\n }\n\n // Forward worker events\n this.worker.on('complete', (data) => this.emit('task:complete', data))\n this.worker.on('output', (data) => this.emit('task:output', data))\n this.worker.on('error', (data) => this.emit('task:error', data))\n\n // Initialize bashgym integration for model hot-swap\n if (this.config.enableBashgymIntegration) {\n this.initBashgymIntegration()\n }\n }\n\n /**\n * Initialize bashgym integration for model hot-swap\n */\n private initBashgymIntegration(): void {\n try {\n const integration = getBashgymIntegration()\n\n // Listen for model updates\n integration.on('model:updated', (version: string, manifest: ModelManifest) => {\n this.handleModelUpdate(version, manifest)\n })\n\n // Check if we should use the bashgym sidekick model\n if (integration.isLinked()) {\n const modelName = integration.getOllamaModelName()\n const currentVersion = integration.getCurrentModelVersion()\n\n if (currentVersion && this.ollama) {\n // Use the bashgym-trained sidekick model\n this.ollama.setModel(`${modelName}:${currentVersion}`)\n this.bashgymModelVersion = currentVersion\n console.log(`🤝 Bash Bro: Using bashgym sidekick model (${currentVersion})`)\n }\n }\n } catch {\n // Integration not available - continue without it\n }\n }\n\n /**\n * Handle model update from bashgym (hot-swap)\n */\n private handleModelUpdate(version: string, manifest: ModelManifest): void {\n if (!this.ollama) return\n\n // Don't update if it's the same version\n if (version === this.bashgymModelVersion) return\n\n try {\n const integration = getBashgymIntegration()\n const modelName = integration.getOllamaModelName()\n\n // Hot-swap to the new model\n this.ollama.setModel(`${modelName}:${version}`)\n this.bashgymModelVersion = version\n\n console.log(`🤝 Bash Bro: Model hot-swapped to ${version}`)\n this.emit('model:updated', version)\n } catch (error) {\n console.error('Failed to hot-swap model:', error)\n }\n }\n\n async initialize(): Promise<void> {\n // Load or scan system profile\n this.profile = this.profiler.load()\n\n if (!this.profile || this.isProfileStale()) {\n console.log('🤝 Bash Bro: Scanning your system...')\n this.profile = await this.profiler.scan()\n console.log('🤝 Bash Bro: System profile updated!')\n }\n\n this.router.updateProfile(this.profile)\n this.suggester.updateProfile(this.profile)\n\n // Check Ollama availability\n if (this.ollama) {\n this.ollamaAvailable = await this.ollama.isAvailable()\n if (this.ollamaAvailable) {\n console.log('🤝 Bash Bro: Ollama connected')\n }\n }\n\n this.emit('ready', this.profile)\n }\n\n private isProfileStale(): boolean {\n if (!this.profile) return true\n\n const age = Date.now() - new Date(this.profile.timestamp).getTime()\n const oneDay = 24 * 60 * 60 * 1000\n\n return age > oneDay\n }\n\n scanProject(projectPath: string): void {\n this.profiler.scanProject(projectPath)\n this.profile = this.profiler.get()\n\n if (this.profile) {\n this.router.updateProfile(this.profile)\n this.suggester.updateProfile(this.profile)\n }\n }\n\n route(command: string): RoutingResult {\n if (!this.config.enableRouting) {\n return { decision: 'main', reason: 'Routing disabled', confidence: 1 }\n }\n\n return this.router.route(command)\n }\n\n suggest(context: SuggestionContext): Suggestion[] {\n if (!this.config.enableSuggestions) {\n return []\n }\n\n return this.suggester.suggest(context)\n }\n\n /**\n * SECURITY FIX: Safe command execution with validation\n */\n async execute(command: string): Promise<string> {\n // Validate command safety\n const safety = validateCommandSafety(command)\n if (!safety.safe) {\n return `Security: Command blocked - ${safety.reason}`\n }\n\n // Parse command safely\n const parsed = parseCommandSafe(command)\n if (!parsed) {\n return `Security: Command not in allowlist. Only safe commands can be executed directly.`\n }\n\n try {\n // SECURITY: Use execFileSync with array args, no shell\n const output = execFileSync(parsed.cmd, parsed.args, {\n encoding: 'utf-8',\n timeout: 30000,\n cwd: process.cwd(),\n windowsHide: true\n })\n return output\n } catch (error: any) {\n return error.message || 'Command failed'\n }\n }\n\n runBackground(command: string, cwd?: string): BackgroundTask {\n if (!this.config.enableBackground) {\n throw new Error('Background tasks disabled')\n }\n\n return this.worker.spawn(command, cwd)\n }\n\n cancelBackground(taskId: string): boolean {\n return this.worker.cancel(taskId)\n }\n\n getBackgroundTasks(): BackgroundTask[] {\n return this.worker.getRunningTasks()\n }\n\n getSystemContext(): string {\n return this.profiler.toContext()\n }\n\n getProfile(): SystemProfile | null {\n return this.profile\n }\n\n /**\n * Check if Ollama is available for AI features\n */\n isOllamaAvailable(): boolean {\n return this.ollamaAvailable\n }\n\n /**\n * Ask Bash Bro (via Ollama) to suggest the next command\n */\n async aiSuggest(context: string): Promise<string | null> {\n if (!this.ollama || !this.ollamaAvailable) {\n return null\n }\n\n return this.ollama.suggestCommand(context)\n }\n\n /**\n * Ask Bash Bro to explain a command\n */\n async aiExplain(command: string): Promise<string> {\n if (!this.ollama || !this.ollamaAvailable) {\n return 'Ollama not available for explanations.'\n }\n\n return this.ollama.explainCommand(command)\n }\n\n /**\n * Ask Bash Bro to fix a failed command\n */\n async aiFix(command: string, error: string): Promise<string | null> {\n if (!this.ollama || !this.ollamaAvailable) {\n return null\n }\n\n return this.ollama.fixCommand(command, error)\n }\n\n /**\n * Set the Ollama model to use\n */\n setModel(model: string): void {\n if (this.ollama) {\n this.ollama.setModel(model)\n }\n }\n\n /**\n * Generate a shell script from natural language description\n */\n async aiGenerateScript(description: string): Promise<string | null> {\n if (!this.ollama || !this.ollamaAvailable) {\n return null\n }\n\n const shell = this.profile?.shell || 'bash'\n return this.ollama.generateScript(description, shell)\n }\n\n /**\n * Analyze command for security risks using AI\n */\n async aiAnalyzeSafety(command: string): Promise<{\n safe: boolean\n risk: 'low' | 'medium' | 'high' | 'critical'\n explanation: string\n suggestions: string[]\n }> {\n if (!this.ollama || !this.ollamaAvailable) {\n return {\n safe: true,\n risk: 'low',\n explanation: 'AI analysis not available.',\n suggestions: []\n }\n }\n\n return this.ollama.analyzeCommandSafety(command)\n }\n\n /**\n * Summarize a terminal session\n */\n async aiSummarize(commands: { command: string; output?: string; error?: string }[]): Promise<string> {\n if (!this.ollama || !this.ollamaAvailable) {\n return 'AI not available for summaries.'\n }\n\n return this.ollama.summarizeSession(commands)\n }\n\n /**\n * Get AI help for a topic or command\n */\n async aiHelp(topic: string): Promise<string> {\n if (!this.ollama || !this.ollamaAvailable) {\n return 'AI not available for help.'\n }\n\n return this.ollama.getHelp(topic)\n }\n\n /**\n * Convert natural language to command\n */\n async aiToCommand(description: string): Promise<string | null> {\n if (!this.ollama || !this.ollamaAvailable) {\n return null\n }\n\n return this.ollama.naturalToCommand(description)\n }\n\n /**\n * Get bashgym sidekick model version (if using)\n */\n getBashgymModelVersion(): string | null {\n return this.bashgymModelVersion\n }\n\n /**\n * Check if using bashgym-trained sidekick model\n */\n isUsingBashgymModel(): boolean {\n return this.bashgymModelVersion !== null\n }\n\n /**\n * Force refresh the bashgym model (check for updates)\n */\n refreshBashgymModel(): boolean {\n if (!this.config.enableBashgymIntegration) {\n return false\n }\n\n try {\n const integration = getBashgymIntegration()\n const currentVersion = integration.getCurrentModelVersion()\n\n if (currentVersion && currentVersion !== this.bashgymModelVersion) {\n const modelName = integration.getOllamaModelName()\n if (this.ollama) {\n this.ollama.setModel(`${modelName}:${currentVersion}`)\n this.bashgymModelVersion = currentVersion\n this.emit('model:updated', currentVersion)\n return true\n }\n }\n } catch {\n // Ignore errors\n }\n\n return false\n }\n\n // Format a nice status message\n status(): string {\n const lines: string[] = [\n '🤝 Bash Bro Status',\n '─'.repeat(40)\n ]\n\n if (this.profile) {\n lines.push(`Platform: ${this.profile.platform} (${this.profile.arch})`)\n lines.push(`Shell: ${this.profile.shell}`)\n\n if (this.profile.python) {\n lines.push(`Python: ${this.profile.python.version}`)\n }\n if (this.profile.node) {\n lines.push(`Node: ${this.profile.node.version}`)\n }\n\n if (this.profile.ollama) {\n lines.push(`Ollama: ${this.profile.ollama.version}`)\n if (this.profile.ollama.models.length > 0) {\n lines.push(` Models: ${this.profile.ollama.models.join(', ')}`)\n }\n }\n\n if (this.profile.projectType) {\n lines.push(`Project: ${this.profile.projectType}`)\n }\n }\n\n // Ollama connection status\n lines.push('')\n if (this.ollamaAvailable) {\n const model = this.ollama?.getModel() || 'default'\n if (this.bashgymModelVersion) {\n lines.push(`AI: Connected (bashgym sidekick ${this.bashgymModelVersion})`)\n } else {\n lines.push(`AI: Connected (${model})`)\n }\n } else {\n lines.push('AI: Not connected (run Ollama for AI features)')\n }\n\n // Bashgym integration status\n if (this.config.enableBashgymIntegration) {\n try {\n const integration = getBashgymIntegration()\n if (integration.isLinked()) {\n lines.push(`BashGym: Linked`)\n if (integration.isBashgymRunning()) {\n lines.push(` Status: Running`)\n }\n }\n } catch {\n // Integration not available\n }\n }\n\n lines.push('')\n lines.push(this.worker.formatStatus())\n\n return lines.join('\\n')\n }\n}\n","/**\r\n * Session Metrics\r\n * Track what the agent is doing for observability\r\n */\r\n\r\nimport type { PolicyViolation } from '../types.js'\r\nimport type { RiskScore } from '../policy/risk-scorer.js'\r\n\r\nexport interface CommandMetric {\r\n command: string\r\n timestamp: Date\r\n duration: number\r\n allowed: boolean\r\n riskScore: RiskScore\r\n violations: PolicyViolation[]\r\n exitCode?: number\r\n}\r\n\r\nexport interface SessionMetrics {\r\n sessionId: string\r\n startTime: Date\r\n endTime?: Date\r\n duration: number\r\n\r\n // Command stats\r\n commandCount: number\r\n blockedCount: number\r\n uniqueCommands: number\r\n topCommands: [string, number][]\r\n\r\n // Risk distribution\r\n riskDistribution: {\r\n safe: number\r\n caution: number\r\n dangerous: number\r\n critical: number\r\n }\r\n avgRiskScore: number\r\n\r\n // Performance\r\n avgExecutionTime: number\r\n totalExecutionTime: number\r\n\r\n // File/path tracking\r\n filesModified: string[]\r\n pathsAccessed: string[]\r\n\r\n // Violations\r\n violationsByType: Record<string, number>\r\n}\r\n\r\nexport class MetricsCollector {\r\n private sessionId: string\r\n private startTime: Date\r\n private commands: CommandMetric[] = []\r\n private filesModified: Set<string> = new Set()\r\n private pathsAccessed: Set<string> = new Set()\r\n\r\n constructor() {\r\n this.sessionId = this.generateSessionId()\r\n this.startTime = new Date()\r\n }\r\n\r\n private generateSessionId(): string {\r\n const now = new Date()\r\n const date = now.toISOString().slice(0, 10).replace(/-/g, '')\r\n const time = now.toTimeString().slice(0, 8).replace(/:/g, '')\r\n const rand = Math.random().toString(36).slice(2, 6)\r\n return `${date}-${time}-${rand}`\r\n }\r\n\r\n /**\r\n * Record a command execution\r\n */\r\n record(metric: CommandMetric): void {\r\n this.commands.push(metric)\r\n\r\n // Track paths\r\n const paths = this.extractPaths(metric.command)\r\n for (const path of paths) {\r\n this.pathsAccessed.add(path)\r\n }\r\n\r\n // Track file modifications\r\n if (this.isWriteCommand(metric.command)) {\r\n for (const path of paths) {\r\n this.filesModified.add(path)\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Get current session metrics\r\n */\r\n getMetrics(): SessionMetrics {\r\n const now = new Date()\r\n const duration = now.getTime() - this.startTime.getTime()\r\n\r\n // Count risk distribution\r\n const riskDist = { safe: 0, caution: 0, dangerous: 0, critical: 0 }\r\n let totalRisk = 0\r\n\r\n for (const cmd of this.commands) {\r\n riskDist[cmd.riskScore.level]++\r\n totalRisk += cmd.riskScore.score\r\n }\r\n\r\n // Count command frequency\r\n const cmdFreq = new Map<string, number>()\r\n for (const cmd of this.commands) {\r\n const base = cmd.command.split(/\\s+/)[0]\r\n cmdFreq.set(base, (cmdFreq.get(base) || 0) + 1)\r\n }\r\n const topCommands = [...cmdFreq.entries()]\r\n .sort((a, b) => b[1] - a[1])\r\n .slice(0, 10)\r\n\r\n // Count violations by type\r\n const violationsByType: Record<string, number> = {}\r\n for (const cmd of this.commands) {\r\n for (const v of cmd.violations) {\r\n violationsByType[v.type] = (violationsByType[v.type] || 0) + 1\r\n }\r\n }\r\n\r\n // Calculate execution times\r\n const totalExecTime = this.commands.reduce((sum, c) => sum + c.duration, 0)\r\n const avgExecTime = this.commands.length > 0 ? totalExecTime / this.commands.length : 0\r\n\r\n return {\r\n sessionId: this.sessionId,\r\n startTime: this.startTime,\r\n duration,\r\n\r\n commandCount: this.commands.length,\r\n blockedCount: this.commands.filter(c => !c.allowed).length,\r\n uniqueCommands: cmdFreq.size,\r\n topCommands,\r\n\r\n riskDistribution: riskDist,\r\n avgRiskScore: this.commands.length > 0 ? totalRisk / this.commands.length : 0,\r\n\r\n avgExecutionTime: avgExecTime,\r\n totalExecutionTime: totalExecTime,\r\n\r\n filesModified: [...this.filesModified],\r\n pathsAccessed: [...this.pathsAccessed],\r\n\r\n violationsByType\r\n }\r\n }\r\n\r\n /**\r\n * Extract paths from a command\r\n */\r\n private extractPaths(command: string): string[] {\r\n const paths: string[] = []\r\n const tokens = command.split(/\\s+/)\r\n\r\n for (const token of tokens) {\r\n if (token.startsWith('-')) continue\r\n\r\n if (\r\n token.startsWith('/') ||\r\n token.startsWith('./') ||\r\n token.startsWith('../') ||\r\n token.startsWith('~/') ||\r\n token.includes('.')\r\n ) {\r\n paths.push(token)\r\n }\r\n }\r\n\r\n return paths\r\n }\r\n\r\n /**\r\n * Check if command modifies files\r\n */\r\n private isWriteCommand(command: string): boolean {\r\n const writePatterns = [\r\n /^(vim|vi|nano|emacs|code)\\s/,\r\n /^(touch|mkdir|cp|mv|rm)\\s/,\r\n /^(echo|cat|printf).*>/,\r\n /^(git\\s+(add|commit|checkout|reset))/,\r\n /^(npm|yarn|pnpm)\\s+(install|uninstall)/,\r\n /^(pip|pip3)\\s+(install|uninstall)/,\r\n /^chmod\\s/,\r\n /^chown\\s/,\r\n ]\r\n\r\n return writePatterns.some(p => p.test(command))\r\n }\r\n\r\n /**\r\n * Get recent commands\r\n */\r\n getRecentCommands(n: number = 10): CommandMetric[] {\r\n return this.commands.slice(-n)\r\n }\r\n\r\n /**\r\n * Get blocked commands\r\n */\r\n getBlockedCommands(): CommandMetric[] {\r\n return this.commands.filter(c => !c.allowed)\r\n }\r\n\r\n /**\r\n * Get high-risk commands\r\n */\r\n getHighRiskCommands(threshold: number = 6): CommandMetric[] {\r\n return this.commands.filter(c => c.riskScore.score >= threshold)\r\n }\r\n\r\n /**\r\n * Format duration for display\r\n */\r\n static formatDuration(ms: number): string {\r\n if (ms < 1000) return `${ms}ms`\r\n if (ms < 60000) return `${(ms / 1000).toFixed(1)}s`\r\n if (ms < 3600000) return `${Math.floor(ms / 60000)}m ${Math.floor((ms % 60000) / 1000)}s`\r\n return `${Math.floor(ms / 3600000)}h ${Math.floor((ms % 3600000) / 60000)}m`\r\n }\r\n\r\n /**\r\n * Reset collector\r\n */\r\n reset(): void {\r\n this.sessionId = this.generateSessionId()\r\n this.startTime = new Date()\r\n this.commands = []\r\n this.filesModified.clear()\r\n this.pathsAccessed.clear()\r\n }\r\n}\r\n","/**\r\n * Cost Estimation\r\n * Estimate API costs based on session complexity\r\n */\r\n\r\nexport interface CostEstimate {\r\n estimatedTokens: number\r\n estimatedCost: number // USD\r\n breakdown: {\r\n inputTokens: number\r\n outputTokens: number\r\n toolCalls: number\r\n contextTokens: number\r\n }\r\n model: string\r\n confidence: 'low' | 'medium' | 'high'\r\n}\r\n\r\nexport interface ModelPricing {\r\n inputPer1k: number // USD per 1K input tokens\r\n outputPer1k: number // USD per 1K output tokens\r\n}\r\n\r\n// Pricing as of 2025 (update as needed)\r\nconst MODEL_PRICING: Record<string, ModelPricing> = {\r\n 'claude-opus-4': { inputPer1k: 0.015, outputPer1k: 0.075 },\r\n 'claude-sonnet-4': { inputPer1k: 0.003, outputPer1k: 0.015 },\r\n 'claude-haiku-4': { inputPer1k: 0.00025, outputPer1k: 0.00125 },\r\n 'gpt-4o': { inputPer1k: 0.005, outputPer1k: 0.015 },\r\n 'gpt-4o-mini': { inputPer1k: 0.00015, outputPer1k: 0.0006 },\r\n 'default': { inputPer1k: 0.003, outputPer1k: 0.015 }\r\n}\r\n\r\n// Heuristics for token estimation\r\nconst AVG_CHARS_PER_TOKEN = 4\r\nconst AVG_TOOL_CALL_TOKENS = 150\r\nconst AVG_TOOL_RESULT_TOKENS = 500\r\nconst CONTEXT_OVERHEAD_RATIO = 0.2 // 20% overhead for system prompts, etc.\r\n\r\nexport class CostEstimator {\r\n private model: string\r\n private pricing: ModelPricing\r\n private totalInputTokens: number = 0\r\n private totalOutputTokens: number = 0\r\n private toolCallCount: number = 0\r\n\r\n constructor(model: string = 'claude-sonnet-4') {\r\n this.model = model\r\n this.pricing = MODEL_PRICING[model] || MODEL_PRICING['default']\r\n }\r\n\r\n /**\r\n * Estimate tokens from text\r\n */\r\n estimateTokens(text: string): number {\r\n return Math.ceil(text.length / AVG_CHARS_PER_TOKEN)\r\n }\r\n\r\n /**\r\n * Record a tool call with input and output\r\n */\r\n recordToolCall(input: string, output?: string): void {\r\n this.toolCallCount++\r\n\r\n // Estimate input tokens (command + tool overhead)\r\n const inputTokens = this.estimateTokens(input) + AVG_TOOL_CALL_TOKENS\r\n this.totalInputTokens += inputTokens\r\n\r\n // Estimate output tokens (result + overhead)\r\n if (output) {\r\n const outputTokens = this.estimateTokens(output) + 50 // Response overhead\r\n this.totalOutputTokens += outputTokens\r\n } else {\r\n this.totalOutputTokens += AVG_TOOL_RESULT_TOKENS\r\n }\r\n }\r\n\r\n /**\r\n * Get current cost estimate\r\n */\r\n getEstimate(): CostEstimate {\r\n // Add context overhead\r\n const contextTokens = Math.ceil(\r\n (this.totalInputTokens + this.totalOutputTokens) * CONTEXT_OVERHEAD_RATIO\r\n )\r\n\r\n const totalInput = this.totalInputTokens + contextTokens\r\n const totalOutput = this.totalOutputTokens\r\n\r\n // Calculate cost\r\n const inputCost = (totalInput / 1000) * this.pricing.inputPer1k\r\n const outputCost = (totalOutput / 1000) * this.pricing.outputPer1k\r\n const totalCost = inputCost + outputCost\r\n\r\n // Determine confidence based on data points\r\n let confidence: CostEstimate['confidence']\r\n if (this.toolCallCount < 5) confidence = 'low'\r\n else if (this.toolCallCount < 20) confidence = 'medium'\r\n else confidence = 'high'\r\n\r\n return {\r\n estimatedTokens: totalInput + totalOutput,\r\n estimatedCost: Math.round(totalCost * 10000) / 10000, // 4 decimal places\r\n breakdown: {\r\n inputTokens: totalInput,\r\n outputTokens: totalOutput,\r\n toolCalls: this.toolCallCount,\r\n contextTokens\r\n },\r\n model: this.model,\r\n confidence\r\n }\r\n }\r\n\r\n /**\r\n * Format cost for display\r\n */\r\n static formatCost(cost: number): string {\r\n if (cost < 0.01) return `$${(cost * 100).toFixed(2)}¢`\r\n if (cost < 1) return `$${cost.toFixed(3)}`\r\n return `$${cost.toFixed(2)}`\r\n }\r\n\r\n /**\r\n * Get cost projection for N more commands\r\n */\r\n projectCost(additionalCommands: number): CostEstimate {\r\n if (this.toolCallCount === 0) {\r\n // Use defaults if no data\r\n const projectedInput = additionalCommands * (AVG_TOOL_CALL_TOKENS + 50)\r\n const projectedOutput = additionalCommands * AVG_TOOL_RESULT_TOKENS\r\n\r\n const inputCost = (projectedInput / 1000) * this.pricing.inputPer1k\r\n const outputCost = (projectedOutput / 1000) * this.pricing.outputPer1k\r\n\r\n return {\r\n estimatedTokens: projectedInput + projectedOutput,\r\n estimatedCost: inputCost + outputCost,\r\n breakdown: {\r\n inputTokens: projectedInput,\r\n outputTokens: projectedOutput,\r\n toolCalls: additionalCommands,\r\n contextTokens: 0\r\n },\r\n model: this.model,\r\n confidence: 'low'\r\n }\r\n }\r\n\r\n // Project based on current averages\r\n const avgInputPerCall = this.totalInputTokens / this.toolCallCount\r\n const avgOutputPerCall = this.totalOutputTokens / this.toolCallCount\r\n\r\n const projectedInput = this.totalInputTokens + (additionalCommands * avgInputPerCall)\r\n const projectedOutput = this.totalOutputTokens + (additionalCommands * avgOutputPerCall)\r\n const contextTokens = Math.ceil((projectedInput + projectedOutput) * CONTEXT_OVERHEAD_RATIO)\r\n\r\n const totalInput = projectedInput + contextTokens\r\n const totalOutput = projectedOutput\r\n\r\n const inputCost = (totalInput / 1000) * this.pricing.inputPer1k\r\n const outputCost = (totalOutput / 1000) * this.pricing.outputPer1k\r\n\r\n return {\r\n estimatedTokens: totalInput + totalOutput,\r\n estimatedCost: inputCost + outputCost,\r\n breakdown: {\r\n inputTokens: Math.ceil(totalInput),\r\n outputTokens: Math.ceil(totalOutput),\r\n toolCalls: this.toolCallCount + additionalCommands,\r\n contextTokens\r\n },\r\n model: this.model,\r\n confidence: this.toolCallCount >= 10 ? 'high' : 'medium'\r\n }\r\n }\r\n\r\n /**\r\n * Set model for pricing\r\n */\r\n setModel(model: string): void {\r\n this.model = model\r\n this.pricing = MODEL_PRICING[model] || MODEL_PRICING['default']\r\n }\r\n\r\n /**\r\n * Reset counters\r\n */\r\n reset(): void {\r\n this.totalInputTokens = 0\r\n this.totalOutputTokens = 0\r\n this.toolCallCount = 0\r\n }\r\n\r\n /**\r\n * Add custom model pricing\r\n */\r\n static addModelPricing(model: string, pricing: ModelPricing): void {\r\n MODEL_PRICING[model] = pricing\r\n }\r\n}\r\n","/**\r\n * Session Reports\r\n * Generate human-readable reports of agent activity\r\n */\r\n\r\nimport type { SessionMetrics } from './metrics.js'\r\nimport type { CostEstimate } from './cost.js'\r\n\r\nexport interface ReportOptions {\r\n showCommands?: boolean\r\n showBlocked?: boolean\r\n showRisk?: boolean\r\n showPaths?: boolean\r\n showCost?: boolean\r\n format?: 'text' | 'json' | 'markdown'\r\n}\r\n\r\nconst DEFAULT_OPTIONS: ReportOptions = {\r\n showCommands: true,\r\n showBlocked: true,\r\n showRisk: true,\r\n showPaths: true,\r\n showCost: true,\r\n format: 'text'\r\n}\r\n\r\nexport class ReportGenerator {\r\n /**\r\n * Generate a session report\r\n */\r\n static generate(\r\n metrics: SessionMetrics,\r\n cost?: CostEstimate,\r\n options: ReportOptions = {}\r\n ): string {\r\n const opts = { ...DEFAULT_OPTIONS, ...options }\r\n\r\n switch (opts.format) {\r\n case 'json':\r\n return this.generateJSON(metrics, cost)\r\n case 'markdown':\r\n return this.generateMarkdown(metrics, cost, opts)\r\n default:\r\n return this.generateText(metrics, cost, opts)\r\n }\r\n }\r\n\r\n /**\r\n * Generate text report\r\n */\r\n private static generateText(\r\n metrics: SessionMetrics,\r\n cost?: CostEstimate,\r\n opts: ReportOptions = {}\r\n ): string {\r\n const lines: string[] = []\r\n const duration = this.formatDuration(metrics.duration)\r\n\r\n lines.push(`Session Report (${duration})`)\r\n lines.push('─'.repeat(45))\r\n lines.push('')\r\n\r\n // Summary line\r\n const blockedPct = metrics.commandCount > 0\r\n ? Math.round((metrics.blockedCount / metrics.commandCount) * 100)\r\n : 0\r\n lines.push(`Commands: ${metrics.commandCount} total, ${metrics.blockedCount} blocked (${blockedPct}%)`)\r\n lines.push('')\r\n\r\n // Risk distribution\r\n if (opts.showRisk) {\r\n const total = metrics.commandCount || 1\r\n const { safe, caution, dangerous, critical } = metrics.riskDistribution\r\n\r\n const safePct = Math.round((safe / total) * 100)\r\n const cautionPct = Math.round((caution / total) * 100)\r\n const dangerousPct = Math.round((dangerous / total) * 100)\r\n const criticalPct = Math.round((critical / total) * 100)\r\n\r\n lines.push('Risk Distribution:')\r\n lines.push(` ${this.progressBar(safePct, 20)} ${safePct}% safe`)\r\n lines.push(` ${this.progressBar(cautionPct, 20)} ${cautionPct}% caution`)\r\n lines.push(` ${this.progressBar(dangerousPct, 20)} ${dangerousPct}% dangerous`)\r\n if (critical > 0) {\r\n lines.push(` ${this.progressBar(criticalPct, 20)} ${criticalPct}% CRITICAL`)\r\n }\r\n lines.push(` Average risk score: ${metrics.avgRiskScore.toFixed(1)}/10`)\r\n lines.push('')\r\n }\r\n\r\n // Top commands\r\n if (opts.showCommands && metrics.topCommands.length > 0) {\r\n lines.push('Top Commands:')\r\n for (const [cmd, count] of metrics.topCommands.slice(0, 5)) {\r\n const pct = Math.round((count / metrics.commandCount) * 100)\r\n lines.push(` ${cmd.padEnd(15)} ${count.toString().padStart(3)} (${pct}%)`)\r\n }\r\n lines.push('')\r\n }\r\n\r\n // Blocked commands\r\n if (opts.showBlocked && metrics.blockedCount > 0) {\r\n lines.push('Violations by Type:')\r\n for (const [type, count] of Object.entries(metrics.violationsByType)) {\r\n lines.push(` ${type}: ${count}`)\r\n }\r\n lines.push('')\r\n }\r\n\r\n // Paths\r\n if (opts.showPaths) {\r\n if (metrics.filesModified.length > 0) {\r\n lines.push(`Files Modified: ${metrics.filesModified.length}`)\r\n for (const file of metrics.filesModified.slice(0, 5)) {\r\n lines.push(` • ${file}`)\r\n }\r\n if (metrics.filesModified.length > 5) {\r\n lines.push(` ... and ${metrics.filesModified.length - 5} more`)\r\n }\r\n lines.push('')\r\n }\r\n\r\n lines.push(`Paths Accessed: ${metrics.pathsAccessed.length} unique`)\r\n lines.push('')\r\n }\r\n\r\n // Cost estimate\r\n if (opts.showCost && cost) {\r\n lines.push('Cost Estimate:')\r\n lines.push(` Tokens: ~${cost.estimatedTokens.toLocaleString()} (${cost.confidence} confidence)`)\r\n lines.push(` Cost: ~${this.formatCost(cost.estimatedCost)} (${cost.model})`)\r\n lines.push('')\r\n }\r\n\r\n // Performance\r\n lines.push('Performance:')\r\n lines.push(` Avg execution time: ${metrics.avgExecutionTime.toFixed(0)}ms`)\r\n lines.push(` Total execution time: ${this.formatDuration(metrics.totalExecutionTime)}`)\r\n lines.push('')\r\n\r\n lines.push(`Session ID: ${metrics.sessionId}`)\r\n\r\n return lines.join('\\n')\r\n }\r\n\r\n /**\r\n * Generate markdown report\r\n */\r\n private static generateMarkdown(\r\n metrics: SessionMetrics,\r\n cost?: CostEstimate,\r\n opts: ReportOptions = {}\r\n ): string {\r\n const lines: string[] = []\r\n const duration = this.formatDuration(metrics.duration)\r\n\r\n lines.push(`# Session Report`)\r\n lines.push('')\r\n lines.push(`**Duration:** ${duration}`)\r\n lines.push(`**Session ID:** \\`${metrics.sessionId}\\``)\r\n lines.push('')\r\n\r\n // Summary table\r\n lines.push('## Summary')\r\n lines.push('')\r\n lines.push('| Metric | Value |')\r\n lines.push('|--------|-------|')\r\n lines.push(`| Commands | ${metrics.commandCount} |`)\r\n lines.push(`| Blocked | ${metrics.blockedCount} |`)\r\n lines.push(`| Unique Commands | ${metrics.uniqueCommands} |`)\r\n lines.push(`| Avg Risk Score | ${metrics.avgRiskScore.toFixed(1)}/10 |`)\r\n lines.push('')\r\n\r\n // Risk distribution\r\n if (opts.showRisk) {\r\n lines.push('## Risk Distribution')\r\n lines.push('')\r\n lines.push('| Level | Count | Percentage |')\r\n lines.push('|-------|-------|------------|')\r\n const total = metrics.commandCount || 1\r\n for (const [level, count] of Object.entries(metrics.riskDistribution)) {\r\n const pct = Math.round((count / total) * 100)\r\n lines.push(`| ${level} | ${count} | ${pct}% |`)\r\n }\r\n lines.push('')\r\n }\r\n\r\n // Top commands\r\n if (opts.showCommands && metrics.topCommands.length > 0) {\r\n lines.push('## Top Commands')\r\n lines.push('')\r\n lines.push('| Command | Count |')\r\n lines.push('|---------|-------|')\r\n for (const [cmd, count] of metrics.topCommands.slice(0, 10)) {\r\n lines.push(`| \\`${cmd}\\` | ${count} |`)\r\n }\r\n lines.push('')\r\n }\r\n\r\n // Cost\r\n if (opts.showCost && cost) {\r\n lines.push('## Cost Estimate')\r\n lines.push('')\r\n lines.push(`- **Tokens:** ~${cost.estimatedTokens.toLocaleString()}`)\r\n lines.push(`- **Cost:** ~${this.formatCost(cost.estimatedCost)}`)\r\n lines.push(`- **Model:** ${cost.model}`)\r\n lines.push(`- **Confidence:** ${cost.confidence}`)\r\n lines.push('')\r\n }\r\n\r\n return lines.join('\\n')\r\n }\r\n\r\n /**\r\n * Generate JSON report\r\n */\r\n private static generateJSON(\r\n metrics: SessionMetrics,\r\n cost?: CostEstimate\r\n ): string {\r\n return JSON.stringify({ metrics, cost }, null, 2)\r\n }\r\n\r\n /**\r\n * Generate a simple progress bar\r\n */\r\n private static progressBar(percent: number, width: number): string {\r\n const filled = Math.round((percent / 100) * width)\r\n const empty = width - filled\r\n return '█'.repeat(filled) + '░'.repeat(empty)\r\n }\r\n\r\n /**\r\n * Format duration\r\n */\r\n private static formatDuration(ms: number): string {\r\n if (ms < 1000) return `${ms}ms`\r\n if (ms < 60000) return `${(ms / 1000).toFixed(1)}s`\r\n if (ms < 3600000) {\r\n const mins = Math.floor(ms / 60000)\r\n const secs = Math.floor((ms % 60000) / 1000)\r\n return `${mins}m ${secs}s`\r\n }\r\n const hours = Math.floor(ms / 3600000)\r\n const mins = Math.floor((ms % 3600000) / 60000)\r\n return `${hours}h ${mins}m`\r\n }\r\n\r\n /**\r\n * Format cost\r\n */\r\n private static formatCost(cost: number): string {\r\n if (cost < 0.01) return `$${(cost * 100).toFixed(2)}¢`\r\n if (cost < 1) return `$${cost.toFixed(3)}`\r\n return `$${cost.toFixed(2)}`\r\n }\r\n\r\n /**\r\n * Generate a one-line summary\r\n */\r\n static oneLine(metrics: SessionMetrics): string {\r\n const duration = this.formatDuration(metrics.duration)\r\n const blockedPct = metrics.commandCount > 0\r\n ? Math.round((metrics.blockedCount / metrics.commandCount) * 100)\r\n : 0\r\n\r\n return `${metrics.commandCount} cmds (${blockedPct}% blocked) | ` +\r\n `risk: ${metrics.avgRiskScore.toFixed(1)}/10 | ${duration}`\r\n }\r\n}\r\n","/**\r\n * Undo Stack\r\n * Track file changes for rollback capability\r\n */\r\n\r\nimport { existsSync, readFileSync, writeFileSync, unlinkSync, mkdirSync, copyFileSync, readdirSync, statSync } from 'fs'\r\nimport { join, dirname, basename } from 'path'\r\nimport { homedir } from 'os'\r\nimport type { UndoPolicy } from '../types.js'\r\n\r\nexport interface UndoEntry {\r\n id: string\r\n timestamp: Date\r\n path: string\r\n operation: 'create' | 'modify' | 'delete'\r\n backupPath?: string\r\n originalContent?: string\r\n command?: string\r\n}\r\n\r\nexport interface UndoResult {\r\n success: boolean\r\n message: string\r\n entry?: UndoEntry\r\n}\r\n\r\nexport interface UndoConfig {\r\n maxStackSize: number\r\n maxFileSize: number\r\n ttlMinutes: number\r\n backupPath: string\r\n enabled: boolean\r\n}\r\n\r\nconst DEFAULT_CONFIG: UndoConfig = {\r\n maxStackSize: 100,\r\n maxFileSize: 10 * 1024 * 1024, // 10MB\r\n ttlMinutes: 60,\r\n backupPath: join(homedir(), '.bashbros', 'undo'),\r\n enabled: true\r\n}\r\n\r\nexport class UndoStack {\r\n private stack: UndoEntry[] = []\r\n private sessionId: string\r\n private config: UndoConfig\r\n private undoDir: string\r\n\r\n constructor(policy?: Partial<UndoPolicy>) {\r\n this.config = { ...DEFAULT_CONFIG }\r\n\r\n if (policy) {\r\n if (typeof policy.maxStackSize === 'number') this.config.maxStackSize = policy.maxStackSize\r\n if (typeof policy.maxFileSize === 'number') this.config.maxFileSize = policy.maxFileSize\r\n if (typeof policy.ttlMinutes === 'number') this.config.ttlMinutes = policy.ttlMinutes\r\n if (typeof policy.backupPath === 'string') {\r\n this.config.backupPath = policy.backupPath.replace('~', homedir())\r\n }\r\n if (typeof policy.enabled === 'boolean') this.config.enabled = policy.enabled\r\n }\r\n\r\n this.undoDir = this.config.backupPath\r\n this.sessionId = Date.now().toString(36)\r\n this.ensureUndoDir()\r\n\r\n // Clean up old backups on init\r\n this.cleanupOldBackups()\r\n }\r\n\r\n private ensureUndoDir(): void {\r\n if (!existsSync(this.undoDir)) {\r\n mkdirSync(this.undoDir, { recursive: true, mode: 0o700 })\r\n }\r\n }\r\n\r\n /**\r\n * Clean up backups older than TTL\r\n */\r\n cleanupOldBackups(): number {\r\n if (!this.config.enabled || this.config.ttlMinutes <= 0) return 0\r\n\r\n const cutoff = Date.now() - (this.config.ttlMinutes * 60 * 1000)\r\n let cleaned = 0\r\n\r\n try {\r\n const files = readdirSync(this.undoDir)\r\n\r\n for (const file of files) {\r\n if (!file.endsWith('.backup')) continue\r\n\r\n const filePath = join(this.undoDir, file)\r\n try {\r\n const stats = statSync(filePath)\r\n if (stats.mtimeMs < cutoff) {\r\n unlinkSync(filePath)\r\n cleaned++\r\n }\r\n } catch { /* ignore individual file errors */ }\r\n }\r\n } catch { /* ignore dir errors */ }\r\n\r\n return cleaned\r\n }\r\n\r\n private generateId(): string {\r\n return `${this.sessionId}-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 6)}`\r\n }\r\n\r\n /**\r\n * Check if undo is enabled\r\n */\r\n isEnabled(): boolean {\r\n return this.config.enabled\r\n }\r\n\r\n /**\r\n * Record a file creation\r\n */\r\n recordCreate(path: string, command?: string): UndoEntry {\r\n const entry: UndoEntry = {\r\n id: this.generateId(),\r\n timestamp: new Date(),\r\n path,\r\n operation: 'create',\r\n command\r\n }\r\n\r\n this.push(entry)\r\n return entry\r\n }\r\n\r\n /**\r\n * Record a file modification (backs up original)\r\n */\r\n recordModify(path: string, command?: string): UndoEntry | null {\r\n if (!this.config.enabled || !existsSync(path)) {\r\n return null\r\n }\r\n\r\n // Check file size\r\n const stats = statSync(path)\r\n if (stats.size > this.config.maxFileSize) {\r\n // Too large, just record without backup\r\n const entry: UndoEntry = {\r\n id: this.generateId(),\r\n timestamp: new Date(),\r\n path,\r\n operation: 'modify',\r\n command\r\n }\r\n this.push(entry)\r\n return entry\r\n }\r\n\r\n // Create backup\r\n const id = this.generateId()\r\n const backupPath = join(this.undoDir, `${id}.backup`)\r\n\r\n try {\r\n copyFileSync(path, backupPath)\r\n\r\n const entry: UndoEntry = {\r\n id,\r\n timestamp: new Date(),\r\n path,\r\n operation: 'modify',\r\n backupPath,\r\n command\r\n }\r\n\r\n this.push(entry)\r\n return entry\r\n } catch {\r\n return null\r\n }\r\n }\r\n\r\n /**\r\n * Record a file deletion (backs up content)\r\n */\r\n recordDelete(path: string, command?: string): UndoEntry | null {\r\n if (!this.config.enabled || !existsSync(path)) {\r\n return null\r\n }\r\n\r\n const stats = statSync(path)\r\n if (stats.size > this.config.maxFileSize) {\r\n // Too large, just record without backup\r\n const entry: UndoEntry = {\r\n id: this.generateId(),\r\n timestamp: new Date(),\r\n path,\r\n operation: 'delete',\r\n command\r\n }\r\n this.push(entry)\r\n return entry\r\n }\r\n\r\n // Create backup\r\n const id = this.generateId()\r\n const backupPath = join(this.undoDir, `${id}.backup`)\r\n\r\n try {\r\n copyFileSync(path, backupPath)\r\n\r\n const entry: UndoEntry = {\r\n id,\r\n timestamp: new Date(),\r\n path,\r\n operation: 'delete',\r\n backupPath,\r\n command\r\n }\r\n\r\n this.push(entry)\r\n return entry\r\n } catch {\r\n return null\r\n }\r\n }\r\n\r\n /**\r\n * Auto-detect operation from command\r\n */\r\n recordFromCommand(command: string, paths: string[]): UndoEntry[] {\r\n const entries: UndoEntry[] = []\r\n\r\n // Detect operation type\r\n const isCreate = /^(touch|mkdir|cp|mv|>|>>)/.test(command) ||\r\n /^(echo|cat|printf).*>/.test(command)\r\n const isDelete = /^rm\\s/.test(command)\r\n const isModify = /^(sed|awk|vim|vi|nano|code)\\s/.test(command) ||\r\n /^(echo|cat).*>>/.test(command)\r\n\r\n for (const path of paths) {\r\n let entry: UndoEntry | null = null\r\n\r\n if (isDelete && existsSync(path)) {\r\n entry = this.recordDelete(path, command)\r\n } else if (isModify && existsSync(path)) {\r\n entry = this.recordModify(path, command)\r\n } else if (isCreate && !existsSync(path)) {\r\n entry = this.recordCreate(path, command)\r\n }\r\n\r\n if (entry) {\r\n entries.push(entry)\r\n }\r\n }\r\n\r\n return entries\r\n }\r\n\r\n /**\r\n * Undo the last operation\r\n */\r\n undo(): UndoResult {\r\n const entry = this.stack.pop()\r\n\r\n if (!entry) {\r\n return { success: false, message: 'Nothing to undo' }\r\n }\r\n\r\n return this.undoEntry(entry)\r\n }\r\n\r\n /**\r\n * Undo a specific entry\r\n */\r\n undoEntry(entry: UndoEntry): UndoResult {\r\n try {\r\n switch (entry.operation) {\r\n case 'create':\r\n // Undo create = delete the file\r\n if (existsSync(entry.path)) {\r\n unlinkSync(entry.path)\r\n return {\r\n success: true,\r\n message: `Deleted created file: ${entry.path}`,\r\n entry\r\n }\r\n }\r\n return {\r\n success: false,\r\n message: `File already deleted: ${entry.path}`,\r\n entry\r\n }\r\n\r\n case 'modify':\r\n // Undo modify = restore from backup\r\n if (entry.backupPath && existsSync(entry.backupPath)) {\r\n copyFileSync(entry.backupPath, entry.path)\r\n return {\r\n success: true,\r\n message: `Restored: ${entry.path}`,\r\n entry\r\n }\r\n }\r\n return {\r\n success: false,\r\n message: `No backup available for: ${entry.path}`,\r\n entry\r\n }\r\n\r\n case 'delete':\r\n // Undo delete = restore from backup\r\n if (entry.backupPath && existsSync(entry.backupPath)) {\r\n // Ensure directory exists\r\n const dir = dirname(entry.path)\r\n if (!existsSync(dir)) {\r\n mkdirSync(dir, { recursive: true })\r\n }\r\n copyFileSync(entry.backupPath, entry.path)\r\n return {\r\n success: true,\r\n message: `Restored deleted file: ${entry.path}`,\r\n entry\r\n }\r\n }\r\n return {\r\n success: false,\r\n message: `No backup available for: ${entry.path}`,\r\n entry\r\n }\r\n\r\n default:\r\n return {\r\n success: false,\r\n message: `Unknown operation: ${entry.operation}`,\r\n entry\r\n }\r\n }\r\n } catch (error: any) {\r\n return {\r\n success: false,\r\n message: `Undo failed: ${error.message}`,\r\n entry\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Undo all operations in the session\r\n */\r\n undoAll(): UndoResult[] {\r\n const results: UndoResult[] = []\r\n\r\n while (this.stack.length > 0) {\r\n results.push(this.undo())\r\n }\r\n\r\n return results\r\n }\r\n\r\n /**\r\n * Get the undo stack\r\n */\r\n getStack(): UndoEntry[] {\r\n return [...this.stack]\r\n }\r\n\r\n /**\r\n * Get stack size\r\n */\r\n size(): number {\r\n return this.stack.length\r\n }\r\n\r\n /**\r\n * Clear the stack (and backups)\r\n */\r\n clear(): void {\r\n // Delete backup files\r\n for (const entry of this.stack) {\r\n if (entry.backupPath && existsSync(entry.backupPath)) {\r\n try {\r\n unlinkSync(entry.backupPath)\r\n } catch { /* ignore */ }\r\n }\r\n }\r\n\r\n this.stack = []\r\n }\r\n\r\n /**\r\n * Push entry to stack\r\n */\r\n private push(entry: UndoEntry): void {\r\n this.stack.push(entry)\r\n\r\n // Limit stack size\r\n if (this.stack.length > this.config.maxStackSize) {\r\n const removed = this.stack.shift()\r\n // Clean up backup\r\n if (removed?.backupPath && existsSync(removed.backupPath)) {\r\n try {\r\n unlinkSync(removed.backupPath)\r\n } catch { /* ignore */ }\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Format stack for display\r\n */\r\n formatStack(): string {\r\n if (this.stack.length === 0) {\r\n return 'Undo stack is empty'\r\n }\r\n\r\n const lines: string[] = ['Undo Stack:', '']\r\n\r\n for (let i = this.stack.length - 1; i >= 0; i--) {\r\n const entry = this.stack[i]\r\n const hasBackup = entry.backupPath ? '✓' : '✗'\r\n const time = entry.timestamp.toLocaleTimeString()\r\n const op = entry.operation.padEnd(6)\r\n\r\n lines.push(`${i + 1}. [${time}] ${op} ${entry.path} (backup: ${hasBackup})`)\r\n if (entry.command) {\r\n lines.push(` └─ ${entry.command.slice(0, 60)}...`)\r\n }\r\n }\r\n\r\n return lines.join('\\n')\r\n }\r\n}\r\n","/**\r\n * Loop Detection\r\n * Detects when agents get stuck in repetitive patterns\r\n */\r\n\r\nexport interface LoopConfig {\r\n maxRepeats: number // Same command N times triggers alert\r\n maxTurns: number // Total commands before hard stop\r\n similarityThreshold: number // 0-1, how similar commands must be\r\n cooldownMs: number // Min time between identical commands\r\n windowSize: number // Commands to look back\r\n}\r\n\r\nexport interface LoopAlert {\r\n type: 'exact_repeat' | 'semantic_repeat' | 'tool_hammering' | 'max_turns'\r\n command: string\r\n count: number\r\n message: string\r\n}\r\n\r\ninterface CommandEntry {\r\n command: string\r\n timestamp: number\r\n normalized: string\r\n}\r\n\r\nconst DEFAULT_CONFIG: LoopConfig = {\r\n maxRepeats: 3,\r\n maxTurns: 100,\r\n similarityThreshold: 0.85,\r\n cooldownMs: 1000,\r\n windowSize: 20\r\n}\r\n\r\nexport class LoopDetector {\r\n private config: LoopConfig\r\n private history: CommandEntry[] = []\r\n private turnCount: number = 0\r\n\r\n constructor(config: Partial<LoopConfig> = {}) {\r\n this.config = { ...DEFAULT_CONFIG, ...config }\r\n }\r\n\r\n /**\r\n * Record a command and check for loops\r\n */\r\n check(command: string): LoopAlert | null {\r\n const now = Date.now()\r\n const normalized = this.normalize(command)\r\n\r\n this.turnCount++\r\n\r\n // Check max turns first\r\n if (this.turnCount >= this.config.maxTurns) {\r\n return {\r\n type: 'max_turns',\r\n command,\r\n count: this.turnCount,\r\n message: `Maximum turns reached (${this.config.maxTurns}). Session may be stuck.`\r\n }\r\n }\r\n\r\n // Check for exact repeats\r\n const exactMatches = this.history.filter(h => h.command === command)\r\n if (exactMatches.length >= this.config.maxRepeats) {\r\n return {\r\n type: 'exact_repeat',\r\n command,\r\n count: exactMatches.length + 1,\r\n message: `Command repeated ${exactMatches.length + 1} times: \"${command.slice(0, 50)}...\"`\r\n }\r\n }\r\n\r\n // Check cooldown (same command too fast)\r\n const lastSame = exactMatches[exactMatches.length - 1]\r\n if (lastSame && (now - lastSame.timestamp) < this.config.cooldownMs) {\r\n return {\r\n type: 'exact_repeat',\r\n command,\r\n count: 2,\r\n message: `Rapid repeat detected (${now - lastSame.timestamp}ms apart)`\r\n }\r\n }\r\n\r\n // Check for semantic repeats (similar commands)\r\n const recentWindow = this.history.slice(-this.config.windowSize)\r\n const similarCount = recentWindow.filter(h =>\r\n this.similarity(h.normalized, normalized) >= this.config.similarityThreshold\r\n ).length\r\n\r\n if (similarCount >= this.config.maxRepeats) {\r\n return {\r\n type: 'semantic_repeat',\r\n command,\r\n count: similarCount + 1,\r\n message: `Similar commands repeated ${similarCount + 1} times`\r\n }\r\n }\r\n\r\n // Check for tool hammering (same base command)\r\n const baseCommand = command.split(/\\s+/)[0]\r\n const toolCount = recentWindow.filter(h =>\r\n h.command.split(/\\s+/)[0] === baseCommand\r\n ).length\r\n\r\n if (toolCount >= this.config.maxRepeats * 2) {\r\n return {\r\n type: 'tool_hammering',\r\n command,\r\n count: toolCount + 1,\r\n message: `Tool \"${baseCommand}\" called ${toolCount + 1} times in last ${this.config.windowSize} commands`\r\n }\r\n }\r\n\r\n // Record this command\r\n this.history.push({ command, timestamp: now, normalized })\r\n\r\n // Trim history\r\n if (this.history.length > this.config.windowSize * 2) {\r\n this.history = this.history.slice(-this.config.windowSize)\r\n }\r\n\r\n return null\r\n }\r\n\r\n /**\r\n * Normalize command for comparison\r\n */\r\n private normalize(command: string): string {\r\n return command\r\n .toLowerCase()\r\n .replace(/[\"']/g, '') // Remove quotes\r\n .replace(/\\s+/g, ' ') // Normalize whitespace\r\n .replace(/\\d+/g, 'N') // Replace numbers\r\n .replace(/[a-f0-9]{8,}/gi, 'H') // Replace hashes\r\n .trim()\r\n }\r\n\r\n /**\r\n * Calculate similarity between two strings (Jaccard index on words)\r\n */\r\n private similarity(a: string, b: string): number {\r\n const wordsA = new Set(a.split(/\\s+/))\r\n const wordsB = new Set(b.split(/\\s+/))\r\n\r\n const intersection = new Set([...wordsA].filter(x => wordsB.has(x)))\r\n const union = new Set([...wordsA, ...wordsB])\r\n\r\n if (union.size === 0) return 1\r\n return intersection.size / union.size\r\n }\r\n\r\n /**\r\n * Get current turn count\r\n */\r\n getTurnCount(): number {\r\n return this.turnCount\r\n }\r\n\r\n /**\r\n * Get command frequency map\r\n */\r\n getFrequencyMap(): Map<string, number> {\r\n const freq = new Map<string, number>()\r\n for (const entry of this.history) {\r\n const base = entry.command.split(/\\s+/)[0]\r\n freq.set(base, (freq.get(base) || 0) + 1)\r\n }\r\n return freq\r\n }\r\n\r\n /**\r\n * Reset detector state\r\n */\r\n reset(): void {\r\n this.history = []\r\n this.turnCount = 0\r\n }\r\n\r\n /**\r\n * Get stats for reporting\r\n */\r\n getStats(): {\r\n turnCount: number\r\n uniqueCommands: number\r\n topCommands: [string, number][]\r\n } {\r\n const freq = this.getFrequencyMap()\r\n const sorted = [...freq.entries()].sort((a, b) => b[1] - a[1])\r\n\r\n return {\r\n turnCount: this.turnCount,\r\n uniqueCommands: freq.size,\r\n topCommands: sorted.slice(0, 5)\r\n }\r\n }\r\n}\r\n"],"mappings":"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","names":["existsSync","readFileSync","writeFileSync","mkdirSync","join","homedir","PolicyEngine","loadConfig","EventEmitter","EventEmitter","result","existsSync","readFileSync","homedir","join","writeFileSync","mkdirSync","spawn","EventEmitter","execFileSync","EventEmitter","EventEmitter","execFileSync","projectedInput","projectedOutput","inputCost","outputCost","mins","existsSync","mkdirSync","join","homedir","DEFAULT_CONFIG"]}
|