@wispbit/local 1.0.80 → 1.0.81

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 +1 -1
  2. package/package.json +1 -1
package/cli-bundle.js CHANGED
@@ -279,7 +279,7 @@ ${ge}`)}else u.push(Y)}let E="";if(o&&(o.mode==="check"?E=o.filePath?` ${W.dim(`
279
279
  `;await CQ.promises.appendFile(o,a)}return{systemMessage:new gl({level:3}).dim.italic("wispbit will automatically review all changes in this session")}}async handlePostToolUse(e){vt.log(`[ClaudeHookHandler] PostToolUse (${e.tool_name}) for file ${e.tool_input.file_path}`);let n=new ga;if(!await n.getSession("claude",e.session_id)){vt.log("[ClaudeHookHandler] Session not initialized, skipping PostToolUse");return}let i=e.tool_input.file_path,o=fC.isAbsolute(i)?fC.relative(e.cwd,i):i,s,a;e.tool_name==="Write"?(a="",s=e.tool_input.content||""):(a=e.tool_input.old_string||"",s=e.tool_input.new_string||""),await n.addFileChange(o,a,s),vt.log(`[ClaudeHookHandler] Added change for ${o}`)}async handleStop(e){vt.log(`[ClaudeHookHandler] Stop for session ${e.session_id}`);let n=new ga,r=await n.getSession("claude",e.session_id);if(!r){vt.log("[ClaudeHookHandler] Session not initialized, skipping Stop");return}vt.log(`[ClaudeHookHandler] Wispbit session ID: ${r.wispbitSessionId}`);let i=n.getLastCheckpointTimestamp();if((i?n.getFileChanges(i):n.getFileChanges()).length===0){vt.log("[ClaudeHookHandler] No file changes since last checkpoint, skipping");return}let s=n.getFileChanges();vt.log(`[ClaudeHookHandler] Found ${s.length} files changed in session`);for(let M of s)vt.log(`
280
280
  [ClaudeHookHandler] File: ${M.filename} (${M.status})`),vt.log(`[ClaudeHookHandler] +${M.additions} -${M.deletions}`),vt.log(`[ClaudeHookHandler] Diff:
281
281
  ${M.patch}`);let{results:a,rules:c}=await this.runPowerlint(e.cwd,s),u=a.flatMap(M=>M.matches.map(G=>({...G,ruleId:M.ruleId}))),l=n.getLastCheckpointMatches(),E=new Map;for(let M of u){let G=M.ruleId;E.has(G)||E.set(G,[]),E.get(G).push(M)}let d=new Map;for(let M of l)d.has(M.ruleId)||d.set(M.ruleId,[]),d.get(M.ruleId).push(M);let T=[];for(let[M,G]of E.entries()){let H=d.get(M)||[],ne=G.map(j=>({file:j.file.path,startLine:j.range.start.line,endLine:j.range.end.line,fingerprint:j.fingerprint})),Z=H.map(j=>({file:j.file.path,startLine:j.range.start.line,endLine:j.range.end.line,fingerprint:j.fingerprint})),q=hh(ne,Z),Y=G.filter((j,se)=>!q.has(se));T.push(...Y)}let f=new Map;for(let M of T){let G=M.ruleId;f.has(G)||f.set(G,[]),f.get(G).push(M)}let p=Array.from(f.entries()).map(([M,G])=>({ruleId:M,matches:G})),S=new Map;for(let M of u){let G=M.ruleId;S.has(G)||S.set(G,[]),S.get(G).push(M)}let h=Array.from(S.entries()).map(([M,G])=>({ruleId:M,matches:G})),O=T.length,m=u.length;vt.log(`[ClaudeHookHandler] New: ${O}, Total: ${m}`),await n.createCheckpoint(T);let C=await this.buildStopMessage(p,h,c,e.cwd,O,m,s.length);if(vt.log(`[ClaudeHookHandler] Built system message: ${C?"yes":"no"}`),!!C)return{systemMessage:C}}async handleSessionEnd(e){vt.log(`[ClaudeHookHandler] SessionEnd (${e.reason}) for session ${e.session_id}`);let n=new ga;if(!await n.getSession("claude",e.session_id)){vt.log("[ClaudeHookHandler] Session not initialized, skipping SessionEnd");return}await n.endSession()}async runPowerlint(e,n){let r=new Kr({repositoryUrl:void 0,workspaceRoot:e}),i=await TC(),o=await Yo.initialize(r,{apiKey:i||void 0});if("failed"in o)throw new Error(`Failed to initialize config: ${o.error}`);let s=o,a=new zr,c=new $o(s,r),u=await c.loadAllRules(),l=new Ma(s,r,a),E=await c.getDismissals([]),d=new Map;for(let f of E)d.has(f.ruleId)||d.set(f.ruleId,[]),d.get(f.ruleId).push(f.match);return{results:await l.execute(u,{mode:"session",customDiffOptions:{fileChanges:n},dismissedMatchesByRule:d}),rules:u}}async buildStopMessage(e,n,r,i,o,s,a){let c=e.filter(T=>T.matches.length>0),u=n.filter(T=>T.matches.length>0),l=new gl({level:3}),E;if(s===o)if(o>0)E=l.red("wispbit found ")+l.red.bold(`${o} new`)+l.red(` ${o===1?"issue":"issues"}`);else return null;else o>0?E=l.red("wispbit found ")+l.red.bold(`${o} new`)+l.red(` ${o===1?"issue":"issues"}`)+l.dim(` (${s} total)`):E=l.dim.italic(`wispbit found ${s} total ${s===1?"issue":"issues"} from ${a} ${a===1?"file edit":"file edits"} this session`);let d=[];if(c.length>0){let T=new Set;for(let p of u)for(let S of p.matches)T.add(S.file.path);let f=await yh(c,r,i,l,{maxMatchesPerRule:1,maxDiffLines:10});d.push(f),d.push("",E),d.push(l.dim("Run ")+l.cyan("!wispbit")+l.dim(" to view, ")+l.cyan("!wispbit --fix")+l.dim(" to fix, ")+l.cyan("!wispbit --dismiss")+l.dim(" to dismiss (add ")+l.cyan("RULE-123")+l.dim(" for specific rules)"))}else u.length>0?d.push(E+l.dim.italic(". Run ")+l.cyan("!wispbit")+l.dim.italic(" to view and fix issues.")):d.push(E);return d.join(`
282
- `)}};function IQ(t){switch(t){case"claude":return new dC;default:throw new Error(`Unknown hook provider: ${t}`)}}import*as Hc from"fs/promises";import*as MQ from"os";import*as bh from"path";var SC=class{getStorageDir(){return bh.join(MQ.homedir(),".wispbit","hooks")}getStoragePath(e){return bh.join(this.getStorageDir(),`${e}.json`)}async load(e){let n=this.getStoragePath(e);try{let r=await Hc.readFile(n,"utf-8");return JSON.parse(r)}catch{return null}}async save(e,n){let r=this.getStoragePath(e);await Hc.mkdir(bh.dirname(r),{recursive:!0}),await Hc.writeFile(r,JSON.stringify(n,null,2))}async clear(e){let n=this.getStoragePath(e);try{await Hc.unlink(n)}catch{}}};async function PQ(t,e){let[n,r]=t.split(".");if(!n||!r)throw new Error(`Invalid providerEvent format: ${t}. Expected "provider.event"`);let i=IQ(n),o=new SC,s=i.eventSchemas[r];if(!s)throw new Error(`Unknown event: ${r} for provider: ${n}`);let a=s.parse(e),c=i.getConversationId(a);i._setContext(o,c);let u=await i.handleEvent(r,a);return i._clearContext(),u??{}}var yr=ue(qne(),1);import{promises as tre}from"fs";import{join as nm,relative as nre}from"path";import{fileURLToPath as ys,pathToFileURL as Uut}from"url";var kI=class t{constructor(e,n,r,i){this._uri=e,this._languageId=n,this._version=r,this._content=i,this._lineOffsets=void 0}get uri(){return this._uri}get languageId(){return this._languageId}get version(){return this._version}getText(e){if(e){let n=this.offsetAt(e.start),r=this.offsetAt(e.end);return this._content.substring(n,r)}return this._content}update(e,n){for(let r of e)if(t.isIncremental(r)){let i=ere(r.range),o=this.offsetAt(i.start),s=this.offsetAt(i.end);this._content=this._content.substring(0,o)+r.text+this._content.substring(s,this._content.length);let a=Math.max(i.start.line,0),c=Math.max(i.end.line,0),u=this._lineOffsets,l=Jne(r.text,!1,o);if(c-a===l.length)for(let d=0,T=l.length;d<T;d++)u[d+a+1]=l[d];else l.length<1e4?u.splice(a+1,c-a,...l):this._lineOffsets=u=u.slice(0,a+1).concat(l,u.slice(c+1));let E=r.text.length-(s-o);if(E!==0)for(let d=a+1+l.length,T=u.length;d<T;d++)u[d]=u[d]+E}else if(t.isFull(r))this._content=r.text,this._lineOffsets=void 0;else throw new Error("Unknown change event received");this._version=n}getLineOffsets(){return this._lineOffsets===void 0&&(this._lineOffsets=Jne(this._content,!0)),this._lineOffsets}positionAt(e){e=Math.max(Math.min(e,this._content.length),0);let n=this.getLineOffsets(),r=0,i=n.length;if(i===0)return{line:0,character:e};for(;r<i;){let s=Math.floor((r+i)/2);n[s]>e?i=s:r=s+1}let o=r-1;return e=this.ensureBeforeEOL(e,n[o]),{line:o,character:e-n[o]}}offsetAt(e){let n=this.getLineOffsets();if(e.line>=n.length)return this._content.length;if(e.line<0)return 0;let r=n[e.line];if(e.character<=0)return r;let i=e.line+1<n.length?n[e.line+1]:this._content.length,o=Math.min(r+e.character,i);return this.ensureBeforeEOL(o,r)}ensureBeforeEOL(e,n){for(;e>n&&Qne(this._content.charCodeAt(e-1));)e--;return e}get lineCount(){return this.getLineOffsets().length}static isIncremental(e){let n=e;return n!=null&&typeof n.text=="string"&&n.range!==void 0&&(n.rangeLength===void 0||typeof n.rangeLength=="number")}static isFull(e){let n=e;return n!=null&&typeof n.text=="string"&&n.range===void 0&&n.rangeLength===void 0}},tm;(function(t){function e(i,o,s,a){return new kI(i,o,s,a)}t.create=e;function n(i,o,s){if(i instanceof kI)return i.update(o,s),i;throw new Error("TextDocument.update: document must be created by TextDocument.create")}t.update=n;function r(i,o){let s=i.getText(),a=fF(o.map(but),(l,E)=>{let d=l.range.start.line-E.range.start.line;return d===0?l.range.start.character-E.range.start.character:d}),c=0,u=[];for(let l of a){let E=i.offsetAt(l.range.start);if(E<c)throw new Error("Overlapping edit");E>c&&u.push(s.substring(c,E)),l.newText.length&&u.push(l.newText),c=i.offsetAt(l.range.end)}return u.push(s.substr(c)),u.join("")}t.applyEdits=r})(tm||(tm={}));function fF(t,e){if(t.length<=1)return t;let n=t.length/2|0,r=t.slice(0,n),i=t.slice(n);fF(r,e),fF(i,e);let o=0,s=0,a=0;for(;o<r.length&&s<i.length;)e(r[o],i[s])<=0?t[a++]=r[o++]:t[a++]=i[s++];for(;o<r.length;)t[a++]=r[o++];for(;s<i.length;)t[a++]=i[s++];return t}function Jne(t,e,n=0){let r=e?[n]:[];for(let i=0;i<t.length;i++){let o=t.charCodeAt(i);Qne(o)&&(o===13&&i+1<t.length&&t.charCodeAt(i+1)===10&&i++,r.push(n+i+1))}return r}function Qne(t){return t===13||t===10}function ere(t){let e=t.start,n=t.end;return e.line>n.line||e.line===n.line&&e.character>n.character?{start:n,end:e}:t}function but(t){let e=ere(t.range);return e!==t.range?{newText:t.newText,range:e}:t}function fi(t){let e=decodeURIComponent(t);return e.startsWith("file:///")&&(e=e.replace(/\\/g,"/")),e=e.replace(/^file:\/\/\/([a-z]):/,(n,r)=>`file:///${r.toUpperCase()}:`),e}var HI=class{syncedDocuments=new Map;diagnosticsByFileAndRule=new Map;dismissalsByFile=new Map;fixesByFile=new Map;listen(e,n){e.onDidOpenTextDocument(r=>{let i=r.textDocument,o=fi(i.uri),s=tm.create(o,i.languageId,i.version,i.text);this.syncedDocuments.set(o,s),n.onDidOpen?.(o,s)}),e.onDidChangeTextDocument(r=>{let i=r.textDocument,o=fi(i.uri),s=r.contentChanges;if(s.length===0)return;let a=i.version;if(a==null)return;let c=this.syncedDocuments.get(o);c&&(c=tm.update(c,s,a),this.syncedDocuments.set(o,c),n.onDidChangeContent?.(o,c,s))}),e.onDidCloseTextDocument(r=>{let i=fi(r.textDocument.uri);this.syncedDocuments.delete(i),n.onDidClose?.(i)}),e.onDidSaveTextDocument(r=>{let i=fi(r.textDocument.uri),o=this.syncedDocuments.get(i);o&&n.onDidSave?.(i,o)})}getDocument(e){let n=fi(e);return this.syncedDocuments.get(n)}getAllDocumentUris(){return Array.from(this.syncedDocuments.values()).map(e=>e.uri)}getAllDiagnosticUris(){return Array.from(this.diagnosticsByFileAndRule.keys())}setDiagnosticsForRule(e,n,r){let i=fi(e);this.diagnosticsByFileAndRule.has(i)||this.diagnosticsByFileAndRule.set(i,new Map),this.diagnosticsByFileAndRule.get(i).set(n,r)}getDiagnostics(e){let n=fi(e),r=this.diagnosticsByFileAndRule.get(n);if(!r)return[];let i=[];for(let[o,s]of r.entries())i.push(...s);return i}clearDiagnostics(e){let n=fi(e);this.diagnosticsByFileAndRule.delete(n)}setDismissals(e,n){this.dismissalsByFile.set(e,n)}getDismissals(e){return this.dismissalsByFile.get(e)||[]}hasDismissals(e){return this.dismissalsByFile.has(e)}clearDismissals(e){this.dismissalsByFile.delete(e)}setFixes(e,n){this.fixesByFile.set(e,n)}getFixes(e){return this.fixesByFile.get(e)||[]}hasFixes(e){return this.fixesByFile.has(e)}clearFixes(e){this.fixesByFile.delete(e)}};import{sep as vut}from"path";var YI=class{contexts=new Map;workspacePath;apiKey;lspClient;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 QN(this.workspacePath);for(let i of r){let o=await this.initializeContext(i).catch(s=>(n?.(i,s),null));o&&(this.contexts.set(i,o),e?.(i,o))}}async initializeContext(e){let n=new Kr({workspaceRoot:e}),r=await Yo.initialize(n,{apiKey:this.apiKey,lspClient:this.lspClient});if("failed"in r)throw new Error(`Config initialization failed for ${e}: ${r.error}`);let i=r,o=new $o(i,n),s=new zr,a=new Ma(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}}findContextForFile(e){return Array.from(this.contexts.entries()).filter(([r])=>e.startsWith(r+vut)||e===r).sort((r,i)=>i[0].length-r[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)}shutdown(){for(let e of this.contexts.values())e.ruleExecutor.clearCache();this.contexts.clear()}};function wut(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}:${xut(r)}`}function xut(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)}var SF=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,yr.createConnection)(yr.ProposedFeatures.all,process.stdin,process.stdout),this.documentManager=new HI,this.repositoryContextManager=new YI({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=ys(e);return this.repositoryContextManager.findContextForFile(n)}pathToNormalizedUri(e){let n=Uut(e).toString();return decodeURIComponent(n)}getDiagnosticsForUri(e){let n=this.documentManager.getDiagnostics(e);if(n.length===0){let r=fi(e),i=this.documentManager.getAllDiagnosticUris();for(let o of i)if(fi(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=nm(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=nm(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)}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)})}toRelativePath(e,n){if(!n){let r=this.pathToNormalizedUri(e);n=this.findContextForFile(r)||void 0}return n?nre(n.repoRoot,e):nre(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){let s=i.length;this.documentManager.hasDismissals(n)||await this.loadDismissalsForFile(e,n),this.documentManager.hasFixes(n)||await this.loadFixesForFile(e,n);let a={ruleId:r,matches:i},c=this.filterDismissedResults([a],n),u=c[0]?.matches.length||0,l=s-u,E=await this.filterFixedResults(e,c,n),d=E[0]?.matches.length||0,T=u-d,f=nm(e.repoRoot,n),p=this.pathToNormalizedUri(f),S=await this.convertResultsToDiagnostics(e,E,o,p);if(s>0){let O=o.find(C=>C.internalId===r)?.id||r,m=[];l>0&&m.push(`${l} dismissed`),T>0&&m.push(`${T} fixed`),m.length>0?this.connection.console.log(`[${e.repoRoot}] ${n}: ${S.length} diagnostic(s) created, ${m.join(", ")} (rule: ${O})`):this.connection.console.log(`[${e.repoRoot}] ${n}: ${S.length} diagnostic(s) created (rule: ${O})`)}return S}async getFileContent(e){let n=this.pathToNormalizedUri(e),r=this.documentManager.getDocument(n);return r?r.getText():await tre.readFile(e,"utf-8").catch(()=>null)}async computeFixForMatch(e,n){let r=await Cd(e,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=mh(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=nm(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&&u1(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})),f=mh(E,d).map(S=>a.matches.find(h=>h.range.start.line===S.startLine&&h.range.end.line===S.endLine&&h.fingerprint===S.fingerprint)),p=a.matches.length-f.length;return p>0&&this.connection.console.log(`[${e.repoRoot}] ${r}: Filtered out ${p} match(es) with active fixes`),{...a,matches:f}})}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=wut(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(h=>(this.connection.console.log(`Warning: Failed to compute fix for match: ${h}`),null)));let T=u.range.end.line-u.range.start.line+1,f=20,p;T>f?p={start:{line:u.range.start.line-1,character:u.range.start.column-1},end:{line:u.range.start.line-1,character:Number.MAX_SAFE_INTEGER}}:p={start:{line:u.range.start.line-1,character:u.range.start.column-1},end:{line:u.range.end.line-1,character:u.range.end.column-1}};let S={range:p,severity:yr.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(S)}}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=ys(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,this.hasRunInitialCheck=!0;try{this.cleanupProgress(),await this.startBatchProgress(0);try{for(let r of e)await this.executeForContext(r,null);this.cleanupProgress()}catch(r){this.connection.console.error(`Error executing rules: ${r.message}`),this.connection.console.error(r.stack),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}`),this.connection.console.error(i.stack),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 ed(e.repoRoot);if(e.lastCommitSelector=i,n!==null&&n.length>0){let s=n.filter(a=>this.findContextForFile(a)?.repoRoot===e.repoRoot);if(s.length===0){this.connection.console.log(`[${e.repoRoot}] No changed files in this repository, skipping`);return}for(let a of s){let c=this.toRelativePath(ys(a),e);this.connection.console.log(`[${e.repoRoot}] Executing rules for ${c}`),e.completedRulesCount=0,await e.ruleExecutor.execute(r,{mode:"diff",filePath:c,diffOptions:{include:o,commitSelector:i,skipPreExistingViolations:!0}})}}else await e.ruleExecutor.execute(r,{mode:"diff",diffOptions:{include:o,commitSelector:i,skipPreExistingViolations:!0}})}catch(r){this.connection.console.error(`[${e.repoRoot}] Error executing rules: ${r.message}`),this.connection.console.error(r.stack)}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(f=>f.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=ys(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=ys(e),d=[];for(let f of l.fileChanges){let S=f.filePath===E?e:f.fileUri,h=this.documentManager.getDocument(S),O=h?h.lineCount:f.oldContent.split(`
282
+ `)}};function IQ(t){switch(t){case"claude":return new dC;default:throw new Error(`Unknown hook provider: ${t}`)}}import*as Hc from"fs/promises";import*as MQ from"os";import*as bh from"path";var SC=class{getStorageDir(){return bh.join(MQ.homedir(),".wispbit","hooks")}getStoragePath(e){return bh.join(this.getStorageDir(),`${e}.json`)}async load(e){let n=this.getStoragePath(e);try{let r=await Hc.readFile(n,"utf-8");return JSON.parse(r)}catch{return null}}async save(e,n){let r=this.getStoragePath(e);await Hc.mkdir(bh.dirname(r),{recursive:!0}),await Hc.writeFile(r,JSON.stringify(n,null,2))}async clear(e){let n=this.getStoragePath(e);try{await Hc.unlink(n)}catch{}}};async function PQ(t,e){let[n,r]=t.split(".");if(!n||!r)throw new Error(`Invalid providerEvent format: ${t}. Expected "provider.event"`);let i=IQ(n),o=new SC,s=i.eventSchemas[r];if(!s)throw new Error(`Unknown event: ${r} for provider: ${n}`);let a=s.parse(e),c=i.getConversationId(a);i._setContext(o,c);let u=await i.handleEvent(r,a);return i._clearContext(),u??{}}var yr=ue(qne(),1);import{promises as tre}from"fs";import{join as nm,relative as nre}from"path";import{fileURLToPath as ys,pathToFileURL as Uut}from"url";var kI=class t{constructor(e,n,r,i){this._uri=e,this._languageId=n,this._version=r,this._content=i,this._lineOffsets=void 0}get uri(){return this._uri}get languageId(){return this._languageId}get version(){return this._version}getText(e){if(e){let n=this.offsetAt(e.start),r=this.offsetAt(e.end);return this._content.substring(n,r)}return this._content}update(e,n){for(let r of e)if(t.isIncremental(r)){let i=ere(r.range),o=this.offsetAt(i.start),s=this.offsetAt(i.end);this._content=this._content.substring(0,o)+r.text+this._content.substring(s,this._content.length);let a=Math.max(i.start.line,0),c=Math.max(i.end.line,0),u=this._lineOffsets,l=Jne(r.text,!1,o);if(c-a===l.length)for(let d=0,T=l.length;d<T;d++)u[d+a+1]=l[d];else l.length<1e4?u.splice(a+1,c-a,...l):this._lineOffsets=u=u.slice(0,a+1).concat(l,u.slice(c+1));let E=r.text.length-(s-o);if(E!==0)for(let d=a+1+l.length,T=u.length;d<T;d++)u[d]=u[d]+E}else if(t.isFull(r))this._content=r.text,this._lineOffsets=void 0;else throw new Error("Unknown change event received");this._version=n}getLineOffsets(){return this._lineOffsets===void 0&&(this._lineOffsets=Jne(this._content,!0)),this._lineOffsets}positionAt(e){e=Math.max(Math.min(e,this._content.length),0);let n=this.getLineOffsets(),r=0,i=n.length;if(i===0)return{line:0,character:e};for(;r<i;){let s=Math.floor((r+i)/2);n[s]>e?i=s:r=s+1}let o=r-1;return e=this.ensureBeforeEOL(e,n[o]),{line:o,character:e-n[o]}}offsetAt(e){let n=this.getLineOffsets();if(e.line>=n.length)return this._content.length;if(e.line<0)return 0;let r=n[e.line];if(e.character<=0)return r;let i=e.line+1<n.length?n[e.line+1]:this._content.length,o=Math.min(r+e.character,i);return this.ensureBeforeEOL(o,r)}ensureBeforeEOL(e,n){for(;e>n&&Qne(this._content.charCodeAt(e-1));)e--;return e}get lineCount(){return this.getLineOffsets().length}static isIncremental(e){let n=e;return n!=null&&typeof n.text=="string"&&n.range!==void 0&&(n.rangeLength===void 0||typeof n.rangeLength=="number")}static isFull(e){let n=e;return n!=null&&typeof n.text=="string"&&n.range===void 0&&n.rangeLength===void 0}},tm;(function(t){function e(i,o,s,a){return new kI(i,o,s,a)}t.create=e;function n(i,o,s){if(i instanceof kI)return i.update(o,s),i;throw new Error("TextDocument.update: document must be created by TextDocument.create")}t.update=n;function r(i,o){let s=i.getText(),a=fF(o.map(but),(l,E)=>{let d=l.range.start.line-E.range.start.line;return d===0?l.range.start.character-E.range.start.character:d}),c=0,u=[];for(let l of a){let E=i.offsetAt(l.range.start);if(E<c)throw new Error("Overlapping edit");E>c&&u.push(s.substring(c,E)),l.newText.length&&u.push(l.newText),c=i.offsetAt(l.range.end)}return u.push(s.substr(c)),u.join("")}t.applyEdits=r})(tm||(tm={}));function fF(t,e){if(t.length<=1)return t;let n=t.length/2|0,r=t.slice(0,n),i=t.slice(n);fF(r,e),fF(i,e);let o=0,s=0,a=0;for(;o<r.length&&s<i.length;)e(r[o],i[s])<=0?t[a++]=r[o++]:t[a++]=i[s++];for(;o<r.length;)t[a++]=r[o++];for(;s<i.length;)t[a++]=i[s++];return t}function Jne(t,e,n=0){let r=e?[n]:[];for(let i=0;i<t.length;i++){let o=t.charCodeAt(i);Qne(o)&&(o===13&&i+1<t.length&&t.charCodeAt(i+1)===10&&i++,r.push(n+i+1))}return r}function Qne(t){return t===13||t===10}function ere(t){let e=t.start,n=t.end;return e.line>n.line||e.line===n.line&&e.character>n.character?{start:n,end:e}:t}function but(t){let e=ere(t.range);return e!==t.range?{newText:t.newText,range:e}:t}function fi(t){let e=decodeURIComponent(t);return e.startsWith("file:///")&&(e=e.replace(/\\/g,"/")),e=e.replace(/^file:\/\/\/([a-z]):/,(n,r)=>`file:///${r.toUpperCase()}:`),e}var HI=class{syncedDocuments=new Map;diagnosticsByFileAndRule=new Map;dismissalsByFile=new Map;fixesByFile=new Map;listen(e,n){e.onDidOpenTextDocument(r=>{let i=r.textDocument,o=fi(i.uri),s=tm.create(o,i.languageId,i.version,i.text);this.syncedDocuments.set(o,s),n.onDidOpen?.(o,s)}),e.onDidChangeTextDocument(r=>{let i=r.textDocument,o=fi(i.uri),s=r.contentChanges;if(s.length===0)return;let a=i.version;if(a==null)return;let c=this.syncedDocuments.get(o);c&&(c=tm.update(c,s,a),this.syncedDocuments.set(o,c),n.onDidChangeContent?.(o,c,s))}),e.onDidCloseTextDocument(r=>{let i=fi(r.textDocument.uri);this.syncedDocuments.delete(i),n.onDidClose?.(i)}),e.onDidSaveTextDocument(r=>{let i=fi(r.textDocument.uri),o=this.syncedDocuments.get(i);o&&n.onDidSave?.(i,o)})}getDocument(e){let n=fi(e);return this.syncedDocuments.get(n)}getAllDocumentUris(){return Array.from(this.syncedDocuments.values()).map(e=>e.uri)}getAllDiagnosticUris(){return Array.from(this.diagnosticsByFileAndRule.keys())}setDiagnosticsForRule(e,n,r){let i=fi(e);this.diagnosticsByFileAndRule.has(i)||this.diagnosticsByFileAndRule.set(i,new Map),this.diagnosticsByFileAndRule.get(i).set(n,r)}getDiagnostics(e){let n=fi(e),r=this.diagnosticsByFileAndRule.get(n);if(!r)return[];let i=[];for(let[o,s]of r.entries())i.push(...s);return i}clearDiagnostics(e){let n=fi(e);this.diagnosticsByFileAndRule.delete(n)}setDismissals(e,n){this.dismissalsByFile.set(e,n)}getDismissals(e){return this.dismissalsByFile.get(e)||[]}hasDismissals(e){return this.dismissalsByFile.has(e)}clearDismissals(e){this.dismissalsByFile.delete(e)}setFixes(e,n){this.fixesByFile.set(e,n)}getFixes(e){return this.fixesByFile.get(e)||[]}hasFixes(e){return this.fixesByFile.has(e)}clearFixes(e){this.fixesByFile.delete(e)}};import{sep as vut}from"path";var YI=class{contexts=new Map;workspacePath;apiKey;lspClient;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 QN(this.workspacePath);for(let i of r){let o=await this.initializeContext(i).catch(s=>(n?.(i,s),null));o&&(this.contexts.set(i,o),e?.(i,o))}}async initializeContext(e){let n=new Kr({workspaceRoot:e}),r=await Yo.initialize(n,{apiKey:this.apiKey,lspClient:this.lspClient});if("failed"in r)throw new Error(`Config initialization failed for ${e}: ${r.error}`);let i=r,o=new $o(i,n),s=new zr,a=new Ma(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}}findContextForFile(e){let n=e.toLowerCase();return Array.from(this.contexts.entries()).filter(([i])=>{let o=i.toLowerCase();return n.startsWith(o+vut)||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)}shutdown(){for(let e of this.contexts.values())e.ruleExecutor.clearCache();this.contexts.clear()}};function wut(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}:${xut(r)}`}function xut(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)}var SF=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,yr.createConnection)(yr.ProposedFeatures.all,process.stdin,process.stdout),this.documentManager=new HI,this.repositoryContextManager=new YI({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=ys(e);return this.repositoryContextManager.findContextForFile(n)}pathToNormalizedUri(e){let n=Uut(e).toString();return decodeURIComponent(n)}getDiagnosticsForUri(e){let n=this.documentManager.getDiagnostics(e);if(n.length===0){let r=fi(e),i=this.documentManager.getAllDiagnosticUris();for(let o of i)if(fi(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=nm(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=nm(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)}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)})}toRelativePath(e,n){if(!n){let r=this.pathToNormalizedUri(e);n=this.findContextForFile(r)||void 0}return n?nre(n.repoRoot,e):nre(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){let s=i.length;this.documentManager.hasDismissals(n)||await this.loadDismissalsForFile(e,n),this.documentManager.hasFixes(n)||await this.loadFixesForFile(e,n);let a={ruleId:r,matches:i},c=this.filterDismissedResults([a],n),u=c[0]?.matches.length||0,l=s-u,E=await this.filterFixedResults(e,c,n),d=E[0]?.matches.length||0,T=u-d,f=nm(e.repoRoot,n),p=this.pathToNormalizedUri(f),S=await this.convertResultsToDiagnostics(e,E,o,p);if(s>0){let O=o.find(C=>C.internalId===r)?.id||r,m=[];l>0&&m.push(`${l} dismissed`),T>0&&m.push(`${T} fixed`),m.length>0?this.connection.console.log(`[${e.repoRoot}] ${n}: ${S.length} diagnostic(s) created, ${m.join(", ")} (rule: ${O})`):this.connection.console.log(`[${e.repoRoot}] ${n}: ${S.length} diagnostic(s) created (rule: ${O})`)}return S}async getFileContent(e){let n=this.pathToNormalizedUri(e),r=this.documentManager.getDocument(n);return r?r.getText():await tre.readFile(e,"utf-8").catch(()=>null)}async computeFixForMatch(e,n){let r=await Cd(e,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=mh(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=nm(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&&u1(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})),f=mh(E,d).map(S=>a.matches.find(h=>h.range.start.line===S.startLine&&h.range.end.line===S.endLine&&h.fingerprint===S.fingerprint)),p=a.matches.length-f.length;return p>0&&this.connection.console.log(`[${e.repoRoot}] ${r}: Filtered out ${p} match(es) with active fixes`),{...a,matches:f}})}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=wut(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(h=>(this.connection.console.log(`Warning: Failed to compute fix for match: ${h}`),null)));let T=u.range.end.line-u.range.start.line+1,f=20,p;T>f?p={start:{line:u.range.start.line-1,character:u.range.start.column-1},end:{line:u.range.start.line-1,character:Number.MAX_SAFE_INTEGER}}:p={start:{line:u.range.start.line-1,character:u.range.start.column-1},end:{line:u.range.end.line-1,character:u.range.end.column-1}};let S={range:p,severity:yr.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(S)}}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=ys(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,this.hasRunInitialCheck=!0;try{this.cleanupProgress(),await this.startBatchProgress(0);try{for(let r of e)await this.executeForContext(r,null);this.cleanupProgress()}catch(r){this.connection.console.error(`Error executing rules: ${r.message}`),this.connection.console.error(r.stack),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}`),this.connection.console.error(i.stack),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 ed(e.repoRoot);if(e.lastCommitSelector=i,n!==null&&n.length>0){let s=n.filter(a=>this.findContextForFile(a)?.repoRoot===e.repoRoot);if(s.length===0){this.connection.console.log(`[${e.repoRoot}] No changed files in this repository, skipping`);return}for(let a of s){let c=this.toRelativePath(ys(a),e);this.connection.console.log(`[${e.repoRoot}] Executing rules for ${c}`),e.completedRulesCount=0,await e.ruleExecutor.execute(r,{mode:"diff",filePath:c,diffOptions:{include:o,commitSelector:i,skipPreExistingViolations:!0}})}}else await e.ruleExecutor.execute(r,{mode:"diff",diffOptions:{include:o,commitSelector:i,skipPreExistingViolations:!0}})}catch(r){this.connection.console.error(`[${e.repoRoot}] Error executing rules: ${r.message}`),this.connection.console.error(r.stack)}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(f=>f.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=ys(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=ys(e),d=[];for(let f of l.fileChanges){let S=f.filePath===E?e:f.fileUri,h=this.documentManager.getDocument(S),O=h?h.lineCount:f.oldContent.split(`
283
283
  `).length;h||f.oldContent.length>0||d.push(yr.CreateFile.create(S,{overwrite:!1,ignoreIfExists:!0}));let C={textDocument:{uri:S,version:h?.version??null},edits:[yr.TextEdit.replace({start:{line:0,character:0},end:{line:O,character:0}},f.newContent)]};d.push(C)}let T=await this.connection.workspace.applyEdit({documentChanges:d});T.applied?this.connection.console.log(`[${a.repoRoot}] Applied fix successfully`):this.connection.console.log(`[${a.repoRoot}] Could not apply fix. Reason: ${T.failureReason}, Change: ${T.failedChange}`),await a.ruleProvider.createFix(s?.id,o).catch(f=>{this.connection.console.log(`[${a.repoRoot}] Failed to track fix: ${f.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=ys(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 h=S.data?.rule?.id,O=S.range.start.line+1,m=S.range.end.line+1;return h===i&&O<=s&&m>=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,T=E.data?.rule?.id,f=E.data?.matchId;if(!d||!T||!f){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:T,startLine:E.range.start.line+1,endLine:E.range.end.line+1,matchId:f,timestamp:Date.now()}),this.removeDiagnosticByMatchId(n,f),await a.ruleProvider.createDismissal(T,d).catch(S=>{this.connection.console.log(`[${a.repoRoot}] Failed to create dismissal: ${S.message}`)});let p=E.data?.rule?.displayId||T;this.connection.console.log(`[${a.repoRoot}] Dismissed violation: ${p} with matchId ${f}`),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=ys(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=fi(n),l=this.documentManager.getAllDocumentUris();for(let E of l)if(fi(E)===u){c=this.documentManager.getDocument(E);break}}return s.map(u=>{let l=a.find(T=>T.internalId===u.ruleId),E="";if(c){let T=c.getText({start:{line:u.startLine-1,character:0},end:{line:u.startLine-1,character:100}});E=T.trim().substring(0,60),T.trim().length>60&&(E+="...")}let d="";if(u.dismissedAt){let T=new Date,f=new Date(u.dismissedAt),p=T.getTime()-f.getTime(),S=Math.floor(p/6e4),h=Math.floor(S/60),O=Math.floor(h/24);S<1?d="just now":S<60?d=`${S} minute${S===1?"":"s"} ago`:h<24?d=`${h} hour${h===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=ys(n),s=this.toRelativePath(o,i),c=this.documentManager.getDismissals(s).find(T=>T.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(T=>T.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=ys(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 T=this.truncateMessage(c.message);r.push({title:`Apply fix: ${T}`,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: ${T}`,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:T}of s.diffs){if(!(d.path===a)){let p=nm(l,d.path),S=this.pathToNormalizedUri(p);E+=`*[${d.path}](${S})*
284
284
  `}E+="```diff\n",E+=T,E+="\n```\n\n"}return o?.summary&&(o.summary.content&&(E+=`**Summary:** ${o.summary.content}
285
285
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wispbit/local",
3
- "version": "1.0.80",
3
+ "version": "1.0.81",
4
4
  "type": "module",
5
5
  "main": "cli.js",
6
6
  "bin": {