import { ConsentError } from './_errors.ts'; import { logger } from './_logger.ts'; export type ToolConsentMode = 'never' | 'once-per-server' | 'always'; export class ConsentManager { private approvedServers = new Set(); private deniedServers = new Set(); private log = logger.child({ component: 'ConsentManager' }); constructor(private mode: ToolConsentMode = 'once-per-server') { this.log.debug('Initialized', { mode }); } requiresPrompt(serverName: string): boolean { if (this.mode === 'never') { return false; } if (this.deniedServers.has(serverName)) { return true; } if (this.mode === 'always') { return true; } return !this.approvedServers.has(serverName); } shouldCacheConsent(): boolean { return this.mode !== 'always'; } registerDecision(serverName: string, approved: boolean): void { this.deniedServers.delete(serverName); this.approvedServers.delete(serverName); if (approved) { this.approvedServers.add(serverName); this.log.debug('Consent granted', { server: serverName }); return; } this.deniedServers.add(serverName); this.log.debug('Consent denied', { server: serverName }); } ensureApproved(serverName: string): void { if (this.mode === 'never') { return; } if (this.deniedServers.has(serverName)) { throw new ConsentError(serverName, { denied: true }); } if (!this.approvedServers.has(serverName)) { throw new ConsentError(serverName, { requiresApproval: true }); } if (this.mode === 'always') { this.approvedServers.delete(serverName); } } clear(serverName?: string): void { if (serverName) { this.approvedServers.delete(serverName); this.deniedServers.delete(serverName); this.log.debug('Cleared consent for server', { server: serverName }); return; } this.approvedServers.clear(); this.deniedServers.clear(); this.log.debug('Cleared all consent records'); } }