@wispbit/local 1.0.89 → 1.0.90

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.
Files changed (2) hide show
  1. package/cli-bundle.js +2 -2
  2. package/package.json +1 -1
package/cli-bundle.js CHANGED
@@ -293,7 +293,7 @@ ${e}`);let r={id:String(++this.requestId),command:"shutdown"};this.serverProcess
293
293
  ${u}`:r.message;c(new Error(l))}else a(r);else if(i)if(i==="success")a(o);else{let u=this.getRecentStderr(),l=u?`${s||"Request failed"}. Runtime logs:
294
294
  ${u}`:s||"Request failed";c(new Error(l))}else Ae.log("[Runtime] Unknown response format"),c(new Error("Unknown response format"))}getRuntimePath(){let e=globalThis.__POWERLINT_ASSETS__;if(!e?.runtime)throw new Error("Runtime binary not found. This should be set by the Bun executable build. Make sure you're running the compiled Bun executable, not the source code directly.");return Ae.log(`[RuntimeProvider] Using runtime from Bun executable: ${e.runtime}`),e.runtime}};import{homedir as OMt}from"os";import{join as CMt}from"path";import{promises as QW}from"fs";import*as Fy from"path";var Hg=class{groups;constructor(e){this.groups=e}patternCount(){return this.groups.length}patternCost(){return this.groups.reduce((e,n)=>e+n.cost*n.fragments.length,0)}patternDensity(){let e=this.patternCount();return e>0?this.patternCost()/e:0}fragmentOccurrences(e){let n=this.groups.find(r=>r.hash===e);return n?n.fragments.length:0}patternHash(e){return this.groups[e]?.hash}fileCount(){let e=new Set;for(let n of this.groups)for(let r of n.fragments)e.add(r.file);return e.size}title(e){let n=this.groups.find(o=>o.hash===e);if(!n||n.fragments.length===0)return"Unknown pattern";let r=n.fragments[0];return`${r.file.split("/").pop()||r.file}:${r.start_line+1}-${r.end_line+1} (${n.fragments.length} occurrences)`}fragmentsByFile(e){let n=new Map,r=this.groups.find(i=>i.hash===e);if(!r)return n;for(let i of r.fragments){let o=n.get(i.file)||[];o.push(i),n.set(i.file,o)}return n}getGroups(){return this.groups}async getFragmentText(e,n){let r=Fy.join(n,e.file),i=await QW.readFile(r,"utf-8");return Buffer.from(i,"utf-8").slice(e.start_index,e.end_index).toString("utf-8")}getFragmentsInFile(e){let n=[];for(let r of this.groups)for(let i of r.fragments)i.file===e&&n.push(i);return n}getStatistics(){let e=this.groups.reduce((n,r)=>n+r.fragments.length,0);return{patternCount:this.patternCount(),totalCost:this.patternCost(),averageCost:this.patternDensity(),fileCount:this.fileCount(),totalFragments:e}}async extractFragmentSnippet(e,n,r){let i;if(r.has(e.file))i=r.get(e.file);else{let o=Fy.join(n,e.file);i=await QW.readFile(o,"utf-8"),r.set(e.file,i)}return Ph(i,{start:{line:e.start_line},end:{line:e.end_line}},20)}async loadFileContents(e){let n=new Map,r=new Set;for(let i of this.groups)for(let o of i.fragments)r.add(o.file);return await Promise.all(Array.from(r).map(async i=>{let o=Fy.join(e,i),s=await QW.readFile(o,"utf-8");n.set(i,s)})),n}extractFragmentContext(e,n,r=20){let i=n.get(e.file);if(!i)throw new Error(`File content not available for ${e.file}`);let o=i.split(`
295
295
  `),s=e.start_line,a=Math.max(0,s-r),c=Math.min(o.length-1,s+r),u=o.slice(a,c+1).join(`
296
- `);return{file:e.file,range:{start:{line:a+1,column:1},end:{line:c+1,column:o[c]?.length||1}},text:u}}extractGroupContext(e,n,r=20){return e.fragments.map(i=>this.extractFragmentContext(i,n,r))}clusterBySharedFiles(){if(this.groups.length===0)return[];let e=new Map;this.groups.forEach((o,s)=>{let a=new Set;for(let c of o.fragments)a.add(c.file);for(let c of a)e.has(c)||e.set(c,[]),e.get(c).push(s)});let n=new eK(this.groups.length);for(let o of e.values())for(let s=1;s<o.length;s++)n.union(o[0],o[s]);let r=new Map;for(let o=0;o<this.groups.length;o++){let s=n.find(o);r.has(s)||r.set(s,[]),r.get(s).push(o)}let i=[];for(let o of r.values()){let s=o.map(c=>this.groups[c]),a=new Set;for(let c of s)for(let u of c.fragments)a.add(u.file);i.push({groups:s,files:a})}return i}},eK=class{parent=new Map;rank=new Map;constructor(e){for(let n=0;n<e;n++)this.parent.set(n,n),this.rank.set(n,0)}find(e){return this.parent.get(e)!==e&&this.parent.set(e,this.find(this.parent.get(e))),this.parent.get(e)}union(e,n){let r=this.find(e),i=this.find(n);if(r===i)return;let o=this.rank.get(r),s=this.rank.get(i);o<s?this.parent.set(r,i):o>s?this.parent.set(i,r):(this.parent.set(i,r),this.rank.set(r,o+1))}};var ky=class t{static INDEX_FOLDER=CMt(OMt(),".wispbit","indexes");provider;initialized=!1;constructor(e){this.provider=e}async initializeProvider(){this.initialized||(await this.provider.initialize(),this.initialized=!0)}async initialize(e){await this.initializeProvider();let n=await this.provider.sendRequest({command:"initialize_workspaces",workspace_configs:e.workspaceConfigs.map(r=>({workspace_root:r.workspaceRoot,base_commit_sha:r.baseCommitSha})),index_folder:t.INDEX_FOLDER,ignores:e.ignores});if("error"in n&&n.error)throw new Error(`Failed to initialize workspaces: ${n.error}`);return{fullScan:n.full_scan||!1}}async getDuplicates(e,n){await this.initializeProvider();let r=await this.provider.sendRequest({command:"get_duplicates",workspace_root:e,file_path:n});if("error"in r&&r.error)throw new Error(`Failed to get duplicates: ${r.error}`);let i=r;return new Hg(i)}async getDuplicatesForFile(e,n){await this.initializeProvider();let r=await this.provider.sendRequest({command:"get_duplicates",workspace_root:e,file_path:n});if("error"in r&&r.error)throw new Error(`Failed to get duplicates for file: ${r.error}`);let i=r;return new Hg(i)}invalidationQueue=Promise.resolve();async invalidateFiles(e,n){let r=this.invalidationQueue.then(async()=>{await this.initializeProvider();let i=Date.now(),o=await this.provider.sendRequest({command:"invalidate_files",workspace_root:e,files:n.map(a=>({file_path:a.filePath,content_sha:a.contentSha}))}),s=Date.now()-i;if(Ae.log(`[RuntimeManager] Invalidated ${n.length} file(s) in ${s}ms for ${e}`),"error"in o&&o.error)throw new Error(`Failed to invalidate files: ${o.error}`)}).catch(i=>{throw Ae.log(`[RuntimeManager] Invalidation failed: ${i.message}`),i});this.invalidationQueue=r.catch(()=>{}),await r}isInitialized(){return this.initialized}async shutdown(){this.initialized&&(Ae.log("[RuntimeManager] Shutdown requested, waiting for in-flight operations..."),await this.invalidationQueue.catch(()=>{}),Ae.log("[RuntimeManager] All operations complete, shutting down runtime..."),await this.provider.shutdown(),this.initialized=!1)}};var Hy=class{contexts=new Map;workspacePath;apiKey;lspClient;sharedRuntimeManager=null;RULES_CACHE_TTL_MS=300*1e3;constructor(e){this.workspacePath=e.workspacePath,this.apiKey=e.apiKey,this.lspClient=e.lspClient}async discoverAndInitialize(e,n){let r=await iO(this.workspacePath),i=[];for(let s of r){let a=await this.initializeContext(s);if("error"in a){n?.(s,new Error(a.error));continue}let c=a,{baseCommitSha:u}=await ga(s);i.push({repoRoot:s,context:c,baseCommitSha:u}),this.contexts.set(s,c),e?.(s,c)}let o=[];for(let{repoRoot:s,context:a,baseCommitSha:c}of i)a.config.getEnableDeduplicator()&&o.push({workspaceRoot:s,baseCommitSha:c});if(o.length>0){let s=new By(o[0].workspaceRoot);this.sharedRuntimeManager=new ky(s);for(let{context:a}of i)a.config.getEnableDeduplicator()&&(a.runtimeManager=this.sharedRuntimeManager,a.duplicateManager=new Gy(this.sharedRuntimeManager,a.config,a.environment))}}async initializeContext(e){let n=Kr.initialize({workspaceRoot:e});if(!n)return{error:"Not in a git repository"};let r=await $o.initialize(n,{apiKey:this.apiKey,lspClient:this.lspClient});if("failed"in r)return{error:`Config initialization failed: ${r.error}`};let i=r,o=new jo(i,n),s=new zr,a=new La(i,n,s);return{repoRoot:e,environment:n,config:i,ruleProvider:o,eventEmitter:s,ruleExecutor:a,cachedRules:null,rulesById:new Map,rulesCacheTimestamp:0,rulesLoadingPromise:null,lastCommitSelector:null,currentExecutionRules:[],completedRulesCount:0,isExecuting:!1,currentExecutionPromise:null,runtimeManager:null,duplicateManager:null,executionContext:null}}findContextForFile(e){let n=e.toLowerCase();return Array.from(this.contexts.entries()).filter(([i])=>{let o=i.toLowerCase();return n.startsWith(o+IMt)||n===o}).sort((i,o)=>o[0].length-i[0].length)[0]?.[1]||null}getAllContexts(){return Array.from(this.contexts.values())}getRepoCount(){return this.contexts.size}hasRepositories(){return this.contexts.size>0}getContext(e){return this.contexts.get(e)}async initializeRuntimeManager(){if(!this.sharedRuntimeManager)return!1;let e=[],n=[];for(let r of this.contexts.values())if(r.config.getEnableDeduplicator()){let{baseCommitSha:i}=await ga(r.repoRoot);e.push({workspaceRoot:r.repoRoot,baseCommitSha:i}),n.length===0&&(n=r.config.getIgnoredGlobs())}return e.length===0?!1:(await this.sharedRuntimeManager.initialize({workspaceConfigs:e,ignores:n}),!0)}async shutdown(){for(let e of this.contexts.values())e.ruleExecutor.clearCache(),e.duplicateManager&&e.duplicateManager.clearCache();this.sharedRuntimeManager&&(await this.sharedRuntimeManager.shutdown(),this.sharedRuntimeManager=null),this.contexts.clear()}};function bWe(t,e,n){if(t.fingerprint)return`${e}:${t.fingerprint}`;let r=t.text?.slice(0,100)||"",i=`${t.range.start.line}:${t.range.start.column}-${t.range.end.line}:${t.range.end.column}`;return`${e}:${n}:${i}:${PMt(r)}`}function PMt(t){let e=0;for(let n=0;n<t.length;n++){let r=t.charCodeAt(n);e=(e<<5)-e+r,e=e&e}return e.toString(36)}function vWe(t){return t.end.line-t.start.line+1>20?{start:{line:t.start.line-1,character:t.start.column-1},end:{line:t.start.line-1,character:Number.MAX_SAFE_INTEGER}}:{start:{line:t.start.line-1,character:t.start.column-1},end:{line:t.end.line-1,character:t.end.column-1}}}var tK=class{connection;documentManager;repositoryContextManager;workspacePath;apiKey;lspClient;batchProgressReporter=null;batchProgressToken="wispbit-batch-lint";progressTokenCreated=!1;fixQueue=[];isProcessingFix=!1;branchCheckTimer=null;BRANCH_CHECK_DEBOUNCE_MS=1e3;branchCheckInterval=null;BRANCH_CHECK_INTERVAL_MS=3e4;executionDebounceTimer=null;EXECUTION_DEBOUNCE_MS=1e3;changedFiles=new Set;hasRunInitialCheck=!1;isExecutingInitial=!1;dismissalsLoadingPromises=new Map;fixesLoadingPromises=new Map;localDismissals=[];constructor(e){this.workspacePath=e.workspacePath,this.apiKey=e.apiKey,this.lspClient=e.lspClient,this.connection=(0,mr.createConnection)(mr.ProposedFeatures.all,process.stdin,process.stdout),this.documentManager=new Vy,this.repositoryContextManager=new Hy({workspacePath:this.workspacePath,apiKey:this.apiKey,lspClient:this.lspClient}),this.registerHandlers()}addLocalDismissal(e){this.localDismissals.push(e)}isLocallyDismissed(e,n,r,i,o){return this.localDismissals.some(s=>s.matchId===o&&s.uri===e?!0:s.uri===e&&s.ruleId===n?s.startLine<=i&&s.endLine>=r:!1)}clearLocalDismissalsForUri(e){this.localDismissals=this.localDismissals.filter(n=>n.uri!==e)}clearAllLocalDismissals(){this.localDismissals=[]}findContextForFile(e){let n=Uo(e);return this.repositoryContextManager.findContextForFile(n)}pathToNormalizedUri(e){let n=MMt(e).toString();return decodeURIComponent(n)}getDiagnosticsForUri(e){let n=this.documentManager.getDiagnostics(e);if(n.length===0){let r=oi(e),i=this.documentManager.getAllDiagnosticUris();for(let o of i)if(oi(o)===r){n=this.documentManager.getDiagnostics(o);break}}return n}handleRuleComplete(e,n,r){if(!e.isExecuting||e.currentExecutionRules.length===0)return;e.completedRulesCount++;let i=Math.round(e.completedRulesCount/e.currentExecutionRules.length*100);this.updateBatchProgress(i,n)}async handleRuleFileComplete(e,n,r,i){if(!e.isExecuting||e.currentExecutionRules.length===0)return;let o=e.currentExecutionRules.find(u=>u.id===n);if(!o){this.connection.console.log(`[${e.repoRoot}] Warning: Rule ${n} not found in current execution`);return}let s=IE(e.repoRoot,r),a=this.pathToNormalizedUri(s);if(i.length===0){this.updateDiagnosticsForRule(a,o.internalId,[]);return}let c=await this.createDiagnosticsForFile(e,r,o.internalId,i,e.currentExecutionRules);this.updateDiagnosticsForRule(a,o.internalId,c)}async handleRuleFilePartial(e,n,r,i,o){if(!e.isExecuting||e.currentExecutionRules.length===0)return;let s=e.currentExecutionRules.find(l=>l.internalId===n);if(!s){this.connection.console.log(`[${e.repoRoot}] Warning: Rule ${n} not found in current execution`);return}let a=IE(e.repoRoot,r),c=this.pathToNormalizedUri(a);if(i.length===0){this.updateDiagnosticsForRule(c,s.internalId,[]);return}let u=await this.createDiagnosticsForFile(e,r,s.internalId,i,e.currentExecutionRules);this.updateDiagnosticsForRule(c,s.internalId,u)}async convertDuplicateResultsToDiagnostics(e,n,r,i){let o=[];for(let s of n)for(let a of s.matches){let c=bWe(a,"DUPLICATE",i);if(this.isLocallyDismissed(i,"DUPLICATE",a.range.start.line,a.range.end.line,c))continue;let u=vWe(a.range),l=a.evidence?.map(f=>{let T=IE(e.repoRoot,f.file.path);return{location:{uri:this.pathToNormalizedUri(T),range:{start:{line:f.range.start.line-1,character:f.range.start.column-1},end:{line:f.range.end.line-1,character:f.range.end.column-1}}},message:"Duplicate location"}}),E=null;a.edits&&a.edits.length>0&&(E=await this.computeFixForMatch(a,e).catch(f=>(this.connection.console.log(`Warning: Failed to compute fix for duplicate: ${f}`),null)));let d={range:u,severity:mr.DiagnosticSeverity.Warning,message:a.description||"Duplicate code detected",code:"DUPLICATE",source:"wispbit",relatedInformation:l,data:{uri:i,match:a,matchId:c,fix:E?{diff:E.diff,diffs:E.diffs,autofix:!1}:null,ruleId:"DUPLICATE",filePath:a.file.path,rule:{id:"DUPLICATE",displayId:"DUPLICATE",summary:null}}};o.push(d)}return o}async handleDuplicateFileComplete(e,n,r,i,o){let s=IE(e.repoRoot,n),a=this.pathToNormalizedUri(s),c=await this.createDiagnosticsForFile(e,n,"DUPLICATE",r,[],this.convertDuplicateResultsToDiagnostics.bind(this));this.updateDiagnosticsForRule(a,"DUPLICATE",c)}setupProgressListenersForContext(e){e.eventEmitter.on("rules:progress",n=>{this.updateBatchProgress(n.percentage,n.ruleId)}),e.eventEmitter.on("rules:rule-complete",n=>{this.handleRuleComplete(e,n.ruleId,n.matches)}),e.eventEmitter.on("rules:rule-file-complete",async n=>{await this.handleRuleFileComplete(e,n.ruleId,n.filePath,n.matches)}),e.eventEmitter.on("rules:rule-file-partial",async n=>{await this.handleRuleFilePartial(e,n.ruleId,n.filePath,n.matches,n.totalMatches)})}normalizePathSeparators(e){return e.replace(/\\/g,"/")}toRelativePath(e,n){if(!n){let r=this.pathToNormalizedUri(e);n=this.findContextForFile(r)||void 0}return n?this.normalizePathSeparators(yWe(n.repoRoot,e)):this.normalizePathSeparators(yWe(this.workspacePath,e))}updateDiagnosticsForRule(e,n,r){this.documentManager.setDiagnosticsForRule(e,n,r);let i=this.documentManager.getDiagnostics(e);this.connection.sendDiagnostics({uri:e,diagnostics:i})}removeDiagnosticByMatchId(e,n){let r=this.documentManager.getDiagnostics(e),i=r.find(a=>a.data?.matchId===n);if(!i)return;let o=i.data?.rule?.id;if(!o)return;let s=r.filter(a=>a.data?.rule?.id===o&&a.data?.matchId!==n);this.updateDiagnosticsForRule(e,o,s)}clearAllDiagnostics(){let e=this.documentManager.getAllDiagnosticUris();for(let n of e)this.clearDiagnosticsForFile(n);this.clearAllLocalDismissals()}clearDiagnosticsForFile(e){this.documentManager.clearDiagnostics(e),this.clearLocalDismissalsForUri(e),this.connection.sendDiagnostics({uri:e,diagnostics:[]})}handleDocumentChangesWithRanges(e,n){let r=this.documentManager.getDiagnostics(e);if(r.length===0)return;this.connection.console.log(`Document changed: ${e}, ${n.length} change(s), ${r.length} diagnostic(s)`);let i=new Set;for(let o of n){if(!o.range){this.connection.console.log("Full document change detected - removing all diagnostics");for(let s of r)s.data?.matchId&&i.add(s.data.matchId);continue}for(let s of r)this.rangesOverlap(o.range,s.range)&&s.data?.matchId&&i.add(s.data.matchId)}for(let o of i)this.removeDiagnosticByMatchId(e,o);i.size>0&&this.connection.console.log(`Removed ${i.size} diagnostic(s) due to document edits`)}rangesOverlap(e,n){return e.end.line<n.start.line||e.start.line>n.end.line?!1:e.start.line<=n.end.line&&e.end.line>=n.start.line}async createDiagnosticsForFile(e,n,r,i,o,s){let a=i.length;this.documentManager.hasDismissals(n)||await this.loadDismissalsForFile(e,n),this.documentManager.hasFixes(n)||await this.loadFixesForFile(e,n);let c={ruleId:r,matches:i},u=this.filterDismissedResults([c],n),l=u[0]?.matches.length||0,E=a-l,d=await this.filterFixedResults(e,u,n),f=d[0]?.matches.length||0,T=l-f,p=IE(e.repoRoot,n),S=this.pathToNormalizedUri(p),m=await(s||this.convertResultsToDiagnostics.bind(this))(e,d,o,S);if(a>0){let h=o.find(P=>P.internalId===r)?.id||r,C=[];E>0&&C.push(`${E} dismissed`),T>0&&C.push(`${T} fixed`),C.length>0?this.connection.console.log(`[${e.repoRoot}] ${n}: ${m.length} diagnostic(s) created, ${C.join(", ")} (rule: ${h})`):this.connection.console.log(`[${e.repoRoot}] ${n}: ${m.length} diagnostic(s) created (rule: ${h})`)}return m}async getFileContent(e){let n=this.pathToNormalizedUri(e),r=this.documentManager.getDocument(n);return r?r.getText():await Yy.access(e).then(()=>!0).catch(()=>!1)?await Yy.readFile(e,"utf-8").catch(()=>null):null}async computeFixForMatch(e,n){if(!e.edits||e.edits.length===0)return null;let r=await jc(e.edits,e.file.path,n.repoRoot,o=>this.getFileContent(o));return r?{fileChanges:r.fileChanges.map(o=>({...o,fileUri:this.pathToNormalizedUri(o.filePath)})),diff:r.diff,diffs:r.diffs}:null}async loadRulesWithCache(e){let r=Date.now()-e.rulesCacheTimestamp;return e.cachedRules&&r<this.repositoryContextManager.RULES_CACHE_TTL_MS?(this.connection.console.log(`[${e.repoRoot}] Using cached rules (age: ${Math.round(r/1e3)}s / ${this.repositoryContextManager.RULES_CACHE_TTL_MS/1e3}s)`),e.cachedRules):e.rulesLoadingPromise?(this.connection.console.log(`[${e.repoRoot}] Rules are already being loaded, waiting for existing request...`),e.rulesLoadingPromise):(this.connection.console.log(`[${e.repoRoot}] Loading fresh rules from API...`),e.rulesLoadingPromise=e.ruleProvider.loadAllRules().then(i=>{let o=i.filter(s=>s.execution==="llm");e.cachedRules=o,e.rulesCacheTimestamp=Date.now(),e.rulesById.clear();for(let s of o)e.rulesById.set(s.id,s);if(this.connection.console.log(`[${e.repoRoot}] Loaded ${o.length} rules (cache valid for ${this.repositoryContextManager.RULES_CACHE_TTL_MS/1e3}s)`),o.length>0){this.connection.console.log(`[${e.repoRoot}] Fetched rules:`);for(let s of o){let a=s.autofix||!1,c="";a&&(c=" (autofix)"),this.connection.console.log(`[${e.repoRoot}] - ${s.id}: ${s.message}${c}`)}}return o}).finally(()=>{e.rulesLoadingPromise=null}),await e.rulesLoadingPromise)}async loadDismissalsForFile(e,n){if(this.documentManager.hasDismissals(n))return;let r=this.dismissalsLoadingPromises.get(n);if(r)return await r;let i=(async()=>{let s=(await e.ruleProvider.getDismissals([n])).map(a=>({ruleId:a.ruleId,file:a.match.file.path,startLine:a.match.range.start.line,endLine:a.match.range.end.line,fingerprint:a.match.fingerprint,dismissedAt:a.createdAt,dismissalId:a.dismissalId}));this.documentManager.setDismissals(n,s)})().finally(()=>{this.dismissalsLoadingPromises.delete(n)});return this.dismissalsLoadingPromises.set(n,i),await i}async loadFixesForFile(e,n){if(this.documentManager.hasFixes(n))return;let r=this.fixesLoadingPromises.get(n);if(r)return await r;let i=(async()=>{let o=await e.ruleProvider.getFixes([n]);this.documentManager.setFixes(n,o)})().finally(()=>{this.fixesLoadingPromises.delete(n)});return this.fixesLoadingPromises.set(n,i),await i}filterDismissedResults(e,n){let r=this.documentManager.getDismissals(n);return r.length===0?e:e.map(i=>{let o=r.filter(u=>u.ruleId===i.ruleId);if(o.length===0)return i;let s=i.matches.map(u=>({file:n,startLine:u.range.start.line,endLine:u.range.end.line,fingerprint:u.fingerprint})),c=Nh(s,o).map(u=>i.matches.find(l=>l.range.start.line===u.startLine&&l.range.end.line===u.endLine&&l.fingerprint===u.fingerprint));return{...i,matches:c}})}async filterFixedResults(e,n,r){let i=this.documentManager.getFixes(r);if(i.length===0)return n;this.connection.console.log(`[${e.repoRoot}] Filtering fixes for ${r}: ${i.length} fix(es) loaded`);let o=IE(e.repoRoot,r),s=await this.getFileContent(o);return s===null?n:n.map(a=>{let c=i.filter(S=>S.ruleId===a.ruleId);if(c.length===0)return a;let u=new Set;for(let S of c)S.match?.edits?.some(O=>O.oldString&&C1(s,O.oldString))&&S.match.fingerprint&&u.add(S.match.fingerprint);let l=c.length-u.size;u.size>0&&this.connection.console.log(`[${e.repoRoot}] ${r}: ${u.size} fix(es) reverted, ${l} still active`);let E=a.matches.map(S=>({file:r,startLine:S.range.start.line,endLine:S.range.end.line,fingerprint:S.fingerprint})),d=c.filter(S=>!S.match.fingerprint||!u.has(S.match.fingerprint)).map(S=>({file:r,startLine:S.match.range.start.line,endLine:S.match.range.end.line,fingerprint:S.match.fingerprint})),T=Nh(E,d).map(S=>a.matches.find(m=>m.range.start.line===S.startLine&&m.range.end.line===S.endLine&&m.fingerprint===S.fingerprint)),p=a.matches.length-T.length;return p>0&&this.connection.console.log(`[${e.repoRoot}] ${r}: Filtered out ${p} match(es) with active fixes`),{...a,matches:T}})}async convertResultsToDiagnostics(e,n,r,i){let o=[],s=new Set;for(let a of n){let c=r.find(u=>u.internalId===a.ruleId);if(!c){this.connection.console.log(`Warning: Could not find rule with internal ID ${a.ruleId}`);continue}for(let u of a.matches){let l=`${u.range.start.line}-${u.range.end.line}`;if(s.has(l))continue;s.add(l);let E=bWe(u,c.internalId,i);if(this.isLocallyDismissed(i,c.internalId,u.range.start.line,u.range.end.line,E))continue;let d=null;u.edits&&u.edits.length>0&&(d=await this.computeFixForMatch(u,e).catch(p=>(this.connection.console.log(`Warning: Failed to compute fix for match: ${p}`),null)));let T={range:vWe(u.range),severity:mr.DiagnosticSeverity.Warning,message:u.description||c.message,code:c.id,codeDescription:{href:`https://app.wispbit.com/rules/${c.internalId}`},source:"wispbit",data:{uri:i,match:u,matchId:E,fix:d?{diff:d.diff,diffs:d.diffs,autofix:c.autofix||!1}:null,rule:{id:c.internalId,displayId:c.id,summary:c.summary||null}}};o.push(T)}}return o}triggerExecution(){this.executionDebounceTimer&&(clearTimeout(this.executionDebounceTimer),this.executionDebounceTimer=null),this.executionDebounceTimer=setTimeout(()=>{this.executionDebounceTimer=null,this.executeQueuedFiles()},this.EXECUTION_DEBOUNCE_MS)}lintDocument(e){if(!this.documentManager.getDocument(e)){this.connection.console.log(`Document not found: ${e}`);return}let r=Uo(e),i=this.toRelativePath(r);this.connection.console.log(`File changed: ${i}`),this.changedFiles.add(e),this.triggerExecution()}async executeQueuedFiles(){let e=this.repositoryContextManager.getAllContexts();if(e.length===0){this.connection.console.log("No repositories found, skipping execution");return}if(!this.hasRunInitialCheck){if(this.isExecutingInitial){this.connection.console.log("Initial check already in progress, files will be queued for next run");return}this.changedFiles.clear(),this.isExecutingInitial=!0;try{await this.repositoryContextManager.initializeRuntimeManager()&&this.connection.console.log("RuntimeManager initialized successfully"),this.hasRunInitialCheck=!0,this.cleanupProgress(),await this.startBatchProgress(0);try{for(let i of e)await this.executeForContext(i,null);this.cleanupProgress()}catch(i){this.connection.console.error(`Error executing rules: ${i.message} ${i.stack}`),await CE(i),this.cleanupProgress()}}finally{this.isExecutingInitial=!1}}else{let r=Array.from(this.changedFiles);if(this.changedFiles.clear(),r.length===0){this.connection.console.log("No files to check, skipping incremental execution");return}this.connection.console.log(`Incremental check for ${r.length} file(s)`),await this.startBatchProgress(0);try{for(let i of e)await this.executeForContext(i,r);this.cleanupProgress()}catch(i){this.connection.console.error(`Error executing rules: ${i.message} ${i.stack}`),await CE(i),this.cleanupProgress()}}}async executeForContext(e,n){e.isExecuting=!0;try{let r=await this.loadRulesWithCache(e);e.completedRulesCount=0,e.currentExecutionRules=r;let{commitSelector:i,include:o}=await ga(e.repoRoot);e.lastCommitSelector=i;let s=await Pa.initialize(e.config,e.environment,"diff",e.eventEmitter,void 0,{include:o,commitSelector:i,skipPreExistingViolations:!0});if(e.executionContext=s,e.runtimeManager){let a=[];if(n!==null&&n.length>0?a=n.filter(c=>this.findContextForFile(c)?.repoRoot===e.repoRoot).map(c=>({filePath:this.toRelativePath(Uo(c),e)})):a=s.filePaths.map(c=>({filePath:c})),a.length>0){this.connection.console.log(`[${e.repoRoot}] Starting invalidation of ${a.length} file(s) in RuntimeManager...`);let c=Date.now();await e.runtimeManager.invalidateFiles(e.repoRoot,a);let u=Date.now()-c;this.connection.console.log(`[${e.repoRoot}] Completed invalidation in ${u}ms`)}}if(n!==null&&n.length>0){let a=n.filter(c=>this.findContextForFile(c)?.repoRoot===e.repoRoot);if(a.length===0){this.connection.console.log(`[${e.repoRoot}] No changed files in this repository, skipping`);return}for(let c of a){let u=this.toRelativePath(Uo(c),e);this.connection.console.log(`[${e.repoRoot}] Executing rules for ${u}`),e.completedRulesCount=0;let l=e.ruleExecutor.execute(r,s,{relativePath:u,emitErrors:!0}),E=e.duplicateManager?e.duplicateManager.execute(s,u,(d,f,T,p)=>{this.handleDuplicateFileComplete(e,d,f,T,p)}):Promise.resolve();await Promise.all([l,E])}}else{let a=e.ruleExecutor.execute(r,s,{emitErrors:!0}),c=e.duplicateManager?(async()=>{let u=e.duplicateManager;this.connection.console.log(`[${e.repoRoot}] Starting duplicate detection...`);let l=Date.now();await u.execute(s,void 0,(d,f,T,p)=>{this.handleDuplicateFileComplete(e,d,f,T,p)});let E=Date.now()-l;this.connection.console.log(`[${e.repoRoot}] Completed duplicate detection in ${E}ms`)})():Promise.resolve();await Promise.all([a,c])}}catch(r){this.connection.console.error(`[${e.repoRoot}] Error executing rules: ${r.message} ${r.stack}`),await CE(r)}finally{e.isExecuting=!1}}async startBatchProgress(e){if(this.batchProgressReporter)this.batchProgressReporter.report(e,"Checking workspace");else try{this.progressTokenCreated||(await this.connection.sendRequest("window/workDoneProgress/create",{token:this.batchProgressToken}),this.progressTokenCreated=!0),this.batchProgressReporter=await this.connection.window.createWorkDoneProgress(),this.batchProgressReporter.begin("wispbit",e,"Checking workspace",!1)}catch(n){this.connection.console.log(`Failed to create batch progress: ${n}`)}}cleanupProgress(){this.batchProgressReporter&&(this.batchProgressReporter.done(),this.batchProgressReporter=null)}updateBatchProgress(e,n){if(!this.batchProgressReporter)return;let r=`Checking workspace (${n})`;this.batchProgressReporter.report(e,r)}async processFixQueue(){if(!this.isProcessingFix){for(this.isProcessingFix=!0;this.fixQueue.length>0;){let e=this.fixQueue.shift();e&&await e()}this.isProcessingFix=!1}}handleQuickfix(e){let{uri:n,matchId:r}=e[0];this.fixQueue.push(async()=>{await this.applyQuickfix(n,r)}),this.processFixQueue()}async applyQuickfix(e,n){let i=this.getDiagnosticsForUri(e).find(T=>T.data?.matchId===n);if(!i){this.connection.window.showErrorMessage("Could not apply fix"),this.connection.console.error(`Diagnostic not found for matchId: ${n}`);return}let o=i.data?.match,s=i.data?.rule;if(!o?.edits||o.edits.length===0){this.connection.window.showErrorMessage("No fix available"),this.connection.console.error(`No fix available for matchId ${n}, rule ${s?.id}`);return}let a=this.findContextForFile(e);if(!a){this.connection.window.showErrorMessage("File is not in any repository"),this.connection.console.error(`No repository context found for ${e}`);return}let c=Uo(e),u=this.toRelativePath(c,a);this.connection.console.log(`[${a.repoRoot}] Applying fix for matchId ${n}, rule ${s?.id}`);let l=await this.computeFixForMatch(o,a);if(!l){this.connection.window.showErrorMessage("Failed to compute fix"),this.connection.console.error(`[${a.repoRoot}] Failed to compute fix for matchId ${n}, rule ${s?.id}`);return}let E=Uo(e),d=[];for(let T of l.fileChanges){let S=T.filePath===E?e:T.fileUri,m=this.documentManager.getDocument(S),O=m?m.lineCount:T.oldContent.split(`
296
+ `);return{file:e.file,range:{start:{line:a+1,column:1},end:{line:c+1,column:o[c]?.length||1}},text:u}}extractGroupContext(e,n,r=20){return e.fragments.map(i=>this.extractFragmentContext(i,n,r))}clusterBySharedFiles(){if(this.groups.length===0)return[];let e=new Map;this.groups.forEach((o,s)=>{let a=new Set;for(let c of o.fragments)a.add(c.file);for(let c of a)e.has(c)||e.set(c,[]),e.get(c).push(s)});let n=new eK(this.groups.length);for(let o of e.values())for(let s=1;s<o.length;s++)n.union(o[0],o[s]);let r=new Map;for(let o=0;o<this.groups.length;o++){let s=n.find(o);r.has(s)||r.set(s,[]),r.get(s).push(o)}let i=[];for(let o of r.values()){let s=o.map(c=>this.groups[c]),a=new Set;for(let c of s)for(let u of c.fragments)a.add(u.file);i.push({groups:s,files:a})}return i}},eK=class{parent=new Map;rank=new Map;constructor(e){for(let n=0;n<e;n++)this.parent.set(n,n),this.rank.set(n,0)}find(e){return this.parent.get(e)!==e&&this.parent.set(e,this.find(this.parent.get(e))),this.parent.get(e)}union(e,n){let r=this.find(e),i=this.find(n);if(r===i)return;let o=this.rank.get(r),s=this.rank.get(i);o<s?this.parent.set(r,i):o>s?this.parent.set(i,r):(this.parent.set(i,r),this.rank.set(r,o+1))}};var ky=class t{static INDEX_FOLDER=CMt(OMt(),".wispbit","indexes");provider;initialized=!1;constructor(e){this.provider=e}async initializeProvider(){this.initialized||(await this.provider.initialize(),this.initialized=!0)}async initialize(e){await this.initializeProvider();let n=await this.provider.sendRequest({command:"initialize_workspaces",workspace_configs:e.workspaceConfigs.map(r=>({workspace_root:r.workspaceRoot,base_commit_sha:r.baseCommitSha})),index_folder:t.INDEX_FOLDER,ignores:e.ignores});if("error"in n&&n.error)throw new Error(`Failed to initialize workspaces: ${n.error}`);return{fullScan:n.full_scan||!1}}async getDuplicates(e,n){await this.initializeProvider();let r=await this.provider.sendRequest({command:"get_duplicates",workspace_root:e,file_path:n});if("error"in r&&r.error)throw new Error(`Failed to get duplicates: ${r.error}`);let i=r;return new Hg(i)}async getDuplicatesForFile(e,n){await this.initializeProvider();let r=await this.provider.sendRequest({command:"get_duplicates",workspace_root:e,file_path:n});if("error"in r&&r.error)throw new Error(`Failed to get duplicates for file: ${r.error}`);let i=r;return new Hg(i)}invalidationQueue=Promise.resolve();async invalidateFiles(e,n){let r=this.invalidationQueue.then(async()=>{await this.initializeProvider();let i=Date.now(),o=await this.provider.sendRequest({command:"invalidate_files",workspace_root:e,files:n.map(a=>({file_path:a.filePath,content_sha:a.contentSha}))}),s=Date.now()-i;if(Ae.log(`[RuntimeManager] Invalidated ${n.length} file(s) in ${s}ms for ${e}`),"error"in o&&o.error)throw new Error(`Failed to invalidate files: ${o.error}`)}).catch(i=>{throw Ae.log(`[RuntimeManager] Invalidation failed: ${i.message}`),i});this.invalidationQueue=r.catch(()=>{}),await r}isInitialized(){return this.initialized}async shutdown(){this.initialized&&(Ae.log("[RuntimeManager] Shutdown requested, waiting for in-flight operations..."),await this.invalidationQueue.catch(()=>{}),Ae.log("[RuntimeManager] All operations complete, shutting down runtime..."),await this.provider.shutdown(),this.initialized=!1)}};var Hy=class{contexts=new Map;workspacePath;apiKey;lspClient;sharedRuntimeManager=null;RULES_CACHE_TTL_MS=300*1e3;constructor(e){this.workspacePath=e.workspacePath,this.apiKey=e.apiKey,this.lspClient=e.lspClient}async discoverAndInitialize(e,n){let r=await iO(this.workspacePath),i=[];for(let s of r){let a=await this.initializeContext(s);if("error"in a){n?.(s,new Error(a.error));continue}let c=a,{baseCommitSha:u}=await ga(s);i.push({repoRoot:s,context:c,baseCommitSha:u}),this.contexts.set(s,c),e?.(s,c)}let o=[];for(let{repoRoot:s,context:a,baseCommitSha:c}of i)a.config.getEnableDeduplicator()&&o.push({workspaceRoot:s,baseCommitSha:c});if(o.length>0){let s=new By(o[0].workspaceRoot);this.sharedRuntimeManager=new ky(s);for(let{context:a}of i)a.config.getEnableDeduplicator()&&(a.runtimeManager=this.sharedRuntimeManager,a.duplicateManager=new Gy(this.sharedRuntimeManager,a.config,a.environment))}}async initializeContext(e){let n=Kr.initialize({workspaceRoot:e});if(!n)return{error:"Not in a git repository"};let r=await $o.initialize(n,{apiKey:this.apiKey,lspClient:this.lspClient});if("failed"in r)return{error:`Config initialization failed: ${r.error}`};let i=r,o=new jo(i,n),s=new zr,a=new La(i,n,s);return{repoRoot:e,environment:n,config:i,ruleProvider:o,eventEmitter:s,ruleExecutor:a,cachedRules:null,rulesById:new Map,rulesCacheTimestamp:0,rulesLoadingPromise:null,lastCommitSelector:null,currentExecutionRules:[],completedRulesCount:0,isExecuting:!1,currentExecutionPromise:null,runtimeManager:null,duplicateManager:null,executionContext:null}}findContextForFile(e){let n=e.toLowerCase();return Array.from(this.contexts.entries()).filter(([i])=>{let o=i.toLowerCase();return n.startsWith(o+IMt)||n===o}).sort((i,o)=>o[0].length-i[0].length)[0]?.[1]||null}getAllContexts(){return Array.from(this.contexts.values())}getRepoCount(){return this.contexts.size}hasRepositories(){return this.contexts.size>0}getContext(e){return this.contexts.get(e)}async initializeRuntimeManager(){if(!this.sharedRuntimeManager)return!1;let e=[],n=[];for(let r of this.contexts.values())if(r.config.getEnableDeduplicator()){let{baseCommitSha:i}=await ga(r.repoRoot);e.push({workspaceRoot:r.repoRoot,baseCommitSha:i}),n.length===0&&(n=r.config.getIgnoredGlobs())}return e.length===0?!1:(await this.sharedRuntimeManager.initialize({workspaceConfigs:e,ignores:n}),!0)}async shutdown(){for(let e of this.contexts.values())e.ruleExecutor.clearCache(),e.duplicateManager&&e.duplicateManager.clearCache();this.sharedRuntimeManager&&(await this.sharedRuntimeManager.shutdown(),this.sharedRuntimeManager=null),this.contexts.clear()}};function bWe(t,e,n){if(t.fingerprint)return`${e}:${t.fingerprint}`;let r=t.text?.slice(0,100)||"",i=`${t.range.start.line}:${t.range.start.column}-${t.range.end.line}:${t.range.end.column}`;return`${e}:${n}:${i}:${PMt(r)}`}function PMt(t){let e=0;for(let n=0;n<t.length;n++){let r=t.charCodeAt(n);e=(e<<5)-e+r,e=e&e}return e.toString(36)}function vWe(t){return t.end.line-t.start.line+1>20?{start:{line:t.start.line-1,character:t.start.column-1},end:{line:t.start.line-1,character:Number.MAX_SAFE_INTEGER}}:{start:{line:t.start.line-1,character:t.start.column-1},end:{line:t.end.line-1,character:t.end.column-1}}}var tK=class{connection;documentManager;repositoryContextManager;workspacePath;apiKey;lspClient;batchProgressReporter=null;batchProgressToken="wispbit-batch-lint";progressTokenCreated=!1;fixQueue=[];isProcessingFix=!1;branchCheckTimer=null;BRANCH_CHECK_DEBOUNCE_MS=1e3;branchCheckInterval=null;BRANCH_CHECK_INTERVAL_MS=3e4;executionDebounceTimer=null;EXECUTION_DEBOUNCE_MS=1e3;changedFiles=new Set;hasRunInitialCheck=!1;isExecutingInitial=!1;dismissalsLoadingPromises=new Map;fixesLoadingPromises=new Map;localDismissals=[];constructor(e){this.workspacePath=e.workspacePath,this.apiKey=e.apiKey,this.lspClient=e.lspClient,this.connection=(0,mr.createConnection)(mr.ProposedFeatures.all,process.stdin,process.stdout),this.documentManager=new Vy,this.repositoryContextManager=new Hy({workspacePath:this.workspacePath,apiKey:this.apiKey,lspClient:this.lspClient}),this.registerHandlers()}addLocalDismissal(e){this.localDismissals.push(e)}isLocallyDismissed(e,n,r,i,o){return this.localDismissals.some(s=>s.matchId===o&&s.uri===e?!0:s.uri===e&&s.ruleId===n?s.startLine<=i&&s.endLine>=r:!1)}clearLocalDismissalsForUri(e){this.localDismissals=this.localDismissals.filter(n=>n.uri!==e)}clearAllLocalDismissals(){this.localDismissals=[]}findContextForFile(e){let n=Uo(e);return this.repositoryContextManager.findContextForFile(n)}pathToNormalizedUri(e){let n=MMt(e).toString();return decodeURIComponent(n)}getDiagnosticsForUri(e){let n=this.documentManager.getDiagnostics(e);if(n.length===0){let r=oi(e),i=this.documentManager.getAllDiagnosticUris();for(let o of i)if(oi(o)===r){n=this.documentManager.getDiagnostics(o);break}}return n}handleRuleComplete(e,n,r){if(!e.isExecuting||e.currentExecutionRules.length===0)return;e.completedRulesCount++;let i=Math.round(e.completedRulesCount/e.currentExecutionRules.length*100);this.updateBatchProgress(i,n)}async handleRuleFileComplete(e,n,r,i){if(!e.isExecuting||e.currentExecutionRules.length===0)return;let o=e.currentExecutionRules.find(u=>u.id===n);if(!o){this.connection.console.log(`[${e.repoRoot}] Warning: Rule ${n} not found in current execution`);return}let s=IE(e.repoRoot,r),a=this.pathToNormalizedUri(s);if(i.length===0){this.updateDiagnosticsForRule(a,o.internalId,[]);return}let c=await this.createDiagnosticsForFile(e,r,o.internalId,i,e.currentExecutionRules);this.updateDiagnosticsForRule(a,o.internalId,c)}async handleRuleFilePartial(e,n,r,i,o){if(!e.isExecuting||e.currentExecutionRules.length===0)return;let s=e.currentExecutionRules.find(l=>l.internalId===n);if(!s){this.connection.console.log(`[${e.repoRoot}] Warning: Rule ${n} not found in current execution`);return}let a=IE(e.repoRoot,r),c=this.pathToNormalizedUri(a);if(i.length===0){this.updateDiagnosticsForRule(c,s.internalId,[]);return}let u=await this.createDiagnosticsForFile(e,r,s.internalId,i,e.currentExecutionRules);this.updateDiagnosticsForRule(c,s.internalId,u)}async convertDuplicateResultsToDiagnostics(e,n,r,i){let o=[];for(let s of n)for(let a of s.matches){let c=bWe(a,"DUPLICATE",i);if(this.isLocallyDismissed(i,"DUPLICATE",a.range.start.line,a.range.end.line,c))continue;let u=vWe(a.range),l=a.evidence?.map(f=>{let T=IE(e.repoRoot,f.file.path);return{location:{uri:this.pathToNormalizedUri(T),range:{start:{line:f.range.start.line-1,character:f.range.start.column-1},end:{line:f.range.end.line-1,character:f.range.end.column-1}}},message:"Duplicate location"}}),E=null;a.edits&&a.edits.length>0&&(E=await this.computeFixForMatch(a,e).catch(f=>(this.connection.console.log(`Warning: Failed to compute fix for duplicate: ${f}`),null)));let d={range:u,severity:mr.DiagnosticSeverity.Warning,message:a.description||"Duplicate code detected",code:"DUPLICATE",source:"wispbit",relatedInformation:l,data:{uri:i,match:a,matchId:c,fix:E?{diff:E.diff,diffs:E.diffs,autofix:!1}:null,ruleId:"DUPLICATE",filePath:a.file.path,rule:{id:"DUPLICATE",displayId:"DUPLICATE",summary:null}}};o.push(d)}return o}async handleDuplicateFileComplete(e,n,r,i,o){let s=IE(e.repoRoot,n),a=this.pathToNormalizedUri(s),c=await this.createDiagnosticsForFile(e,n,"DUPLICATE",r,[],this.convertDuplicateResultsToDiagnostics.bind(this));this.updateDiagnosticsForRule(a,"DUPLICATE",c)}setupProgressListenersForContext(e){e.eventEmitter.on("rules:progress",n=>{this.updateBatchProgress(n.percentage,n.ruleId)}),e.eventEmitter.on("rules:rule-complete",n=>{this.handleRuleComplete(e,n.ruleId,n.matches)}),e.eventEmitter.on("rules:rule-file-complete",async n=>{await this.handleRuleFileComplete(e,n.ruleId,n.filePath,n.matches)}),e.eventEmitter.on("rules:rule-file-partial",async n=>{await this.handleRuleFilePartial(e,n.ruleId,n.filePath,n.matches,n.totalMatches)})}normalizePathSeparators(e){return e.replace(/\\/g,"/")}toRelativePath(e,n){if(!n){let r=this.pathToNormalizedUri(e);n=this.findContextForFile(r)||void 0}return n?this.normalizePathSeparators(yWe(n.repoRoot,e)):this.normalizePathSeparators(yWe(this.workspacePath,e))}updateDiagnosticsForRule(e,n,r){this.documentManager.setDiagnosticsForRule(e,n,r);let i=this.documentManager.getDiagnostics(e);this.connection.sendDiagnostics({uri:e,diagnostics:i})}removeDiagnosticByMatchId(e,n){let r=this.documentManager.getDiagnostics(e),i=r.find(a=>a.data?.matchId===n);if(!i)return;let o=i.data?.rule?.id;if(!o)return;let s=r.filter(a=>a.data?.rule?.id===o&&a.data?.matchId!==n);this.updateDiagnosticsForRule(e,o,s)}clearAllDiagnostics(){let e=this.documentManager.getAllDiagnosticUris();for(let n of e)this.clearDiagnosticsForFile(n);this.clearAllLocalDismissals()}clearDiagnosticsForFile(e){this.documentManager.clearDiagnostics(e),this.clearLocalDismissalsForUri(e),this.connection.sendDiagnostics({uri:e,diagnostics:[]})}handleDocumentChangesWithRanges(e,n){let r=this.documentManager.getDiagnostics(e);if(r.length===0)return;this.connection.console.log(`Document changed: ${e}, ${n.length} change(s), ${r.length} diagnostic(s)`);let i=new Set;for(let o of n){if(!o.range){this.connection.console.log("Full document change detected - removing all diagnostics");for(let s of r)s.data?.matchId&&i.add(s.data.matchId);continue}for(let s of r)this.rangesOverlap(o.range,s.range)&&s.data?.matchId&&i.add(s.data.matchId)}for(let o of i)this.removeDiagnosticByMatchId(e,o);i.size>0&&this.connection.console.log(`Removed ${i.size} diagnostic(s) due to document edits`)}rangesOverlap(e,n){return e.end.line<n.start.line||e.start.line>n.end.line?!1:e.start.line<=n.end.line&&e.end.line>=n.start.line}async createDiagnosticsForFile(e,n,r,i,o,s){let a=i.length;this.documentManager.hasDismissals(n)||await this.loadDismissalsForFile(e,n),this.documentManager.hasFixes(n)||await this.loadFixesForFile(e,n);let c={ruleId:r,matches:i},u=this.filterDismissedResults([c],n),l=u[0]?.matches.length||0,E=a-l,d=await this.filterFixedResults(e,u,n),f=d[0]?.matches.length||0,T=l-f,p=IE(e.repoRoot,n),S=this.pathToNormalizedUri(p),m=await(s||this.convertResultsToDiagnostics.bind(this))(e,d,o,S);if(a>0){let h=o.find(P=>P.internalId===r)?.id||r,C=[];E>0&&C.push(`${E} dismissed`),T>0&&C.push(`${T} fixed`),C.length>0?this.connection.console.log(`[${e.repoRoot}] ${n}: ${m.length} diagnostic(s) created, ${C.join(", ")} (rule: ${h})`):this.connection.console.log(`[${e.repoRoot}] ${n}: ${m.length} diagnostic(s) created (rule: ${h})`)}return m}async getFileContent(e){let n=this.pathToNormalizedUri(e),r=this.documentManager.getDocument(n);return r?r.getText():await Yy.access(e).then(()=>!0).catch(()=>!1)?await Yy.readFile(e,"utf-8").catch(()=>null):null}async computeFixForMatch(e,n){if(!e.edits||e.edits.length===0)return null;let r=await jc(e.edits,e.file.path,n.repoRoot,o=>this.getFileContent(o));return r?{fileChanges:r.fileChanges.map(o=>({...o,fileUri:this.pathToNormalizedUri(o.filePath)})),diff:r.diff,diffs:r.diffs}:null}async loadRulesWithCache(e){let r=Date.now()-e.rulesCacheTimestamp;return e.cachedRules&&r<this.repositoryContextManager.RULES_CACHE_TTL_MS?(this.connection.console.log(`[${e.repoRoot}] Using cached rules (age: ${Math.round(r/1e3)}s / ${this.repositoryContextManager.RULES_CACHE_TTL_MS/1e3}s)`),e.cachedRules):e.rulesLoadingPromise?(this.connection.console.log(`[${e.repoRoot}] Rules are already being loaded, waiting for existing request...`),e.rulesLoadingPromise):(this.connection.console.log(`[${e.repoRoot}] Loading fresh rules from API...`),e.rulesLoadingPromise=e.ruleProvider.loadAllRules().then(i=>{let o=i.filter(s=>s.execution==="llm");e.cachedRules=o,e.rulesCacheTimestamp=Date.now(),e.rulesById.clear();for(let s of o)e.rulesById.set(s.id,s);if(this.connection.console.log(`[${e.repoRoot}] Loaded ${o.length} rules (cache valid for ${this.repositoryContextManager.RULES_CACHE_TTL_MS/1e3}s)`),o.length>0){this.connection.console.log(`[${e.repoRoot}] Fetched rules:`);for(let s of o){let a=s.autofix||!1,c="";a&&(c=" (autofix)"),this.connection.console.log(`[${e.repoRoot}] - ${s.id}: ${s.message}${c}`)}}return o}).finally(()=>{e.rulesLoadingPromise=null}),await e.rulesLoadingPromise)}async loadDismissalsForFile(e,n){if(this.documentManager.hasDismissals(n))return;let r=this.dismissalsLoadingPromises.get(n);if(r)return await r;let i=(async()=>{let s=(await e.ruleProvider.getDismissals([n])).map(a=>({ruleId:a.ruleId,file:a.match.file.path,startLine:a.match.range.start.line,endLine:a.match.range.end.line,fingerprint:a.match.fingerprint,dismissedAt:a.createdAt,dismissalId:a.dismissalId}));this.documentManager.setDismissals(n,s)})().finally(()=>{this.dismissalsLoadingPromises.delete(n)});return this.dismissalsLoadingPromises.set(n,i),await i}async loadFixesForFile(e,n){if(this.documentManager.hasFixes(n))return;let r=this.fixesLoadingPromises.get(n);if(r)return await r;let i=(async()=>{let o=await e.ruleProvider.getFixes([n]);this.documentManager.setFixes(n,o)})().finally(()=>{this.fixesLoadingPromises.delete(n)});return this.fixesLoadingPromises.set(n,i),await i}filterDismissedResults(e,n){let r=this.documentManager.getDismissals(n);return r.length===0?e:e.map(i=>{let o=r.filter(u=>u.ruleId===i.ruleId);if(o.length===0)return i;let s=i.matches.map(u=>({file:n,startLine:u.range.start.line,endLine:u.range.end.line,fingerprint:u.fingerprint})),c=Nh(s,o).map(u=>i.matches.find(l=>l.range.start.line===u.startLine&&l.range.end.line===u.endLine&&l.fingerprint===u.fingerprint));return{...i,matches:c}})}async filterFixedResults(e,n,r){let i=this.documentManager.getFixes(r);if(i.length===0)return n;this.connection.console.log(`[${e.repoRoot}] Filtering fixes for ${r}: ${i.length} fix(es) loaded`);let o=IE(e.repoRoot,r),s=await this.getFileContent(o);return s===null?n:n.map(a=>{let c=i.filter(S=>S.ruleId===a.ruleId);if(c.length===0)return a;let u=new Set;for(let S of c)S.match?.edits?.some(O=>O.oldString&&C1(s,O.oldString))&&S.match.fingerprint&&u.add(S.match.fingerprint);let l=c.length-u.size;u.size>0&&this.connection.console.log(`[${e.repoRoot}] ${r}: ${u.size} fix(es) reverted, ${l} still active`);let E=a.matches.map(S=>({file:r,startLine:S.range.start.line,endLine:S.range.end.line,fingerprint:S.fingerprint})),d=c.filter(S=>!S.match.fingerprint||!u.has(S.match.fingerprint)).map(S=>({file:r,startLine:S.match.range.start.line,endLine:S.match.range.end.line,fingerprint:S.match.fingerprint})),T=Nh(E,d).map(S=>a.matches.find(m=>m.range.start.line===S.startLine&&m.range.end.line===S.endLine&&m.fingerprint===S.fingerprint)),p=a.matches.length-T.length;return p>0&&this.connection.console.log(`[${e.repoRoot}] ${r}: Filtered out ${p} match(es) with active fixes`),{...a,matches:T}})}async convertResultsToDiagnostics(e,n,r,i){let o=[],s=new Set;for(let a of n){let c=r.find(u=>u.internalId===a.ruleId);if(!c){this.connection.console.log(`Warning: Could not find rule with internal ID ${a.ruleId}`);continue}for(let u of a.matches){let l=`${u.range.start.line}-${u.range.end.line}`;if(s.has(l))continue;s.add(l);let E=bWe(u,c.internalId,i);if(this.isLocallyDismissed(i,c.internalId,u.range.start.line,u.range.end.line,E))continue;let d=null;u.edits&&u.edits.length>0&&(d=await this.computeFixForMatch(u,e).catch(p=>(this.connection.console.log(`Warning: Failed to compute fix for match: ${p}`),null)));let T={range:vWe(u.range),severity:mr.DiagnosticSeverity.Warning,message:u.description||c.message,code:c.id,codeDescription:{href:`https://app.wispbit.com/rules/${c.internalId}`},source:"wispbit",data:{uri:i,match:u,matchId:E,fix:d?{diff:d.diff,diffs:d.diffs,autofix:c.autofix||!1}:null,rule:{id:c.internalId,displayId:c.id,summary:c.summary||null}}};o.push(T)}}return o}triggerExecution(){this.executionDebounceTimer&&(clearTimeout(this.executionDebounceTimer),this.executionDebounceTimer=null),this.executionDebounceTimer=setTimeout(()=>{this.executionDebounceTimer=null,this.executeQueuedFiles()},this.EXECUTION_DEBOUNCE_MS)}lintDocument(e){if(!this.documentManager.getDocument(e)){this.connection.console.log(`Document not found: ${e}`);return}let r=Uo(e),i=this.toRelativePath(r);this.connection.console.log(`File changed: ${i}`),this.changedFiles.add(e),this.triggerExecution()}async executeQueuedFiles(){let e=this.repositoryContextManager.getAllContexts();if(e.length===0){this.connection.console.log("No repositories found, skipping execution");return}if(!this.hasRunInitialCheck){if(this.isExecutingInitial){this.connection.console.log("Initial check already in progress, files will be queued for next run");return}this.changedFiles.clear(),this.isExecutingInitial=!0;try{await this.repositoryContextManager.initializeRuntimeManager()&&this.connection.console.log("RuntimeManager initialized successfully"),this.hasRunInitialCheck=!0,this.cleanupProgress(),await this.startBatchProgress(0);try{for(let i of e)await this.executeForContext(i,null);this.cleanupProgress()}catch(i){this.connection.console.error(`Error executing rules: ${i.message} ${i.stack}`),await CE(i),this.cleanupProgress()}}finally{this.isExecutingInitial=!1}}else{let r=Array.from(this.changedFiles);if(this.changedFiles.clear(),r.length===0){this.connection.console.log("No files to check, skipping incremental execution");return}this.connection.console.log(`Incremental check for ${r.length} file(s)`),await this.startBatchProgress(0);try{for(let i of e)await this.executeForContext(i,r);this.cleanupProgress()}catch(i){this.connection.console.error(`Error executing rules: ${i.message} ${i.stack}`),await CE(i),this.cleanupProgress()}}}async executeForContext(e,n){e.isExecuting=!0;try{let r=await this.loadRulesWithCache(e);e.completedRulesCount=0,e.currentExecutionRules=r;let{commitSelector:i,include:o}=await ga(e.repoRoot);e.lastCommitSelector=i;let s=await Pa.initialize(e.config,e.environment,"diff",e.eventEmitter,void 0,{include:o,commitSelector:i,skipPreExistingViolations:e.config.getSkipPreExistingViolationsEnabled()});if(e.executionContext=s,e.runtimeManager){let a=[];if(n!==null&&n.length>0?a=n.filter(c=>this.findContextForFile(c)?.repoRoot===e.repoRoot).map(c=>({filePath:this.toRelativePath(Uo(c),e)})):a=s.filePaths.map(c=>({filePath:c})),a.length>0){this.connection.console.log(`[${e.repoRoot}] Starting invalidation of ${a.length} file(s) in RuntimeManager...`);let c=Date.now();await e.runtimeManager.invalidateFiles(e.repoRoot,a);let u=Date.now()-c;this.connection.console.log(`[${e.repoRoot}] Completed invalidation in ${u}ms`)}}if(n!==null&&n.length>0){let a=n.filter(c=>this.findContextForFile(c)?.repoRoot===e.repoRoot);if(a.length===0){this.connection.console.log(`[${e.repoRoot}] No changed files in this repository, skipping`);return}for(let c of a){let u=this.toRelativePath(Uo(c),e);this.connection.console.log(`[${e.repoRoot}] Executing rules for ${u}`),e.completedRulesCount=0;let l=e.ruleExecutor.execute(r,s,{relativePath:u,emitErrors:!0}),E=e.duplicateManager?e.duplicateManager.execute(s,u,(d,f,T,p)=>{this.handleDuplicateFileComplete(e,d,f,T,p)}):Promise.resolve();await Promise.all([l,E])}}else{let a=e.ruleExecutor.execute(r,s,{emitErrors:!0}),c=e.duplicateManager?(async()=>{let u=e.duplicateManager;this.connection.console.log(`[${e.repoRoot}] Starting duplicate detection...`);let l=Date.now();await u.execute(s,void 0,(d,f,T,p)=>{this.handleDuplicateFileComplete(e,d,f,T,p)});let E=Date.now()-l;this.connection.console.log(`[${e.repoRoot}] Completed duplicate detection in ${E}ms`)})():Promise.resolve();await Promise.all([a,c])}}catch(r){this.connection.console.error(`[${e.repoRoot}] Error executing rules: ${r.message} ${r.stack}`),await CE(r)}finally{e.isExecuting=!1}}async startBatchProgress(e){if(this.batchProgressReporter)this.batchProgressReporter.report(e,"Checking workspace");else try{this.progressTokenCreated||(await this.connection.sendRequest("window/workDoneProgress/create",{token:this.batchProgressToken}),this.progressTokenCreated=!0),this.batchProgressReporter=await this.connection.window.createWorkDoneProgress(),this.batchProgressReporter.begin("wispbit",e,"Checking workspace",!1)}catch(n){this.connection.console.log(`Failed to create batch progress: ${n}`)}}cleanupProgress(){this.batchProgressReporter&&(this.batchProgressReporter.done(),this.batchProgressReporter=null)}updateBatchProgress(e,n){if(!this.batchProgressReporter)return;let r=`Checking workspace (${n})`;this.batchProgressReporter.report(e,r)}async processFixQueue(){if(!this.isProcessingFix){for(this.isProcessingFix=!0;this.fixQueue.length>0;){let e=this.fixQueue.shift();e&&await e()}this.isProcessingFix=!1}}handleQuickfix(e){let{uri:n,matchId:r}=e[0];this.fixQueue.push(async()=>{await this.applyQuickfix(n,r)}),this.processFixQueue()}async applyQuickfix(e,n){let i=this.getDiagnosticsForUri(e).find(T=>T.data?.matchId===n);if(!i){this.connection.window.showErrorMessage("Could not apply fix"),this.connection.console.error(`Diagnostic not found for matchId: ${n}`);return}let o=i.data?.match,s=i.data?.rule;if(!o?.edits||o.edits.length===0){this.connection.window.showErrorMessage("No fix available"),this.connection.console.error(`No fix available for matchId ${n}, rule ${s?.id}`);return}let a=this.findContextForFile(e);if(!a){this.connection.window.showErrorMessage("File is not in any repository"),this.connection.console.error(`No repository context found for ${e}`);return}let c=Uo(e),u=this.toRelativePath(c,a);this.connection.console.log(`[${a.repoRoot}] Applying fix for matchId ${n}, rule ${s?.id}`);let l=await this.computeFixForMatch(o,a);if(!l){this.connection.window.showErrorMessage("Failed to compute fix"),this.connection.console.error(`[${a.repoRoot}] Failed to compute fix for matchId ${n}, rule ${s?.id}`);return}let E=Uo(e),d=[];for(let T of l.fileChanges){let S=T.filePath===E?e:T.fileUri,m=this.documentManager.getDocument(S),O=m?m.lineCount:T.oldContent.split(`
297
297
  `).length,h=Uo(S),C=!!m;C||(C=await Yy.access(h).then(()=>!0).catch(()=>!1)),C||d.push(mr.CreateFile.create(S,{overwrite:!1,ignoreIfExists:!0}));let P={textDocument:{uri:S,version:m?.version??null},edits:[mr.TextEdit.replace({start:{line:0,character:0},end:{line:O,character:0}},T.newContent)]};d.push(P)}let f=await this.connection.workspace.applyEdit({documentChanges:d});f.applied?this.connection.console.log(`[${a.repoRoot}] Applied fix successfully`):this.connection.console.log(`[${a.repoRoot}] Could not apply fix. Reason: ${f.failureReason}, Change: ${f.failedChange}`),await a.ruleProvider.createFix(s?.id,o).catch(T=>{this.connection.console.log(`[${a.repoRoot}] Failed to track fix: ${T.message}`)}),this.removeDiagnosticByMatchId(e,n),this.documentManager.clearFixes(u)}async handleDismiss(e){let{uri:n,matchId:r,ruleId:i,startLine:o,endLine:s}=e[0],a=this.findContextForFile(n);if(!a){this.connection.window.showErrorMessage("File is not in any repository"),this.connection.console.error(`No repository context found for ${n}`);return}let c=Uo(n),u=this.toRelativePath(c,a),l=this.getDiagnosticsForUri(n),E=l.find(S=>S.data?.matchId===r);if(!E&&i&&o!==void 0&&s!==void 0&&(E=l.find(S=>{let m=S.data?.rule?.id,O=S.range.start.line+1,h=S.range.end.line+1;return m===i&&O<=s&&h>=o})),!E){this.connection.window.showErrorMessage("Could not dismiss violation"),this.connection.console.error(`[${a.repoRoot}] Diagnostic not found for matchId: ${r}`);return}let d=E.data?.match,f=E.data?.rule?.id,T=E.data?.matchId;if(!d||!f||!T){this.connection.window.showErrorMessage("Could not dismiss violation"),this.connection.console.error(`[${a.repoRoot}] Match not found for matchId: ${r}`);return}this.addLocalDismissal({uri:n,ruleId:f,startLine:E.range.start.line+1,endLine:E.range.end.line+1,matchId:T,timestamp:Date.now()}),this.removeDiagnosticByMatchId(n,T),await a.ruleProvider.createDismissal(f,d).catch(S=>{this.connection.console.log(`[${a.repoRoot}] Failed to create dismissal: ${S.message}`)});let p=E.data?.rule?.displayId||f;this.connection.console.log(`[${a.repoRoot}] Dismissed violation: ${p} with matchId ${T}`),this.documentManager.clearDismissals(u)}async handleGetDismissals(e){let{uri:n}=e[0];if(!n||typeof n!="string")return this.connection.console.log(`Invalid URI provided to getDismissals: ${n}`),[];if(!n.startsWith("file://"))return this.connection.console.log(`URI must be a file:// URL, got: ${n}`),[];let r=this.findContextForFile(n);if(!r)return this.connection.console.log(`No repository context found for ${n}`),[];let i=Uo(n),o=this.toRelativePath(i,r);await this.loadDismissalsForFile(r,o);let s=this.documentManager.getDismissals(o),a=await this.loadRulesWithCache(r),c=this.documentManager.getDocument(n);if(!c){let u=oi(n),l=this.documentManager.getAllDocumentUris();for(let E of l)if(oi(E)===u){c=this.documentManager.getDocument(E);break}}return s.map(u=>{let l=a.find(f=>f.internalId===u.ruleId),E="";if(c){let f=c.getText({start:{line:u.startLine-1,character:0},end:{line:u.startLine-1,character:100}});E=f.trim().substring(0,60),f.trim().length>60&&(E+="...")}let d="";if(u.dismissedAt){let f=new Date,T=new Date(u.dismissedAt),p=f.getTime()-T.getTime(),S=Math.floor(p/6e4),m=Math.floor(S/60),O=Math.floor(m/24);S<1?d="just now":S<60?d=`${S} minute${S===1?"":"s"} ago`:m<24?d=`${m} hour${m===1?"":"s"} ago`:d=`${O} day${O===1?"":"s"} ago`}return{dismissalId:u.dismissalId,ruleId:u.ruleId,displayId:l?.id||u.ruleId,ruleName:l?.message||"Unknown rule",line:u.startLine,fingerprint:u.fingerprint,fileName:o,codeSnippet:E,timeAgo:d}})}async handleUndismiss(e){let{uri:n,dismissalId:r}=e[0],i=this.findContextForFile(n);if(!i){this.connection.window.showErrorMessage("File is not in any repository"),this.connection.console.error(`No repository context found for ${n}`);return}let o=Uo(n),s=this.toRelativePath(o,i),c=this.documentManager.getDismissals(s).find(f=>f.dismissalId===r);if(!c){this.connection.window.showErrorMessage("Dismissal not found"),this.connection.console.error(`[${i.repoRoot}] Dismissal not found with ID ${r}`);return}await i.ruleProvider.deleteDismissal(c.ruleId,c.file,c.fingerprint);let l=(await this.loadRulesWithCache(i)).find(f=>f.internalId===c.ruleId),E=l?.id||c.ruleId,d=l?.message||"Unknown rule";this.connection.console.log(`Undismissed violation: ${E} at line ${c.startLine}`),this.connection.window.showInformationMessage(`Undismissed violation: ${E} at line ${c.startLine} - ${d}`),this.documentManager.clearDismissals(s),this.triggerExecution()}async handleRemember(e){let{uri:n,range:r,selectedText:i,note:o}=e[0],s=this.findContextForFile(n);if(!s){this.connection.window.showErrorMessage("File is not in any repository"),this.connection.console.error(`No repository context found for ${n}`);return}let a=Uo(n),c=this.toRelativePath(a,s);if(!o||o.trim().length===0){this.connection.window.showErrorMessage("Note is required to remember a pattern");return}let l=this.getDiagnosticsForUri(n).filter(E=>E.source==="wispbit"&&E.data?.match).map(E=>({...E.data.match,ruleId:E.data.rule?.id}));this.connection.console.log(`[${s.repoRoot}] Remembering pattern with ${l.length} matches: ${i.substring(0,100)}...`),this.connection.console.log(`[${s.repoRoot}] Note: ${o}`);try{await s.ruleProvider.rememberPattern(c,i,{start:{line:r.start.line+1,column:r.start.character+1},end:{line:r.end.line+1,column:r.end.character+1}},o.trim(),l),this.connection.window.showInformationMessage(`Pattern remembered: ${o.trim()}`)}catch(E){this.connection.console.log(`Failed to remember: ${E.message}`),this.connection.window.showErrorMessage(`Failed to remember: ${E.message}`)}}truncateMessage(e,n=60){return e.length<=n?e:e.substring(0,n)+"..."}generateCodeActions(e,n){let r=[],i=n.filter(c=>c.source==="wispbit"),o=i.filter(c=>c.data?.fix),s=o.length>1&&o.some((c,u)=>o.slice(u+1).some(l=>c.range.start.line<=l.range.end.line&&c.range.end.line>=l.range.start.line)),a=!1;for(let c of i){let u=c.data?.fix,l=u?.autofix||!1,E=u&&(!s||!a);if(u){let f=this.truncateMessage(c.message);r.push({title:`Apply fix: ${f}`,kind:"quickfix",command:{title:"Apply Fix",command:"wispbit.quickfix",arguments:[{uri:e,matchId:c.data?.matchId}]},diagnostics:[c],isPreferred:E}),E&&(a=!0),l&&r.push({title:`Fix: ${f}`,kind:"source.fixAll",command:{title:"Apply Fix",command:"wispbit.quickfix",arguments:[{uri:e,matchId:c.data?.matchId}]},diagnostics:[c],isPreferred:!1})}let d=this.truncateMessage(c.message);r.push({title:`Dismiss: ${d}`,kind:"quickfix",command:{title:"Dismiss",command:"wispbit.dismiss",arguments:[{uri:e,matchId:c.data?.matchId}]},diagnostics:[c]})}return r}generateHover(e,n){let r=e.find(d=>n.line<d.range.start.line||n.line>d.range.end.line?!1:d.range.start.line===d.range.end.line?n.character>=d.range.start.character&&n.character<=d.range.end.character:n.line===d.range.start.line?n.character>=d.range.start.character:n.line===d.range.end.line?n.character<=d.range.end.character:!0);if(!r)return null;let i=String(r.code||""),o;for(let d of this.repositoryContextManager.getAllContexts())if(o=d.rulesById.get(i),o)break;let s=r.data?.fix,a=r.data?.match?.file?.path,c=r.data?.uri,l=(c?this.findContextForFile(c):null)?.repoRoot||this.workspacePath,E="";if(s?.diffs&&s.diffs.length>0)for(let{file:d,diff:f}of s.diffs){if(!(d.path===a)){let p=IE(l,d.path),S=this.pathToNormalizedUri(p);E+=`*[${d.path}](${S})*
298
298
  `}E+="```diff\n",E+=f,E+="\n```\n\n"}return o?.summary&&(o.summary.content&&(E+=`**Summary:** ${o.summary.content}
299
299
 
@@ -399,7 +399,7 @@ Global options:
399
399
  --repo-url <url> Override repository URL (default: from git remote)
400
400
  -v, --version Show version number
401
401
  -h, --help Show help
402
- `,{importMeta:import.meta,flags:{rule:{type:"string"},file:{type:"string"},json:{type:"string"},include:{type:"string"},repoUrl:{type:"string"},workspace:{type:"string"},lspClientVersion:{type:"string"},lspClientPackage:{type:"string"},validate:{type:"boolean",default:!1},apiKey:{type:"string"},line:{type:"string"},fix:{type:"string"},dismiss:{type:"string"},version:{type:"boolean",shortFlag:"v"},help:{type:"boolean",shortFlag:"h"}},version:Yo()});async function rK(t){let e=new Kr({repositoryUrl:t.repoUrl}),n=await Yg(e),r=e.getWorkspaceRoot(),{ruleId:i,json:o,mode:s,filePath:a}=t,{commitSelector:c,diffInclude:u}=t;if(s==="diff"){let H=e.getWorkspaceRoot();if(c)u||(u=(await ga(H)).include);else{let oe=await ga(H);c=oe.commitSelector,u||(u=oe.include)}}if(s==="diff"&&c&&u){let H=e.getWorkspaceRoot(),oe=await aV(H),te=cV(c,u,oe);te&&(console.error(j.red(te)),process.exit(1))}let l=!1,E="pretty";o!==void 0?(l=!0,typeof o=="string"?o==="stream"?E="stream":o==="compact"?E="compact":E="pretty":E="pretty"):await FWe();let d,f=new jo(n,e);if(i?d=[await f.loadRuleById(i)]:d=await f.loadAllRules(),!l){let H=n.getContext(),oe=H?.organization_name||"",te=H?.repository_owner||"",Ee=H?.repository_name||"",Re=oe&&te&&Ee?j.dim(` {${oe}:${te}/${Ee}}`):"",Ce=j.bgHex("#4a90e2").black(" DIFF "),Be=(c||"").replace(/\b[0-9a-f]{30,}\b/gi,rt=>rt.substring(0,7)),Ze=a?j.dim(` (${a})`):"",xt=u?` ${Be} ${j.dim(`[${u.join("/")}]`)}`:` ${Be}`;console.log(`${Ce}${xt}${Ze}${Re}`)}let T=new zr,p=u?u.join(", "):"all";T.setExecutionMode("diff",{baseCommit:c||"",headCommit:p});let S=new Map(d.map(H=>[H.id,{message:H.message,severity:H.severity,internalId:H.internalId,execution:H.execution}])),m=process.env.CLAUDECODE==="1",O=s==="diff"&&!l&&!m,h=!t.json&&!l&&!m?L1(T,O,S,r):void 0,C=Date.now(),P=new La(n,e,T),G=0,Y=[];T.on("files:discovery:complete",H=>{G=H.totalFiles}),T.on("rules:rule-error",H=>{let oe=d.find(te=>te.id===H.ruleId);oe&&(Y.push({ruleId:H.ruleId,internalId:oe.internalId,message:H.message,severity:H.severity,error:H.error}),CE(H.error,{tags:{source:"rule-execution",ruleId:H.ruleId,severity:H.severity},extra:{message:H.message,internalId:oe.internalId}}))});let re;l||(re=(await kWe(f)).dismissedMatchesByRule);let W=await Pa.initialize(n,e,s,T,a,s==="diff"?{include:u,commitSelector:c,skipPreExistingViolations:!0}:void 0),q=await P.execute(d,W,{dismissedMatchesByRule:re,emitErrors:!0}),Z=[];for(let H of q){let oe=d.find(te=>te.id===H.ruleId);if(oe){let Re={ruleId:H.ruleId,internalId:oe.internalId,message:oe.message,severity:oe.severity,execution:oe.execution,matches:H.matches,llmCost:void 0,llmTokens:void 0};Z.push(Re)}}if(t.fix!==void 0&&!l){let H=t.fix?t.fix.split(",").map(oe=>oe.trim()):void 0;await HWe(Z,d,f,r,H,j)}if(t.dismiss!==void 0&&!l){let H=t.dismiss?t.dismiss.split(",").map(oe=>oe.trim()):void 0;await YWe(Z,d,f,H,j)}if(h?.(),l)D1(Z,E,Y);else{let H=Z.filter(ft=>ft.severity==="violation"),oe=Z.filter(ft=>ft.severity==="suggestion"),te=H.reduce((ft,Ve)=>ft+Ve.matches.length,0),Ee=oe.reduce((ft,Ve)=>ft+Ve.matches.length,0),Re=te+Ee,Ce=Z.filter(ft=>ft.llmCost).reduce((ft,Ve)=>ft.plus(new sr(Ve.llmCost||0)),new sr(0)),Be=Z.filter(ft=>ft.llmTokens).reduce((ft,Ve)=>ft+(Ve.llmTokens||0),0),Ze=(c||"").replace(/\b[0-9a-f]{30,}\b/gi,ft=>ft.substring(0,7)),xt=u?u.join(", "):"all",rt={mode:"diff",baseCommit:Ze,headCommit:xt,filePath:a},At=Date.now()-C;P1(Z,{totalRules:d.length,violationCount:te,suggestionCount:Ee,totalMatches:Re,totalLLMCost:Ce.toString(),totalLLMTokens:Be,executionMode:rt,executionTime:At,totalFiles:G,ruleErrors:Y,debugMode:$y,showCommandHints:!0})}return Z}async function xWe(t){let e=Date.now(),n=new Na;await n.loadSession(t.sessionId);let i=n.getSessionData().workspaceRoot,o=new Kr({repositoryUrl:t.repoUrl,workspaceRoot:i}),s=await Yg(o),{ruleId:a,json:c}=t,u=!1,l="pretty";c!==void 0?(u=!0,typeof c=="string"?c==="stream"?l="stream":c==="compact"?l="compact":l="pretty":l="pretty"):await FWe();let E,d=new jo(s,o);a?E=[await d.loadRuleById(a)]:E=await d.loadAllRules();let f=new zr;f.setExecutionMode("session",{});let T=new Map(E.map(W=>[W.id,{message:W.message,severity:W.severity,internalId:W.internalId,execution:W.execution}])),p=process.env.CLAUDECODE==="1",S=!t.json&&!u&&!p?L1(f,!0,T,i):void 0,m=n.getFileChanges(),O=m.length,h;u||(h=(await kWe(d)).dismissedMatchesByRule);let C=new La(s,o,f),P=[],G=await Pa.initialize(s,o,"session",f,void 0,void 0,{fileChanges:m}),Y=await C.execute(E,G,{dismissedMatchesByRule:h,emitErrors:!0});f.on("rules:rule-error",W=>{P.push({ruleId:W.ruleId,message:W.message,severity:W.severity,error:W.error})});let re=[];for(let W of Y){let q=E.find(H=>H.id===W.ruleId);if(!q)continue;let Z={ruleId:W.ruleId,message:q.message,severity:q.severity,execution:q.execution,matches:W.matches.map(H=>({file:H.file,range:H.range,language:H.language||"Unknown",text:H.text,fingerprint:H.fingerprint,description:H.description,evidence:H.evidence,edits:H.edits})),llmCost:W.cost,llmTokens:void 0};re.push(Z)}if(S?.(),u)D1(re,l,P);else{let q=process.env.CLAUDECODE==="1"?new Cl({level:3}):j,Z=re.reduce((rt,At)=>rt+At.matches.length,0);if(t.fix===void 0&&t.dismiss===void 0)if(Z>0){let rt=q.red("wispbit found ")+q.red.bold(`${Z}`)+q.red(` ${Z===1?"issue":"issues"}`);console.log(rt)}else console.log(q.hex("#ff69b4")("wispbit found no issues"));if(console.log(q.dim.italic("reviewing changes from current Claude Code session only, run `wispbit diff` to view changes for all sessions")),console.log(),t.fix!==void 0){let rt=t.fix?t.fix.split(",").map(At=>At.trim()):void 0;await HWe(re,E,d,i,rt,q)}if(t.dismiss!==void 0){let rt=t.dismiss?t.dismiss.split(",").map(At=>At.trim()):void 0;await YWe(re,E,d,rt,q)}if(re.length>0&&t.fix===void 0&&t.dismiss===void 0){let rt=await xh(re,E,i,q);console.log(rt)}let H=re.filter(rt=>rt.severity==="violation"),oe=re.filter(rt=>rt.severity==="suggestion"),te=H.reduce((rt,At)=>rt+At.matches.length,0),Ee=oe.reduce((rt,At)=>rt+At.matches.length,0),Re=te+Ee,Ce=re.filter(rt=>rt.llmCost).reduce((rt,At)=>rt.plus(new sr(At.llmCost||0)),new sr(0)),Be=re.filter(rt=>rt.llmTokens).reduce((rt,At)=>rt+(At.llmTokens||0),0),Ze={mode:"session"},xt=Date.now()-e;t.fix===void 0&&t.dismiss===void 0&&P1(re,{totalRules:E.length,violationCount:te,suggestionCount:Ee,totalMatches:Re,totalLLMCost:Ce.toString(),totalLLMTokens:Be,executionMode:Ze,executionTime:xt,totalFiles:O,ruleErrors:P,debugMode:$y,showCommandHints:!0},q)}return re}async function wMt(t){let e=new Kr({repositoryUrl:t}),n=await Yg(e),i=await new jo(n,e).loadAllRules();FQ(i)}async function xMt(){let t=ot.flags.apiKey||process.env.WISPBIT_API_KEY;t||(console.error("WISPBIT_API_KEY environment variable or --api-key flag required"),process.exit(1));let e=ot.flags.workspace||process.cwd(),n=ot.flags.lspClientVersion,r=ot.flags.lspClientPackage,i=ot.flags.validate,o=n&&r?{version:n,package:r}:void 0;if(i){let s=await iO(e);s.length===0&&(console.log(JSON.stringify({valid:!1,error:"No git repository found"})),process.exit(1));let a=null,c=[];for(let d of s){let f=new Kr({workspaceRoot:d}),T=await $o.initialize(f,{apiKey:t,lspClient:o});"failed"in T?c.push({repo:d,success:!1,error:T.error}):(c.push({repo:d,success:!0}),a||(a=T))}if(!a){let d=c.length===1?c[0].error:`No repositories validated successfully (tried ${c.length} repositories)`;console.log(JSON.stringify({valid:!1,error:d,validationResults:c})),process.exit(1)}let u=a.getContext(),l=c.filter(d=>d.success).length,E="https://app.wispbit.com/setup/cli";r&&r.includes("vscode")&&(E="https://app.wispbit.com/setup/vscode"),console.log(JSON.stringify({valid:!0,organizationId:u?.organization_id,organizationName:u?.organization_name,repositoryId:u?.repository_id,repositoryUrl:u?.repository_url,repositoryOwner:u?.repository_owner,repositoryName:u?.repository_name,setupUrl:E,discoveredRepositories:s.length,validRepositories:l,validationResults:c})),process.exit(0)}await UWe({workspacePath:e,apiKey:t,lspClient:o})}async function VMt(t){let e=new Kr({repositoryUrl:t});await Yg(e,{force:!0})}function GMt(){return new Promise((t,e)=>{let n="";process.stdin.setEncoding("utf8"),process.stdin.on("data",r=>{n+=r}),process.stdin.on("end",()=>{t(n)}),process.stdin.on("error",e)})}async function BMt(t,e){let n=await e.loadAllRules(),r=n.find(i=>i.id===t||i.internalId===t);return r||(console.error(j.red(`Error: Rule not found: ${t}`)),console.error(j.dim(`Available rules: ${n.map(i=>i.id).join(", ")}`)),process.exit(1)),r}async function FMt(t,e){let n=Al.resolve(e,t);try{await Ss.access(n)}catch{console.error(j.red(`Error: File not found: ${t}`)),console.error(j.dim(`Workspace root: ${e}`)),process.exit(1)}return n}async function kMt(t){let{ruleId:e,filePath:n,lineNumbers:r,repoUrl:i}=t,o=new Kr({repositoryUrl:i}),s=await Yg(o),a=new jo(s,o),c=await BMt(e,a);n&&await FMt(n,o.getWorkspaceRoot());let u=await rK({ruleId:c.internalId,mode:"diff",filePath:n,repoUrl:i}),l=[];for(let f of u)for(let T of f.matches)if(r&&r.length>0){let p=T.range.start.line;r.includes(p)&&l.push(T)}else l.push(T);if(l.length===0){let f=n?` in ${n}`:"";console.log(j.yellow(`No violations found for rule ${c.id}${f}`));return}let E=0;for(let f of l)await a.createDismissal(c.internalId,f),E++;console.log(j.green(`\u2713 Dismissed ${E} violation(s) for rule ${c.id}`)),console.log(j.dim(`
402
+ `,{importMeta:import.meta,flags:{rule:{type:"string"},file:{type:"string"},json:{type:"string"},include:{type:"string"},repoUrl:{type:"string"},workspace:{type:"string"},lspClientVersion:{type:"string"},lspClientPackage:{type:"string"},validate:{type:"boolean",default:!1},apiKey:{type:"string"},line:{type:"string"},fix:{type:"string"},dismiss:{type:"string"},version:{type:"boolean",shortFlag:"v"},help:{type:"boolean",shortFlag:"h"}},version:Yo()});async function rK(t){let e=new Kr({repositoryUrl:t.repoUrl}),n=await Yg(e),r=e.getWorkspaceRoot(),{ruleId:i,json:o,mode:s,filePath:a}=t,{commitSelector:c,diffInclude:u}=t;if(s==="diff"){let H=e.getWorkspaceRoot();if(c)u||(u=(await ga(H)).include);else{let oe=await ga(H);c=oe.commitSelector,u||(u=oe.include)}}if(s==="diff"&&c&&u){let H=e.getWorkspaceRoot(),oe=await aV(H),te=cV(c,u,oe);te&&(console.error(j.red(te)),process.exit(1))}let l=!1,E="pretty";o!==void 0?(l=!0,typeof o=="string"?o==="stream"?E="stream":o==="compact"?E="compact":E="pretty":E="pretty"):await FWe();let d,f=new jo(n,e);if(i?d=[await f.loadRuleById(i)]:d=await f.loadAllRules(),!l){let H=n.getContext(),oe=H?.organization_name||"",te=H?.repository_owner||"",Ee=H?.repository_name||"",Re=oe&&te&&Ee?j.dim(` {${oe}:${te}/${Ee}}`):"",Ce=j.bgHex("#4a90e2").black(" DIFF "),Be=(c||"").replace(/\b[0-9a-f]{30,}\b/gi,rt=>rt.substring(0,7)),Ze=a?j.dim(` (${a})`):"",xt=u?` ${Be} ${j.dim(`[${u.join("/")}]`)}`:` ${Be}`;console.log(`${Ce}${xt}${Ze}${Re}`)}let T=new zr,p=u?u.join(", "):"all";T.setExecutionMode("diff",{baseCommit:c||"",headCommit:p});let S=new Map(d.map(H=>[H.id,{message:H.message,severity:H.severity,internalId:H.internalId,execution:H.execution}])),m=process.env.CLAUDECODE==="1",O=s==="diff"&&!l&&!m,h=!t.json&&!l&&!m?L1(T,O,S,r):void 0,C=Date.now(),P=new La(n,e,T),G=0,Y=[];T.on("files:discovery:complete",H=>{G=H.totalFiles}),T.on("rules:rule-error",H=>{let oe=d.find(te=>te.id===H.ruleId);oe&&(Y.push({ruleId:H.ruleId,internalId:oe.internalId,message:H.message,severity:H.severity,error:H.error}),CE(H.error,{tags:{source:"rule-execution",ruleId:H.ruleId,severity:H.severity},extra:{message:H.message,internalId:oe.internalId}}))});let re;l||(re=(await kWe(f)).dismissedMatchesByRule);let W=await Pa.initialize(n,e,s,T,a,s==="diff"?{include:u,commitSelector:c,skipPreExistingViolations:n.getSkipPreExistingViolationsEnabled()}:void 0),q=await P.execute(d,W,{dismissedMatchesByRule:re,emitErrors:!0}),Z=[];for(let H of q){let oe=d.find(te=>te.id===H.ruleId);if(oe){let Re={ruleId:H.ruleId,internalId:oe.internalId,message:oe.message,severity:oe.severity,execution:oe.execution,matches:H.matches,llmCost:void 0,llmTokens:void 0};Z.push(Re)}}if(t.fix!==void 0&&!l){let H=t.fix?t.fix.split(",").map(oe=>oe.trim()):void 0;await HWe(Z,d,f,r,H,j)}if(t.dismiss!==void 0&&!l){let H=t.dismiss?t.dismiss.split(",").map(oe=>oe.trim()):void 0;await YWe(Z,d,f,H,j)}if(h?.(),l)D1(Z,E,Y);else{let H=Z.filter(ft=>ft.severity==="violation"),oe=Z.filter(ft=>ft.severity==="suggestion"),te=H.reduce((ft,Ve)=>ft+Ve.matches.length,0),Ee=oe.reduce((ft,Ve)=>ft+Ve.matches.length,0),Re=te+Ee,Ce=Z.filter(ft=>ft.llmCost).reduce((ft,Ve)=>ft.plus(new sr(Ve.llmCost||0)),new sr(0)),Be=Z.filter(ft=>ft.llmTokens).reduce((ft,Ve)=>ft+(Ve.llmTokens||0),0),Ze=(c||"").replace(/\b[0-9a-f]{30,}\b/gi,ft=>ft.substring(0,7)),xt=u?u.join(", "):"all",rt={mode:"diff",baseCommit:Ze,headCommit:xt,filePath:a},At=Date.now()-C;P1(Z,{totalRules:d.length,violationCount:te,suggestionCount:Ee,totalMatches:Re,totalLLMCost:Ce.toString(),totalLLMTokens:Be,executionMode:rt,executionTime:At,totalFiles:G,ruleErrors:Y,debugMode:$y,showCommandHints:!0})}return Z}async function xWe(t){let e=Date.now(),n=new Na;await n.loadSession(t.sessionId);let i=n.getSessionData().workspaceRoot,o=new Kr({repositoryUrl:t.repoUrl,workspaceRoot:i}),s=await Yg(o),{ruleId:a,json:c}=t,u=!1,l="pretty";c!==void 0?(u=!0,typeof c=="string"?c==="stream"?l="stream":c==="compact"?l="compact":l="pretty":l="pretty"):await FWe();let E,d=new jo(s,o);a?E=[await d.loadRuleById(a)]:E=await d.loadAllRules();let f=new zr;f.setExecutionMode("session",{});let T=new Map(E.map(W=>[W.id,{message:W.message,severity:W.severity,internalId:W.internalId,execution:W.execution}])),p=process.env.CLAUDECODE==="1",S=!t.json&&!u&&!p?L1(f,!0,T,i):void 0,m=n.getFileChanges(),O=m.length,h;u||(h=(await kWe(d)).dismissedMatchesByRule);let C=new La(s,o,f),P=[],G=await Pa.initialize(s,o,"session",f,void 0,void 0,{fileChanges:m}),Y=await C.execute(E,G,{dismissedMatchesByRule:h,emitErrors:!0});f.on("rules:rule-error",W=>{P.push({ruleId:W.ruleId,message:W.message,severity:W.severity,error:W.error})});let re=[];for(let W of Y){let q=E.find(H=>H.id===W.ruleId);if(!q)continue;let Z={ruleId:W.ruleId,message:q.message,severity:q.severity,execution:q.execution,matches:W.matches.map(H=>({file:H.file,range:H.range,language:H.language||"Unknown",text:H.text,fingerprint:H.fingerprint,description:H.description,evidence:H.evidence,edits:H.edits})),llmCost:W.cost,llmTokens:void 0};re.push(Z)}if(S?.(),u)D1(re,l,P);else{let q=process.env.CLAUDECODE==="1"?new Cl({level:3}):j,Z=re.reduce((rt,At)=>rt+At.matches.length,0);if(t.fix===void 0&&t.dismiss===void 0)if(Z>0){let rt=q.red("wispbit found ")+q.red.bold(`${Z}`)+q.red(` ${Z===1?"issue":"issues"}`);console.log(rt)}else console.log(q.hex("#ff69b4")("wispbit found no issues"));if(console.log(q.dim.italic("reviewing changes from current Claude Code session only, run `wispbit diff` to view changes for all sessions")),console.log(),t.fix!==void 0){let rt=t.fix?t.fix.split(",").map(At=>At.trim()):void 0;await HWe(re,E,d,i,rt,q)}if(t.dismiss!==void 0){let rt=t.dismiss?t.dismiss.split(",").map(At=>At.trim()):void 0;await YWe(re,E,d,rt,q)}if(re.length>0&&t.fix===void 0&&t.dismiss===void 0){let rt=await xh(re,E,i,q);console.log(rt)}let H=re.filter(rt=>rt.severity==="violation"),oe=re.filter(rt=>rt.severity==="suggestion"),te=H.reduce((rt,At)=>rt+At.matches.length,0),Ee=oe.reduce((rt,At)=>rt+At.matches.length,0),Re=te+Ee,Ce=re.filter(rt=>rt.llmCost).reduce((rt,At)=>rt.plus(new sr(At.llmCost||0)),new sr(0)),Be=re.filter(rt=>rt.llmTokens).reduce((rt,At)=>rt+(At.llmTokens||0),0),Ze={mode:"session"},xt=Date.now()-e;t.fix===void 0&&t.dismiss===void 0&&P1(re,{totalRules:E.length,violationCount:te,suggestionCount:Ee,totalMatches:Re,totalLLMCost:Ce.toString(),totalLLMTokens:Be,executionMode:Ze,executionTime:xt,totalFiles:O,ruleErrors:P,debugMode:$y,showCommandHints:!0},q)}return re}async function wMt(t){let e=new Kr({repositoryUrl:t}),n=await Yg(e),i=await new jo(n,e).loadAllRules();FQ(i)}async function xMt(){let t=ot.flags.apiKey||process.env.WISPBIT_API_KEY;t||(console.error("WISPBIT_API_KEY environment variable or --api-key flag required"),process.exit(1));let e=ot.flags.workspace||process.cwd(),n=ot.flags.lspClientVersion,r=ot.flags.lspClientPackage,i=ot.flags.validate,o=n&&r?{version:n,package:r}:void 0;if(i){let s=await iO(e);s.length===0&&(console.log(JSON.stringify({valid:!1,error:"No git repository found"})),process.exit(1));let a=null,c=[];for(let d of s){let f=new Kr({workspaceRoot:d}),T=await $o.initialize(f,{apiKey:t,lspClient:o});"failed"in T?c.push({repo:d,success:!1,error:T.error}):(c.push({repo:d,success:!0}),a||(a=T))}if(!a){let d=c.length===1?c[0].error:`No repositories validated successfully (tried ${c.length} repositories)`;console.log(JSON.stringify({valid:!1,error:d,validationResults:c})),process.exit(1)}let u=a.getContext(),l=c.filter(d=>d.success).length,E="https://app.wispbit.com/setup/cli";r&&r.includes("vscode")&&(E="https://app.wispbit.com/setup/vscode"),console.log(JSON.stringify({valid:!0,organizationId:u?.organization_id,organizationName:u?.organization_name,repositoryId:u?.repository_id,repositoryUrl:u?.repository_url,repositoryOwner:u?.repository_owner,repositoryName:u?.repository_name,setupUrl:E,discoveredRepositories:s.length,validRepositories:l,validationResults:c})),process.exit(0)}await UWe({workspacePath:e,apiKey:t,lspClient:o})}async function VMt(t){let e=new Kr({repositoryUrl:t});await Yg(e,{force:!0})}function GMt(){return new Promise((t,e)=>{let n="";process.stdin.setEncoding("utf8"),process.stdin.on("data",r=>{n+=r}),process.stdin.on("end",()=>{t(n)}),process.stdin.on("error",e)})}async function BMt(t,e){let n=await e.loadAllRules(),r=n.find(i=>i.id===t||i.internalId===t);return r||(console.error(j.red(`Error: Rule not found: ${t}`)),console.error(j.dim(`Available rules: ${n.map(i=>i.id).join(", ")}`)),process.exit(1)),r}async function FMt(t,e){let n=Al.resolve(e,t);try{await Ss.access(n)}catch{console.error(j.red(`Error: File not found: ${t}`)),console.error(j.dim(`Workspace root: ${e}`)),process.exit(1)}return n}async function kMt(t){let{ruleId:e,filePath:n,lineNumbers:r,repoUrl:i}=t,o=new Kr({repositoryUrl:i}),s=await Yg(o),a=new jo(s,o),c=await BMt(e,a);n&&await FMt(n,o.getWorkspaceRoot());let u=await rK({ruleId:c.internalId,mode:"diff",filePath:n,repoUrl:i}),l=[];for(let f of u)for(let T of f.matches)if(r&&r.length>0){let p=T.range.start.line;r.includes(p)&&l.push(T)}else l.push(T);if(l.length===0){let f=n?` in ${n}`:"";console.log(j.yellow(`No violations found for rule ${c.id}${f}`));return}let E=0;for(let f of l)await a.createDismissal(c.internalId,f),E++;console.log(j.green(`\u2713 Dismissed ${E} violation(s) for rule ${c.id}`)),console.log(j.dim(`
403
403
  Files affected:`));let d=new Map;for(let f of l)d.has(f.file.path)||d.set(f.file.path,[]),d.get(f.file.path).push(f.range.start.line);for(let[f,T]of d)console.log(j.dim(` \u2022 ${f} (line ${T.join(", ")})`))}async function HMt(){let t=ot.input[0],e=ot.input[1];switch($y&&Ae.enable(),t){case"diff":{let n;if(ot.flags.include){let o=ot.flags.include.split(",").map(c=>c.trim()),s=["committed","staged","unstaged","untracked"],a=o.filter(c=>!s.includes(c));a.length>0&&(console.error(j.red(`Invalid include(s): ${a.join(", ")}. Valid includes: ${s.join(", ")}`)),process.exit(1)),n=o}let r=ot.input[1];await rK({ruleId:ot.flags.rule,json:ot.flags.json,mode:"diff",filePath:ot.flags.file,diffInclude:n,commitSelector:r,repoUrl:ot.flags.repoUrl,fix:ot.flags.fix,dismiss:ot.flags.dismiss});break}case"session":{let n=ot.input[1]||process.env.WISPBIT_SESSION_ID;n||(console.error(j.red("Error: No session ID provided")),console.error(j.dim("Usage: wispbit session <session-id> or set WISPBIT_SESSION_ID environment variable")),process.exit(1)),await xWe({sessionId:n,ruleId:ot.flags.rule,json:ot.flags.json,repoUrl:ot.flags.repoUrl,fix:ot.flags.fix,dismiss:ot.flags.dismiss});break}case"list":{await wMt(ot.flags.repoUrl);break}case"setup":{await VMt(ot.flags.repoUrl);break}case"dismiss":{ot.flags.rule||(console.error(j.red("Error: --rule flag is required")),console.error(j.dim("Usage: wispbit dismiss --rule <ruleId> [--file <path>] [--line <numbers>]")),process.exit(1));let n;ot.flags.line&&(n=ot.flags.line.split(",").map(r=>parseInt(r.trim(),10)).filter(r=>!isNaN(r))),await kMt({ruleId:ot.flags.rule,filePath:ot.flags.file,lineNumbers:n,repoUrl:ot.flags.repoUrl});break}case"cache":{if(e==="purge"){let n=new Kr({repositoryUrl:ot.flags.repoUrl}),i=await new EO(n).purgeCache();console.log(`
404
404
  ${j.green("Cache purged successfully.")} Removed ${i.deletedCount} item(s).`)}else console.error(j.red("Unknown cache subcommand:"),e),ot.showHelp(),process.exit(1);break}case"handle-hooks":{let n=e;(!n||!n.includes("."))&&(console.error(j.red("Invalid format. Expected: provider.event (e.g., cursor.afterFileEdit)")),process.exit(1));let r=await GMt();Ae.log(`[handle-hooks] Input: ${r}`);let i=JSON.parse(r),o=await $Q(n,i);Ae.log(`[handle-hooks] Output: ${JSON.stringify(o)}`),console.log(JSON.stringify(o));break}case"server":{await xMt();break}default:{let n=process.env.WISPBIT_SESSION_ID;if(n){await xWe({sessionId:n,ruleId:ot.flags.rule,json:ot.flags.json,repoUrl:ot.flags.repoUrl,fix:ot.flags.fix,dismiss:ot.flags.dismiss});break}let r;if(ot.flags.include){let s=ot.flags.include.split(",").map(u=>u.trim()),a=["committed","staged","unstaged","untracked"],c=s.filter(u=>!a.includes(u));c.length>0&&(console.error(j.red(`Invalid include(s): ${c.join(", ")}. Valid includes: ${a.join(", ")}`)),process.exit(1)),r=s}let i=ot.input[0];await rK({ruleId:ot.flags.rule,json:ot.flags.json,mode:"diff",filePath:ot.flags.file,diffInclude:r,commitSelector:i,repoUrl:ot.flags.repoUrl,fix:ot.flags.fix,dismiss:ot.flags.dismiss});break}}}HMt().catch(async t=>{await CE(t,{tags:{source:"cli"}}),await MWe(2e3),$y?console.error(t):console.error(j.red("Error:"),t.message||String(t)),process.exit(1)});export{FWe as checkForUpdates,NC as loadApiKey};
405
405
  /*! Bundled license information:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wispbit/local",
3
- "version": "1.0.89",
3
+ "version": "1.0.90",
4
4
  "type": "module",
5
5
  "main": "cli.js",
6
6
  "bin": {