pando-ai 0.1.4 → 0.1.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +124 -124
- package/dist/watcher-process.js +421 -421
- package/dist/workers/chunk-Z7LW7C4Z.mjs +518 -0
- package/dist/workers/indexer-worker.mjs +1 -1
- package/dist/workers/snapshot-worker.mjs +8 -4
- package/package.json +5 -4
- package/resources/tools/{pando-tools.json → generated_pando-tools.json} +98 -4
- package/resources/tools/generated_tools.md +93 -0
- package/tools/clojure-editor/lib/pando-clojure-editor-standalone.jar +0 -0
- package/tools/clojure-indexer/lib/pando-clojure-indexer-standalone.jar +0 -0
- package/tools/csharp-indexer/CSharpIndexer.csproj +1 -1
- package/tools/csharp-indexer/bin/pando-csharp-indexer +81 -23
- package/tools/csharp-indexer/bin/pando-csharp-indexer.cmd +82 -14
- package/tools/csharp-indexer/src/Program.cs +1860 -0
- package/dist/workers/chunk-BD3AO7O3.mjs +0 -522
- package/tools/csharp-indexer/bin/Release/net10.0/CSharpIndexer +0 -0
- package/tools/csharp-indexer/bin/Release/net10.0/CSharpIndexer.deps.json +0 -383
- package/tools/csharp-indexer/bin/Release/net10.0/CSharpIndexer.dll +0 -0
- package/tools/csharp-indexer/bin/Release/net10.0/CSharpIndexer.pdb +0 -0
- package/tools/csharp-indexer/bin/Release/net10.0/CSharpIndexer.runtimeconfig.json +0 -13
- package/tools/csharp-indexer/bin/Release/net10.0/Humanizer.dll +0 -0
- package/tools/csharp-indexer/bin/Release/net10.0/Microsoft.CodeAnalysis.CSharp.Workspaces.dll +0 -0
- package/tools/csharp-indexer/bin/Release/net10.0/Microsoft.CodeAnalysis.CSharp.dll +0 -0
- package/tools/csharp-indexer/bin/Release/net10.0/Microsoft.CodeAnalysis.Workspaces.dll +0 -0
- package/tools/csharp-indexer/bin/Release/net10.0/Microsoft.CodeAnalysis.dll +0 -0
- package/tools/csharp-indexer/bin/Release/net10.0/System.Composition.AttributedModel.dll +0 -0
- package/tools/csharp-indexer/bin/Release/net10.0/System.Composition.Convention.dll +0 -0
- package/tools/csharp-indexer/bin/Release/net10.0/System.Composition.Hosting.dll +0 -0
- package/tools/csharp-indexer/bin/Release/net10.0/System.Composition.Runtime.dll +0 -0
- package/tools/csharp-indexer/bin/Release/net10.0/System.Composition.TypedParts.dll +0 -0
- package/tools/csharp-indexer/bin/Release/net10.0/cs/Microsoft.CodeAnalysis.CSharp.Workspaces.resources.dll +0 -0
- package/tools/csharp-indexer/bin/Release/net10.0/cs/Microsoft.CodeAnalysis.CSharp.resources.dll +0 -0
- package/tools/csharp-indexer/bin/Release/net10.0/cs/Microsoft.CodeAnalysis.Workspaces.resources.dll +0 -0
- package/tools/csharp-indexer/bin/Release/net10.0/cs/Microsoft.CodeAnalysis.resources.dll +0 -0
- package/tools/csharp-indexer/bin/Release/net10.0/de/Microsoft.CodeAnalysis.CSharp.Workspaces.resources.dll +0 -0
- package/tools/csharp-indexer/bin/Release/net10.0/de/Microsoft.CodeAnalysis.CSharp.resources.dll +0 -0
- package/tools/csharp-indexer/bin/Release/net10.0/de/Microsoft.CodeAnalysis.Workspaces.resources.dll +0 -0
- package/tools/csharp-indexer/bin/Release/net10.0/de/Microsoft.CodeAnalysis.resources.dll +0 -0
- package/tools/csharp-indexer/bin/Release/net10.0/es/Microsoft.CodeAnalysis.CSharp.Workspaces.resources.dll +0 -0
- package/tools/csharp-indexer/bin/Release/net10.0/es/Microsoft.CodeAnalysis.CSharp.resources.dll +0 -0
- package/tools/csharp-indexer/bin/Release/net10.0/es/Microsoft.CodeAnalysis.Workspaces.resources.dll +0 -0
- package/tools/csharp-indexer/bin/Release/net10.0/es/Microsoft.CodeAnalysis.resources.dll +0 -0
- package/tools/csharp-indexer/bin/Release/net10.0/fr/Microsoft.CodeAnalysis.CSharp.Workspaces.resources.dll +0 -0
- package/tools/csharp-indexer/bin/Release/net10.0/fr/Microsoft.CodeAnalysis.CSharp.resources.dll +0 -0
- package/tools/csharp-indexer/bin/Release/net10.0/fr/Microsoft.CodeAnalysis.Workspaces.resources.dll +0 -0
- package/tools/csharp-indexer/bin/Release/net10.0/fr/Microsoft.CodeAnalysis.resources.dll +0 -0
- package/tools/csharp-indexer/bin/Release/net10.0/it/Microsoft.CodeAnalysis.CSharp.Workspaces.resources.dll +0 -0
- package/tools/csharp-indexer/bin/Release/net10.0/it/Microsoft.CodeAnalysis.CSharp.resources.dll +0 -0
- package/tools/csharp-indexer/bin/Release/net10.0/it/Microsoft.CodeAnalysis.Workspaces.resources.dll +0 -0
- package/tools/csharp-indexer/bin/Release/net10.0/it/Microsoft.CodeAnalysis.resources.dll +0 -0
- package/tools/csharp-indexer/bin/Release/net10.0/ja/Microsoft.CodeAnalysis.CSharp.Workspaces.resources.dll +0 -0
- package/tools/csharp-indexer/bin/Release/net10.0/ja/Microsoft.CodeAnalysis.CSharp.resources.dll +0 -0
- package/tools/csharp-indexer/bin/Release/net10.0/ja/Microsoft.CodeAnalysis.Workspaces.resources.dll +0 -0
- package/tools/csharp-indexer/bin/Release/net10.0/ja/Microsoft.CodeAnalysis.resources.dll +0 -0
- package/tools/csharp-indexer/bin/Release/net10.0/ko/Microsoft.CodeAnalysis.CSharp.Workspaces.resources.dll +0 -0
- package/tools/csharp-indexer/bin/Release/net10.0/ko/Microsoft.CodeAnalysis.CSharp.resources.dll +0 -0
- package/tools/csharp-indexer/bin/Release/net10.0/ko/Microsoft.CodeAnalysis.Workspaces.resources.dll +0 -0
- package/tools/csharp-indexer/bin/Release/net10.0/ko/Microsoft.CodeAnalysis.resources.dll +0 -0
- package/tools/csharp-indexer/bin/Release/net10.0/pl/Microsoft.CodeAnalysis.CSharp.Workspaces.resources.dll +0 -0
- package/tools/csharp-indexer/bin/Release/net10.0/pl/Microsoft.CodeAnalysis.CSharp.resources.dll +0 -0
- package/tools/csharp-indexer/bin/Release/net10.0/pl/Microsoft.CodeAnalysis.Workspaces.resources.dll +0 -0
- package/tools/csharp-indexer/bin/Release/net10.0/pl/Microsoft.CodeAnalysis.resources.dll +0 -0
- package/tools/csharp-indexer/bin/Release/net10.0/pt-BR/Microsoft.CodeAnalysis.CSharp.Workspaces.resources.dll +0 -0
- package/tools/csharp-indexer/bin/Release/net10.0/pt-BR/Microsoft.CodeAnalysis.CSharp.resources.dll +0 -0
- package/tools/csharp-indexer/bin/Release/net10.0/pt-BR/Microsoft.CodeAnalysis.Workspaces.resources.dll +0 -0
- package/tools/csharp-indexer/bin/Release/net10.0/pt-BR/Microsoft.CodeAnalysis.resources.dll +0 -0
- package/tools/csharp-indexer/bin/Release/net10.0/ru/Microsoft.CodeAnalysis.CSharp.Workspaces.resources.dll +0 -0
- package/tools/csharp-indexer/bin/Release/net10.0/ru/Microsoft.CodeAnalysis.CSharp.resources.dll +0 -0
- package/tools/csharp-indexer/bin/Release/net10.0/ru/Microsoft.CodeAnalysis.Workspaces.resources.dll +0 -0
- package/tools/csharp-indexer/bin/Release/net10.0/ru/Microsoft.CodeAnalysis.resources.dll +0 -0
- package/tools/csharp-indexer/bin/Release/net10.0/tr/Microsoft.CodeAnalysis.CSharp.Workspaces.resources.dll +0 -0
- package/tools/csharp-indexer/bin/Release/net10.0/tr/Microsoft.CodeAnalysis.CSharp.resources.dll +0 -0
- package/tools/csharp-indexer/bin/Release/net10.0/tr/Microsoft.CodeAnalysis.Workspaces.resources.dll +0 -0
- package/tools/csharp-indexer/bin/Release/net10.0/tr/Microsoft.CodeAnalysis.resources.dll +0 -0
- package/tools/csharp-indexer/bin/Release/net10.0/zh-Hans/Microsoft.CodeAnalysis.CSharp.Workspaces.resources.dll +0 -0
- package/tools/csharp-indexer/bin/Release/net10.0/zh-Hans/Microsoft.CodeAnalysis.CSharp.resources.dll +0 -0
- package/tools/csharp-indexer/bin/Release/net10.0/zh-Hans/Microsoft.CodeAnalysis.Workspaces.resources.dll +0 -0
- package/tools/csharp-indexer/bin/Release/net10.0/zh-Hans/Microsoft.CodeAnalysis.resources.dll +0 -0
- package/tools/csharp-indexer/bin/Release/net10.0/zh-Hant/Microsoft.CodeAnalysis.CSharp.Workspaces.resources.dll +0 -0
- package/tools/csharp-indexer/bin/Release/net10.0/zh-Hant/Microsoft.CodeAnalysis.CSharp.resources.dll +0 -0
- package/tools/csharp-indexer/bin/Release/net10.0/zh-Hant/Microsoft.CodeAnalysis.Workspaces.resources.dll +0 -0
- package/tools/csharp-indexer/bin/Release/net10.0/zh-Hant/Microsoft.CodeAnalysis.resources.dll +0 -0
- package/tools/csharp-indexer/bin/Release/net8.0/CSharpIndexer +0 -0
- package/tools/csharp-indexer/bin/Release/net8.0/CSharpIndexer.deps.json +0 -400
- package/tools/csharp-indexer/bin/Release/net8.0/CSharpIndexer.dll +0 -0
- package/tools/csharp-indexer/bin/Release/net8.0/CSharpIndexer.pdb +0 -0
- package/tools/csharp-indexer/bin/Release/net8.0/CSharpIndexer.runtimeconfig.json +0 -13
- package/tools/csharp-indexer/bin/Release/net8.0/Humanizer.dll +0 -0
- package/tools/csharp-indexer/bin/Release/net8.0/Microsoft.CodeAnalysis.CSharp.Workspaces.dll +0 -0
- package/tools/csharp-indexer/bin/Release/net8.0/Microsoft.CodeAnalysis.CSharp.dll +0 -0
- package/tools/csharp-indexer/bin/Release/net8.0/Microsoft.CodeAnalysis.Workspaces.dll +0 -0
- package/tools/csharp-indexer/bin/Release/net8.0/Microsoft.CodeAnalysis.dll +0 -0
- package/tools/csharp-indexer/bin/Release/net8.0/System.Composition.AttributedModel.dll +0 -0
- package/tools/csharp-indexer/bin/Release/net8.0/System.Composition.Convention.dll +0 -0
- package/tools/csharp-indexer/bin/Release/net8.0/System.Composition.Hosting.dll +0 -0
- package/tools/csharp-indexer/bin/Release/net8.0/System.Composition.Runtime.dll +0 -0
- package/tools/csharp-indexer/bin/Release/net8.0/System.Composition.TypedParts.dll +0 -0
- package/tools/csharp-indexer/bin/Release/net8.0/System.IO.Pipelines.dll +0 -0
- package/tools/csharp-indexer/bin/Release/net8.0/cs/Microsoft.CodeAnalysis.CSharp.Workspaces.resources.dll +0 -0
- package/tools/csharp-indexer/bin/Release/net8.0/cs/Microsoft.CodeAnalysis.CSharp.resources.dll +0 -0
- package/tools/csharp-indexer/bin/Release/net8.0/cs/Microsoft.CodeAnalysis.Workspaces.resources.dll +0 -0
- package/tools/csharp-indexer/bin/Release/net8.0/cs/Microsoft.CodeAnalysis.resources.dll +0 -0
- package/tools/csharp-indexer/bin/Release/net8.0/de/Microsoft.CodeAnalysis.CSharp.Workspaces.resources.dll +0 -0
- package/tools/csharp-indexer/bin/Release/net8.0/de/Microsoft.CodeAnalysis.CSharp.resources.dll +0 -0
- package/tools/csharp-indexer/bin/Release/net8.0/de/Microsoft.CodeAnalysis.Workspaces.resources.dll +0 -0
- package/tools/csharp-indexer/bin/Release/net8.0/de/Microsoft.CodeAnalysis.resources.dll +0 -0
- package/tools/csharp-indexer/bin/Release/net8.0/es/Microsoft.CodeAnalysis.CSharp.Workspaces.resources.dll +0 -0
- package/tools/csharp-indexer/bin/Release/net8.0/es/Microsoft.CodeAnalysis.CSharp.resources.dll +0 -0
- package/tools/csharp-indexer/bin/Release/net8.0/es/Microsoft.CodeAnalysis.Workspaces.resources.dll +0 -0
- package/tools/csharp-indexer/bin/Release/net8.0/es/Microsoft.CodeAnalysis.resources.dll +0 -0
- package/tools/csharp-indexer/bin/Release/net8.0/fr/Microsoft.CodeAnalysis.CSharp.Workspaces.resources.dll +0 -0
- package/tools/csharp-indexer/bin/Release/net8.0/fr/Microsoft.CodeAnalysis.CSharp.resources.dll +0 -0
- package/tools/csharp-indexer/bin/Release/net8.0/fr/Microsoft.CodeAnalysis.Workspaces.resources.dll +0 -0
- package/tools/csharp-indexer/bin/Release/net8.0/fr/Microsoft.CodeAnalysis.resources.dll +0 -0
- package/tools/csharp-indexer/bin/Release/net8.0/it/Microsoft.CodeAnalysis.CSharp.Workspaces.resources.dll +0 -0
- package/tools/csharp-indexer/bin/Release/net8.0/it/Microsoft.CodeAnalysis.CSharp.resources.dll +0 -0
- package/tools/csharp-indexer/bin/Release/net8.0/it/Microsoft.CodeAnalysis.Workspaces.resources.dll +0 -0
- package/tools/csharp-indexer/bin/Release/net8.0/it/Microsoft.CodeAnalysis.resources.dll +0 -0
- package/tools/csharp-indexer/bin/Release/net8.0/ja/Microsoft.CodeAnalysis.CSharp.Workspaces.resources.dll +0 -0
- package/tools/csharp-indexer/bin/Release/net8.0/ja/Microsoft.CodeAnalysis.CSharp.resources.dll +0 -0
- package/tools/csharp-indexer/bin/Release/net8.0/ja/Microsoft.CodeAnalysis.Workspaces.resources.dll +0 -0
- package/tools/csharp-indexer/bin/Release/net8.0/ja/Microsoft.CodeAnalysis.resources.dll +0 -0
- package/tools/csharp-indexer/bin/Release/net8.0/ko/Microsoft.CodeAnalysis.CSharp.Workspaces.resources.dll +0 -0
- package/tools/csharp-indexer/bin/Release/net8.0/ko/Microsoft.CodeAnalysis.CSharp.resources.dll +0 -0
- package/tools/csharp-indexer/bin/Release/net8.0/ko/Microsoft.CodeAnalysis.Workspaces.resources.dll +0 -0
- package/tools/csharp-indexer/bin/Release/net8.0/ko/Microsoft.CodeAnalysis.resources.dll +0 -0
- package/tools/csharp-indexer/bin/Release/net8.0/pl/Microsoft.CodeAnalysis.CSharp.Workspaces.resources.dll +0 -0
- package/tools/csharp-indexer/bin/Release/net8.0/pl/Microsoft.CodeAnalysis.CSharp.resources.dll +0 -0
- package/tools/csharp-indexer/bin/Release/net8.0/pl/Microsoft.CodeAnalysis.Workspaces.resources.dll +0 -0
- package/tools/csharp-indexer/bin/Release/net8.0/pl/Microsoft.CodeAnalysis.resources.dll +0 -0
- package/tools/csharp-indexer/bin/Release/net8.0/pt-BR/Microsoft.CodeAnalysis.CSharp.Workspaces.resources.dll +0 -0
- package/tools/csharp-indexer/bin/Release/net8.0/pt-BR/Microsoft.CodeAnalysis.CSharp.resources.dll +0 -0
- package/tools/csharp-indexer/bin/Release/net8.0/pt-BR/Microsoft.CodeAnalysis.Workspaces.resources.dll +0 -0
- package/tools/csharp-indexer/bin/Release/net8.0/pt-BR/Microsoft.CodeAnalysis.resources.dll +0 -0
- package/tools/csharp-indexer/bin/Release/net8.0/ru/Microsoft.CodeAnalysis.CSharp.Workspaces.resources.dll +0 -0
- package/tools/csharp-indexer/bin/Release/net8.0/ru/Microsoft.CodeAnalysis.CSharp.resources.dll +0 -0
- package/tools/csharp-indexer/bin/Release/net8.0/ru/Microsoft.CodeAnalysis.Workspaces.resources.dll +0 -0
- package/tools/csharp-indexer/bin/Release/net8.0/ru/Microsoft.CodeAnalysis.resources.dll +0 -0
- package/tools/csharp-indexer/bin/Release/net8.0/tr/Microsoft.CodeAnalysis.CSharp.Workspaces.resources.dll +0 -0
- package/tools/csharp-indexer/bin/Release/net8.0/tr/Microsoft.CodeAnalysis.CSharp.resources.dll +0 -0
- package/tools/csharp-indexer/bin/Release/net8.0/tr/Microsoft.CodeAnalysis.Workspaces.resources.dll +0 -0
- package/tools/csharp-indexer/bin/Release/net8.0/tr/Microsoft.CodeAnalysis.resources.dll +0 -0
- package/tools/csharp-indexer/bin/Release/net8.0/zh-Hans/Microsoft.CodeAnalysis.CSharp.Workspaces.resources.dll +0 -0
- package/tools/csharp-indexer/bin/Release/net8.0/zh-Hans/Microsoft.CodeAnalysis.CSharp.resources.dll +0 -0
- package/tools/csharp-indexer/bin/Release/net8.0/zh-Hans/Microsoft.CodeAnalysis.Workspaces.resources.dll +0 -0
- package/tools/csharp-indexer/bin/Release/net8.0/zh-Hans/Microsoft.CodeAnalysis.resources.dll +0 -0
- package/tools/csharp-indexer/bin/Release/net8.0/zh-Hant/Microsoft.CodeAnalysis.CSharp.Workspaces.resources.dll +0 -0
- package/tools/csharp-indexer/bin/Release/net8.0/zh-Hant/Microsoft.CodeAnalysis.CSharp.resources.dll +0 -0
- package/tools/csharp-indexer/bin/Release/net8.0/zh-Hant/Microsoft.CodeAnalysis.Workspaces.resources.dll +0 -0
- package/tools/csharp-indexer/bin/Release/net8.0/zh-Hant/Microsoft.CodeAnalysis.resources.dll +0 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
import{
|
|
1
|
+
import{a as B,b as O,c as q,d as A,e as z,f as F,i as C}from"./chunk-Z7LW7C4Z.mjs";import"./chunk-ODST7O2H.mjs";import{c as L}from"./chunk-AYCBSZ56.mjs";import{parentPort as h,threadId as te}from"worker_threads";import U from"fs";import $ from"path";import{promises as K}from"fs";import X from"ignore";import{createHash as re}from"crypto";var Z=Math.max(1,Number(process.env.PANDO_BATCH_INDEX_MAX_FILES||"64")),ee=Math.max(1,Number(process.env.PANDO_BATCH_INDEX_MAX_BYTES||`${1024*1024}`)),ae=Math.max(1,Number(process.env.PANDO_BATCH_INDEX_MAX_WAIT_MS||"15")),oe=Math.max(Z,Number(process.env.PANDO_BATCH_INDEX_MAX_PENDING_FILES||"256")),de=Math.max(ee,Number(process.env.PANDO_BATCH_INDEX_MAX_PENDING_BYTES||`${8*1024*1024}`));var ve=1*1024*1024,xe=Math.max(3e4,Number(process.env.PANDO_WORKER_INIT_TIMEOUT_MS||12e4)),Pe=q();function N(e,r){return Buffer.from(e).toString(r)}function M(e,r,l,t,d,p){let m=Buffer.from(e),n=re("sha1").update(m).digest("hex"),i=p??m.toString(d),c=i?i.split(/\r?\n/).length:0;return{relPath:r,size:l,mtime:t,objectId:n,lineCount:c,encoding:d}}if(!h)throw new Error("Indexer worker must be spawned as a worker thread");L();function u(e,r){try{if(r===void 0){console.error(`[${new Date().toISOString()}] [IndexerWorker] ${e}`);return}console.error(`[${new Date().toISOString()}] [IndexerWorker] ${e} ${JSON.stringify({pid:process.pid,threadId:te,...r&&typeof r=="object"&&!Array.isArray(r)?r:{details:r}})}`)}catch{}}u("module loaded",{cwd:process.cwd(),hasParentPort:!!h,envWorkerRoot:process.env.PANDO_WORKER_SCRIPT_DIR??null,envRuntimeRoot:process.env.PANDO_RUNTIME_ROOT??null});var G=new Map,D="",T="index",x=new Map,I=new Set;function H(e,r){return $.relative(e,r).replace(/\\/g,"/")}function se(e,r){let l=(r||[]).map(t=>typeof t=="string"?t.trim():"").filter(Boolean).map(t=>t.replace(/^[\\/]+/,"").replace(/[\\/]+$/,"")).map(t=>t.endsWith("/")?t:`${t}/`);return l.length?t=>{let d=H(e,t);if(!d||d.startsWith(".."))return!1;let p=d.endsWith("/")?d:`${d}/`;return l.some(m=>p.startsWith(m))}:null}async function ie(e){await new Promise(r=>{x.set(e,r)})}h.on("message",async e=>{if(e.cmd==="scan-ack"){let r=x.get(e.requestId);if(r){x.delete(e.requestId);try{r()}catch{}}return}if(e.cmd==="scan-cancel"){I.add(e.requestId);let r=x.get(e.requestId);if(r){x.delete(e.requestId);try{r()}catch{}}return}if(e.cmd==="init"){try{u("init received",{mode:e.mode??"index",projectRoot:typeof e.projectRoot=="string"?e.projectRoot:null}),typeof e.projectRoot=="string"&&(D=e.projectRoot),T=e.mode??"index",u("init completed",{mode:T,projectRoot:D}),h.postMessage({type:"ready"})}catch(r){u("init failed",{error:r?.message||String(r),stack:r?.stack??null}),h.postMessage({type:"error",message:`init failed: ${r?.message||r}`,stack:r?.stack})}return}if(e.cmd==="scan"){let r=e.requestId,l=typeof e.projectRoot=="string"?e.projectRoot:D;if(u("scan received",{requestId:r,projectRoot:l||null,batchSize:e.batchSize??null,maxFileBytes:e.maxFileBytes??null,excludeDirs:Array.isArray(e.excludeDirs)?e.excludeDirs.slice(0,20):[]}),!l){h.postMessage({type:"error",requestId:r,message:"worker not initialized"});return}let t=Math.max(1,Math.min(500,Number(e.batchSize||100))),d=Math.max(1,Number(e.maxFileBytes||1*1024*1024)),p=e.languageSupport,m=F(p),n=se(l,e.excludeDirs??[]),i=new Set(["node_modules",".git",".pando-data"]),c=o=>o.replace(/\\/g,"/"),f=await C(l,""),v=X().add(f),g=[{dir:l,relDir:"",rules:f,ig:v}],y=0,a=0,s=[],k=async()=>{s.length&&(h.postMessage({type:"scan:batch",requestId:r,files:s}),s=[],await ie(r))};try{for(;g.length&&!I.has(r);){let o=g.pop(),P=[];try{P=await K.readdir(o.dir,{withFileTypes:!0})}catch{a+=1;continue}for(let S of P){if(I.has(r))break;let w=$.join(o.dir,S.name);if(S.isSymbolicLink?.()){a+=1;continue}if(S.isDirectory()){if(i.has(S.name)){a+=1;continue}if(n?.(w)){a+=1;continue}let Y=o.relDir?`${o.relDir}/${S.name}`:S.name,R=c(Y);if(o.ig.ignores(R)){a+=1;continue}let E=o.rules.slice(),j=await C(w,R);j.length&&E.push(...j);let Q=X().add(E);g.push({dir:w,relDir:R,rules:E,ig:Q});continue}if(!S.isFile()){a+=1;continue}if(n?.(w)){a+=1;continue}let b=H(l,w);if(!b||b.startsWith("..")){a+=1;continue}if(o.ig.ignores(b)){a+=1;continue}let J=$.extname(S.name).toLowerCase();if(!m.has(J)){a+=1;continue}let _=A(b);if(!_){a+=1;continue}let W;try{W=await K.stat(w)}catch{a+=1;continue}if(W.size>d){a+=1;continue}s.push({relPath:b,absPath:w,mtimeMs:Math.floor(W.mtimeMs),size:W.size,lang:_}),y+=1,s.length>=t&&await k()}}I.has(r)||await k(),h.postMessage({type:"scan:done",requestId:r,discovered:y,skipped:a,cancelled:I.has(r)}),u("scan complete",{requestId:r,discovered:y,skipped:a,cancelled:I.has(r)})}catch(o){u("scan failed",{requestId:r,error:o?.message||String(o),stack:o?.stack??null}),h.postMessage({type:"error",requestId:r,message:o?.message||String(o),stack:o?.stack})}finally{I.delete(r),x.delete(r)}return}if(e.cmd==="process"){let r=e.role??T,l=typeof e.projectRoot=="string"?e.projectRoot:D;if(!l){h.postMessage({type:"error",requestId:e.requestId,message:"worker not initialized"});return}let{file:t}=e,d=t.encoding??"utf8",p=t.sharedBuffer,m={size:t.size,mtime:t.mtime};try{let n=t.lang??"ts",i,c,f=()=>{if(c&&typeof i=="string")return{content:i,sharedBuffer:c};if(p instanceof SharedArrayBuffer)return c=p,i=N(p,d),{content:i,sharedBuffer:c};if(p instanceof ArrayBuffer){let o=Buffer.from(p),P=new SharedArrayBuffer(o.byteLength);return new Uint8Array(P).set(o),c=P,i=o.toString(d),{content:i,sharedBuffer:c}}let s=U.readFileSync(t.absPath),k=new SharedArrayBuffer(s.byteLength);return new Uint8Array(k).set(s),c=k,i=s.toString(d),{content:i,sharedBuffer:c}},v=()=>{let s=B(n,t.relPath,m),k=f();h.postMessage({type:"result",requestId:e.requestId,role:"index",relPath:t.relPath,result:{payload:s.payload,meta:{size:s.fileSize,mtime:s.mtime},snapshotSummary:M(k.sharedBuffer,t.relPath,t.size,t.mtime,d,k.content)}})},g=`${l}:${n}`,y=G.get(g);if(!y)try{u("creating language indexer",{role:r,requestId:e.requestId,lang:n,projectRoot:l});let s=z(n);if(!O(s))throw new Error(`${n} is not a worker-indexed language`);y=s.createIndexer(l),G.set(g,y),u("language indexer ready",{role:r,requestId:e.requestId,lang:n,projectRoot:l})}catch(s){u("language indexer create failed",{role:r,requestId:e.requestId,lang:n,error:s?.message||String(s),stack:s?.stack??null}),v();return}({content:i,sharedBuffer:c}=f());let a;try{a=await y.process({absPath:t.absPath,relPath:t.relPath,content:i,meta:m,preDeleted:!!t.preDeleted,lang:n})}catch(s){u("process failed",{role:r,requestId:e.requestId,lang:n,relPath:t.relPath,error:s?.message||String(s),stack:s?.stack??null}),v();return}h.postMessage({type:"result",requestId:e.requestId,role:"index",relPath:t.relPath,result:{payload:a.payload,meta:{size:a.fileSize,mtime:a.mtime},snapshotSummary:M(c,t.relPath,t.size,t.mtime,d,i)}})}catch(n){u("process wrapper failed",{role:r,requestId:e.requestId,relPath:t.relPath,error:n?.message||String(n),stack:n?.stack??null});try{let i=t.lang??"ts",c=U.readFileSync(t.absPath),f=new SharedArrayBuffer(c.byteLength);new Uint8Array(f).set(c);let v=c.toString(d),g=B(i,t.relPath,m);h.postMessage({type:"result",requestId:e.requestId,role:"index",relPath:t.relPath,result:{payload:g.payload,meta:{size:g.fileSize,mtime:g.mtime},snapshotSummary:M(f,t.relPath,t.size,t.mtime,d,v)}})}catch(i){h.postMessage({type:"error",requestId:e.requestId,message:i?.message||n?.message||String(i??n),stack:i?.stack??n?.stack})}}return}e.cmd==="close"&&h.postMessage({type:"closed"})});process.on("uncaughtException",e=>{try{h.postMessage({type:"error",message:e?.message||String(e),stack:e?.stack})}catch{}});process.on("unhandledRejection",e=>{try{h.postMessage({type:"error",message:String(e)})}catch{}});
|
|
@@ -1,6 +1,10 @@
|
|
|
1
|
-
import{
|
|
2
|
-
`)
|
|
3
|
-
`,"utf8");try{await g.add({fs:o,dir:this.repoDir,filepath:".gitignore"})}catch{}f(`[GitHistoryStore] restored missing .gitignore at ${t}`)}catch(e){ot(`[GitHistoryStore] failed to recreate .gitignore: ${e?.message||e}`)}}normalizeLogicalPath(t){return String(t||"").replace(/\\/g,"/").replace(/^(?:\.\/)+/,"").replace(/^\/+/,"")}gitExists(){try{return v("git",["--version"],{cwd:this.repoDir,stdio:"ignore"}),!0}catch{return!1}}createSnapshotNative(t,e,n,r){let a=(typeof n=="string"?n.match(/^AST-Restore-Trace-Id:\s*(.+)$/m):null)?.[1]?.trim()||null,p=e;if(!p)try{p=v("git",["rev-parse","HEAD"],{cwd:this.repoDir,encoding:"utf8"}).trim()}catch{p=void 0}let m=new Map,u=Date.now();try{f("[GitHistoryStore] native snapshot start",{traceId:a,repoDir:this.repoDir,memberCount:t.length,parentOid:p||null})}catch{}for(let h=0;h<t.length;h++){let y=t[h];if(y.content==null)throw new Error(`Direct snapshot requires content for ${y.logicalPath}`);let S=Buffer.isBuffer(y.content)?y.content:Buffer.from(y.content),c=this.normalizeLogicalPath(y.logicalPath);if(!c)throw new Error("Direct snapshot requires non-empty logicalPath");let d=Date.now();try{f("[GitHistoryStore] native hash-object start",{traceId:a,repoDir:this.repoDir,index:h+1,total:t.length,logicalPath:c,bytes:S.length})}catch{}let D;try{D=v("git",["hash-object","-w","--stdin"],{cwd:this.repoDir,input:S}).toString("utf8").trim()}catch(T){try{ot("[GitHistoryStore] native hash-object failed",{traceId:a,repoDir:this.repoDir,index:h+1,total:t.length,logicalPath:c,bytes:S.length,durationMs:Date.now()-d,message:T?.message||String(T),status:T?.status??null,signal:T?.signal??null,stdout:T?.stdout?String(T.stdout).slice(0,500):null,stderr:T?.stderr?String(T.stderr).slice(0,500):null})}catch{}throw T}let E=Date.now()-d;try{(E>1e3||h<3||h===t.length-1)&&f("[GitHistoryStore] native hash-object done",{traceId:a,repoDir:this.repoDir,index:h+1,total:t.length,logicalPath:c,bytes:S.length,durationMs:E,oid:D})}catch{}m.set(c,D)}try{f("[GitHistoryStore] native hash-object phase complete",{traceId:a,repoDir:this.repoDir,memberCount:t.length,durationMs:Date.now()-u})}catch{}let b=I.join(this.repoDir,`.pando-index-${process.pid}-${Date.now()}`),l={...process.env,GIT_INDEX_FILE:b};try{let h=Date.now();try{f("[GitHistoryStore] native read-tree begin",{traceId:a,repoDir:this.repoDir,tmpIndex:b})}catch{}v("git",["read-tree","--empty"],{cwd:this.repoDir,env:l});try{f("[GitHistoryStore] native read-tree complete",{traceId:a,repoDir:this.repoDir,durationMs:Date.now()-h})}catch{}let y=Array.from(m.keys()).sort((k,C)=>k.localeCompare(C)),S=Date.now();for(let k of y){let C=m.get(k);v("git",["update-index","--add","--cacheinfo","100644",C,k],{cwd:this.repoDir,env:l})}try{f("[GitHistoryStore] native update-index complete",{traceId:a,repoDir:this.repoDir,entryCount:y.length,durationMs:Date.now()-S})}catch{}let c=Date.now();try{f("[GitHistoryStore] native write-tree begin",{traceId:a,repoDir:this.repoDir,entryCount:y.length})}catch{}let d=v("git",["write-tree"],{cwd:this.repoDir,env:l}).toString("utf8").trim();try{f("[GitHistoryStore] native write-tree complete",{traceId:a,repoDir:this.repoDir,treeOid:d,durationMs:Date.now()-c})}catch{}let D=["commit-tree",d];p&&D.push("-p",p),n&&D.push("-m",n);let E=Date.now();try{f("[GitHistoryStore] native commit-tree begin",{traceId:a,repoDir:this.repoDir,treeOid:d,parentOid:p||null})}catch{}let T=v("git",D,{cwd:this.repoDir}).toString("utf8").trim();try{f("[GitHistoryStore] native commit-tree complete",{traceId:a,repoDir:this.repoDir,commitOid:T,durationMs:Date.now()-E})}catch{}let $=Date.now();try{f("[GitHistoryStore] native update-ref begin",{traceId:a,repoDir:this.repoDir,commitOid:T})}catch{}v("git",["update-ref","refs/heads/master",T],{cwd:this.repoDir});try{f("[GitHistoryStore] native update-ref complete",{traceId:a,repoDir:this.repoDir,commitOid:T,durationMs:Date.now()-$})}catch{}return{snapshotId:T,parent:p}}finally{try{o.unlinkSync(b)}catch{}try{o.unlinkSync(`${b}.lock`)}catch{}}}async readObject(t){let{object:e}=await g.readObject({fs:o,dir:this.repoDir,oid:t});return Buffer.from(e)}async hasObject(t){try{return await g.readObject({fs:o,dir:this.repoDir,oid:t}),!0}catch{return!1}}async createSnapshot(t,e){x(e,"Snapshot cancelled"),await this.ensureInitialized(),f(`[${new Date().toISOString()}] [GitHistoryStore] Creating snapshot (streaming) with ${t.members.length} members`);let n=[...t.members].map(w=>({...w,logicalPath:this.normalizeLogicalPath(w.logicalPath)})).filter(w=>!!w.logicalPath).sort((w,P)=>w.logicalPath.localeCompare(P.logicalPath)),r=this.gitExists()&&!e;try{r?_.info("[GitHistoryStore] Using native git snapshot path",{members:n.length}):_.info("[GitHistoryStore] Using JS snapshot path",{members:n.length,git:!1,cancellable:!!e})}catch{}if(r)try{return this.createSnapshotNative(n,t.parent,t.message,t.when).snapshotId}catch(w){try{_.warn(`[GitHistoryStore] Native git path failed; falling back to JS path: ${w?.message||w}`)}catch{}}let s=Date.now(),a=w=>w.toString("hex"),p=w=>Dt("crypto").createHash("sha1").update(w).digest(),m=w=>{let P=Buffer.from(`blob ${w.length}\0`,"utf8"),A=Buffer.concat([P,w]);return a(p(A))},u=Math.max(1,Math.min(64,Number(process.env.SNAPSHOT_BLOB_CONCURRENCY||16))),b=String(process.env.SNAPSHOT_PRECOMPUTE_OIDS||"1")!=="0";try{_.info("[GitHistoryStore] JS snapshot settings",{SNAPSHOT_BLOB_CONCURRENCY:u,SNAPSHOT_PRECOMPUTE_OIDS:b})}catch{}let l=new Map,h=0,y=0,S=0,c=n.map(w=>({path:w.logicalPath,buf:Buffer.isBuffer(w.content)?w.content:Buffer.from(w.content)})),d=async()=>{for(;;){x(e,"Snapshot cancelled");let w;if(h<c.length)w=c[h++];else break;let P;if(b)try{let A=m(w.buf);await this.hasObject(A)&&(P=A,S++)}catch{}if(P||(P=await g.writeBlob({fs:o,dir:this.repoDir,blob:w.buf}),y++),x(e,"Snapshot cancelled"),!P)throw new Error("Failed to compute blob object id");l.set(w.path,P)}},D=Array.from({length:Math.min(u,c.length)},()=>d());await Promise.all(D),x(e,"Snapshot cancelled"),f(`[GitHistoryStore] Blobs ready wrote=${y} skipped=${S} in ${Date.now()-s}ms`);let E=new F(this.repoDir),T=Array.from(l.keys()).sort((w,P)=>w.localeCompare(P));for(let w of T)x(e,"Snapshot cancelled"),await E.addFile(w,l.get(w));x(e,"Snapshot cancelled");let $=Date.now(),k=await E.finish();f(`[GitHistoryStore] Wrote tree(s). root=${k} in ${Date.now()-$}ms`);let C=t.parent;if(!C)try{C=await g.resolveRef({fs:o,dir:this.repoDir,ref:"HEAD"})}catch{}x(e,"Snapshot cancelled");let N=t.when?Math.floor(t.when/1e3):Math.floor(Date.now()/1e3),G=new Date(N*1e3).getTimezoneOffset(),B=await g.commit({fs:o,dir:this.repoDir,message:t.message,parent:C?[C]:[],tree:k,author:{name:"ast-db",email:"ast-db@example.com",timestamp:N,timezoneOffset:G},committer:{name:"ast-db",email:"ast-db@example.com",timestamp:N,timezoneOffset:G}});return await g.writeRef({fs:o,dir:this.repoDir,ref:"refs/heads/master",value:B,force:!0}),f(`[GitHistoryStore] Snapshot commit oid ${B}`),B}async listSnapshotMembers(t){await this.ensureInitialized();let e=s=>Math.round((s||0)/(1024*1024)),n=()=>{let s=process.memoryUsage();return`rss=${e(s.rss)}MB heapUsed=${e(s.heapUsed)}MB heapTotal=${e(s.heapTotal)}MB`},r=[];return f(`[${new Date().toISOString()}] [GitHistoryStore] listSnapshotMembers(${t}) start (${n()})`),await g.walk({fs:o,dir:this.repoDir,trees:[g.TREE({ref:t})],map:async(s,[a])=>{if(!a)return;if(await a.type()==="blob"){let m=await a.oid();r.push({logicalPath:s,objectId:m})}}}),f(`[${new Date().toISOString()}] [GitHistoryStore] listSnapshotMembers(${t}) -> ${r.length} blobs`),r.filter(s=>s.logicalPath&&s.logicalPath!==".").map(s=>({logicalPath:s.logicalPath.replace(/^\.\//,""),objectId:s.objectId}))}async readCommit(t){let{commit:e}=await g.readCommit({fs:o,dir:this.repoDir,oid:t});return{message:e.message,committer:e.committer}}async readCommitParent(t){let{commit:e}=await g.readCommit({fs:o,dir:this.repoDir,oid:t});return Array.isArray(e.parent)&&e.parent.length>0?String(e.parent[0]):void 0}async createSnapshotFromDisk(t,e){x(e,"Snapshot cancelled"),await this.ensureInitialized(),f(`[${new Date().toISOString()}] [GitHistoryStore] Creating snapshot from disk (streaming) with ${t.relPaths.length} members`);let n=[...t.relPaths].map(y=>this.normalizeLogicalPath(y)).filter(Boolean).sort((y,S)=>y.localeCompare(S)),r=Date.now(),s=new F(this.repoDir),a=0;for(let y of n){x(e,"Snapshot cancelled");let S=I.join(this.baseDir,y);try{let c=o.readFileSync(S),d=await g.writeBlob({fs:o,dir:this.repoDir,blob:c});await s.addFile(y,d),a++}catch{}}f(`[GitHistoryStore] Wrote ${a} blobs (disk) in ${Date.now()-r}ms`),x(e,"Snapshot cancelled");let p=Date.now(),m=await s.finish();f(`[GitHistoryStore] Wrote tree(s) (disk). root=${m} in ${Date.now()-p}ms`);let u=t.parent;if(!u)try{u=await g.resolveRef({fs:o,dir:this.repoDir,ref:"HEAD"})}catch{}x(e,"Snapshot cancelled");let b=t.when?Math.floor(t.when/1e3):Math.floor(Date.now()/1e3),l=new Date(b*1e3).getTimezoneOffset(),h=await g.commit({fs:o,dir:this.repoDir,message:t.message,parent:u?[u]:[],tree:m,author:{name:"ast-db",email:"ast-db@example.com",timestamp:b,timezoneOffset:l},committer:{name:"ast-db",email:"ast-db@example.com",timestamp:b,timezoneOffset:l}});return await g.writeRef({fs:o,dir:this.repoDir,ref:"refs/heads/master",value:h,force:!0}),f(`[GitHistoryStore] Snapshot commit oid ${h}`),h}async createSnapshotFromDiskAndCapturedIfChanged(t){await this.ensureInitialized();let e=new Map;for(let c of t.capturedMembers||[]){let d=this.normalizeLogicalPath(c.logicalPath);!d||c.content==null||e.has(d)||e.set(d,Buffer.isBuffer(c.content)?c.content:Buffer.from(c.content))}f(`[${new Date().toISOString()}] [GitHistoryStore] Creating snapshot from disk+captured (diff) with ${t.relPaths.length} members, captured=${e.size}`);let n=[...t.relPaths].map(c=>this.normalizeLogicalPath(c)).filter(Boolean).sort((c,d)=>c.localeCompare(d)),r=Date.now(),s=new F(this.repoDir),a=0,p=0,m=0;for(let c of n)try{let d=e.get(c),D=d??o.readFileSync(I.join(this.baseDir,c)),E=await g.writeBlob({fs:o,dir:this.repoDir,blob:D});await s.addFile(c,E),a++,d?p++:m++}catch{}f(`[GitHistoryStore] Wrote ${a} blobs (captured=${p}, disk=${m}) in ${Date.now()-r}ms`);let u=Date.now(),b=await s.finish();f(`[GitHistoryStore] Wrote tree(s) (disk+captured). root=${b} in ${Date.now()-u}ms`);let l=t.parent;if(!l)try{l=await g.resolveRef({fs:o,dir:this.repoDir,ref:"HEAD"})}catch{}if(l)try{let{commit:c}=await g.readCommit({fs:o,dir:this.repoDir,oid:l});if(c?.tree===b){f("[GitHistoryStore] Snapshot identical to parent; skipping commit",{parentOid:l,tree:b});let d=await this.readCommitParent(l);return{snapshotId:l,identical:!0,parent:d}}}catch(c){f("[GitHistoryStore] Parent read failed; proceeding with commit",{error:c?.message||String(c)})}let h=t.when?Math.floor(t.when/1e3):Math.floor(Date.now()/1e3),y=new Date(h*1e3).getTimezoneOffset(),S=await g.commit({fs:o,dir:this.repoDir,message:t.message,parent:l?[l]:[],tree:b,author:{name:"ast-db",email:"ast-db@example.com",timestamp:h,timezoneOffset:y},committer:{name:"ast-db",email:"ast-db@example.com",timestamp:h,timezoneOffset:y}});return await g.writeRef({fs:o,dir:this.repoDir,ref:"refs/heads/master",value:S,force:!0}),f(`[GitHistoryStore] Snapshot commit oid ${S}`),{snapshotId:S,identical:!1,parent:l}}async createSnapshotFromDiskIfChanged(t){await this.ensureInitialized(),f(`[${new Date().toISOString()}] [GitHistoryStore] Creating snapshot from disk (diff) with ${t.relPaths.length} members`);let e=[...t.relPaths].map(h=>this.normalizeLogicalPath(h)).filter(Boolean).sort((h,y)=>h.localeCompare(y)),n=Date.now(),r=new F(this.repoDir),s=0;for(let h of e){let y=I.join(this.baseDir,h);try{let S=o.readFileSync(y),c=await g.writeBlob({fs:o,dir:this.repoDir,blob:S});await r.addFile(h,c),s++}catch{}}f(`[GitHistoryStore] Wrote ${s} blobs (disk) in ${Date.now()-n}ms`);let a=Date.now(),p=await r.finish();f(`[GitHistoryStore] Wrote tree(s) (disk). root=${p} in ${Date.now()-a}ms`);let m=t.parent;if(!m)try{m=await g.resolveRef({fs:o,dir:this.repoDir,ref:"HEAD"})}catch{}if(m)try{let{commit:h}=await g.readCommit({fs:o,dir:this.repoDir,oid:m});if(h?.tree===p){f("[GitHistoryStore] Snapshot identical to parent; skipping commit",{parentOid:m,tree:p});let y=await this.readCommitParent(m);return{snapshotId:m,identical:!0,parent:y}}}catch(h){f("[GitHistoryStore] Parent read failed; proceeding with commit",{error:h?.message||String(h)})}let u=t.when?Math.floor(t.when/1e3):Math.floor(Date.now()/1e3),b=new Date(u*1e3).getTimezoneOffset(),l=await g.commit({fs:o,dir:this.repoDir,message:t.message,parent:m?[m]:[],tree:p,author:{name:"ast-db",email:"ast-db@example.com",timestamp:u,timezoneOffset:b},committer:{name:"ast-db",email:"ast-db@example.com",timestamp:u,timezoneOffset:b}});return await g.writeRef({fs:o,dir:this.repoDir,ref:"refs/heads/master",value:l,force:!0}),f(`[GitHistoryStore] Snapshot commit oid ${l}`),{snapshotId:l,identical:!1,parent:m}}};function Z(i){let t={},e=i.split(/\r?\n/);for(let n of e){let r=n.match(/^([A-Za-z0-9-]+):\s*(.*)$/);r&&(t[r[1]]=r[2])}return t}import Et from"fs";import L from"path";import at from"ignore";import{Project as Wt}from"ts-morph";var Pt=new Set(["node_modules",".git",".pando-data",".clj-kondo"]);function lt(i,t){if(!t?.length)return null;let e=t.map(r=>r.replace(/^\/+/,"").replace(/\/+$/,"")).filter(Boolean).map(r=>`${r}/`);if(!e.length)return null;let n=r=>r.replace(/\\/g,"/");return r=>{let s=n(L.relative(i,r));if(!s||s.startsWith(".."))return!1;let a=s.endsWith("/")?s:`${s}/`;return e.some(p=>a.startsWith(p))}}function ht(i,t){return xt(i,t,null)}function xt(i,t,e){let n=t?.shouldExclude||null,r=[],s=L.resolve(t?.gitignoreRoot??i),a=K(s,""),p=at().add(a),m=[{dir:i,relDir:"",rules:a,ig:p}];for(;m.length;){let u=m.pop(),b=[];try{b=Et.readdirSync(u.dir,{withFileTypes:!0})}catch{continue}for(let l of b){let h=L.join(u.dir,l.name);if(!(typeof l.isSymbolicLink=="function"&&l.isSymbolicLink())){if(l.isDirectory()){if(Pt.has(l.name)||n?.(h))continue;let S=u.relDir?`${u.relDir}/${l.name}`:l.name,c=ct(S);if(u.ig.ignores(c))continue;let d=u.rules.slice(),D=K(h,c);D.length&&d.push(...D);let E=D.length?at().add(d):u.ig;m.push({dir:h,relDir:c,rules:d,ig:E})}else if(l.isFile()){if(n?.(h))continue;let S=ct(L.relative(i,h));if(u.ig.ignores(S))continue;if(e===null)r.push(h);else{let c=L.extname(l.name).toLowerCase();e.has(c)&&r.push(h)}}}}}return r}function ct(i){return i.replace(/\\/g,"/")}V();Tt();V();import q from"fs";import It from"path";function pt(i){i.pragma("journal_mode = WAL"),i.pragma("synchronous = NORMAL"),i.pragma("busy_timeout = 10000");try{i.pragma("temp_store = MEMORY")}catch{}i.exec(`
|
|
1
|
+
import{g as P,h as J}from"./chunk-Z7LW7C4Z.mjs";import{a as V,b as st,c as K,e as R}from"./chunk-ODST7O2H.mjs";import{a as Q,b as Et}from"./chunk-Z5RGEDVQ.mjs";import{a as Tt,c as ot}from"./chunk-AYCBSZ56.mjs";import{parentPort as $}from"worker_threads";import nt from"path";import*as o from"fs";import*as I from"path";import*as g from"isomorphic-git";function xt(){return new Date().toISOString()}function U(r,t,e){let n=`[${xt()}] [${r.toUpperCase()}] ${t}`;if(!e)return n;try{return n+" "+JSON.stringify(e)}catch{return n}}var B={debug:(r,t)=>{try{process.stderr.write(U("debug",r,t)+`
|
|
2
|
+
`)}catch{}},info:(r,t)=>{try{process.stderr.write(U("info",r,t)+`
|
|
3
|
+
`)}catch{}},warn:(r,t)=>{try{process.stderr.write(U("warn",r,t)+`
|
|
4
|
+
`)}catch{}},error:(r,t)=>{try{process.stderr.write(U("error",r,t)+`
|
|
5
|
+
`)}catch{}}};import{execFileSync as v}from"child_process";K();import*as Z from"path";function at(r){let t=V(r);return{root:t,historyGit:Z.join(t,"history.git"),workdir:Z.join(t,"workdir")}}function f(r,t){try{B.info(r,t)}catch{}}function ct(r,t){try{B.warn(r,t)}catch{}}var F=class{constructor(t){this.repoDir=t;this.stack=[{name:"",entries:[],dirNames:new Set,fileNames:new Set}]}currentDirs(){return this.stack.slice(1).map(t=>t.name)}lcpLen(t,e){let n=0;for(;n<t.length&&n<e.length&&t[n]===e[n];)n++;return n}async flushTop(){if(this.stack.length<=1)return;let t=this.stack.pop();t.entries.sort((i,s)=>i.path.localeCompare(s.path));let e=await g.writeTree({fs:o,dir:this.repoDir,tree:t.entries}),n=this.stack[this.stack.length-1];n.entries.push({mode:"040000",path:t.name,oid:e,type:"tree"}),n.dirNames.add(t.name)}async addFile(t,e){let n=t.replace(/^\.\//,"").replace(/\\/g,"/"),i=n.split("/").filter(Boolean);if(!i.length)return;let s=i.slice(0,-1),a=i[i.length-1],p=this.currentDirs(),m=this.lcpLen(p,s);for(let b=p.length;b>m;b--)await this.flushTop();for(let b=m;b<s.length;b++){let h=s[b];if(this.stack[this.stack.length-1].fileNames.has(h))throw new Error(`Path conflict: file exists where directory expected: ${s.slice(0,b+1).join("/")}`);this.stack.push({name:h,entries:[],dirNames:new Set,fileNames:new Set})}let u=this.stack[this.stack.length-1];if(u.dirNames.has(a))throw new Error(`Path conflict: directory exists where file expected: ${n}`);u.entries.push({mode:"100644",path:a,oid:e,type:"blob"}),u.fileNames.add(a)}async finish(){for(;this.stack.length>1;)await this.flushTop();let t=this.stack[0];return t.entries.sort((e,n)=>e.path.localeCompare(n.path)),g.writeTree({fs:o,dir:this.repoDir,tree:t.entries})}},L=class{constructor(t){this.baseDir=t.baseDir;let e=at(t.shadowDir??t.baseDir);this.repoDir=I.join(e.root,"history")}async ensureInitialized(){o.mkdirSync(this.repoDir,{recursive:!0});let t=I.join(this.repoDir,".git");if(o.existsSync(t)){await this.ensureDefaultGitignore();return}let e=I.join(this.repoDir,".init.lock"),n=s=>new Promise(a=>setTimeout(a,s)),i=null;try{try{i=o.openSync(e,"wx"),o.writeFileSync(i,String(Date.now()))}catch{let s=Date.now(),a=3e4;for(;!o.existsSync(t);){try{let p=o.statSync(e);if(Date.now()-p.mtimeMs>a){try{o.unlinkSync(e)}catch{}break}}catch{}if(Date.now()-s>a)break;await n(200)}if(o.existsSync(t))return;i=o.openSync(e,"wx"),o.writeFileSync(i,String(Date.now()))}if(o.existsSync(t))return;f(`[${new Date().toISOString()}] [GitHistoryStore] Initializing history repo at ${this.repoDir}`),await g.init({fs:o,dir:this.repoDir}),f(`[${new Date().toISOString()}] [GitHistoryStore] git.init OK`),await g.setConfig({fs:o,dir:this.repoDir,path:"user.name",value:"ast-db"}),await g.setConfig({fs:o,dir:this.repoDir,path:"user.email",value:"ast-db@example.com"}),f(`[${new Date().toISOString()}] [GitHistoryStore] git config set (user.name/user.email)`),o.writeFileSync(I.join(this.repoDir,".gitignore"),`# ast history repo
|
|
6
|
+
`),f(`[${new Date().toISOString()}] [GitHistoryStore] wrote .gitignore`)}finally{try{i!=null&&o.closeSync(i)}catch{}try{o.existsSync(e)&&o.unlinkSync(e)}catch{}}await this.ensureDefaultGitignore()}async ensureDefaultGitignore(){let t=I.join(this.repoDir,".gitignore");if(!o.existsSync(t))try{o.mkdirSync(I.dirname(t),{recursive:!0}),o.writeFileSync(t,`# ast history repo
|
|
7
|
+
`,"utf8");try{await g.add({fs:o,dir:this.repoDir,filepath:".gitignore"})}catch{}f(`[GitHistoryStore] restored missing .gitignore at ${t}`)}catch(e){ct(`[GitHistoryStore] failed to recreate .gitignore: ${e?.message||e}`)}}normalizeLogicalPath(t){return String(t||"").replace(/\\/g,"/").replace(/^(?:\.\/)+/,"").replace(/^\/+/,"")}gitExists(){try{return v("git",["--version"],{cwd:this.repoDir,stdio:"ignore"}),!0}catch{return!1}}createSnapshotNative(t,e,n,i){let a=(typeof n=="string"?n.match(/^AST-Restore-Trace-Id:\s*(.+)$/m):null)?.[1]?.trim()||null,p=e;if(!p)try{p=v("git",["rev-parse","HEAD"],{cwd:this.repoDir,encoding:"utf8"}).trim()}catch{p=void 0}let m=new Map,u=Date.now();try{f("[GitHistoryStore] native snapshot start",{traceId:a,repoDir:this.repoDir,memberCount:t.length,parentOid:p||null})}catch{}for(let l=0;l<t.length;l++){let y=t[l];if(y.content==null)throw new Error(`Direct snapshot requires content for ${y.logicalPath}`);let S=Buffer.isBuffer(y.content)?y.content:Buffer.from(y.content),c=this.normalizeLogicalPath(y.logicalPath);if(!c)throw new Error("Direct snapshot requires non-empty logicalPath");let d=Date.now();try{f("[GitHistoryStore] native hash-object start",{traceId:a,repoDir:this.repoDir,index:l+1,total:t.length,logicalPath:c,bytes:S.length})}catch{}let D;try{D=v("git",["hash-object","-w","--stdin"],{cwd:this.repoDir,input:S}).toString("utf8").trim()}catch(T){try{ct("[GitHistoryStore] native hash-object failed",{traceId:a,repoDir:this.repoDir,index:l+1,total:t.length,logicalPath:c,bytes:S.length,durationMs:Date.now()-d,message:T?.message||String(T),status:T?.status??null,signal:T?.signal??null,stdout:T?.stdout?String(T.stdout).slice(0,500):null,stderr:T?.stderr?String(T.stderr).slice(0,500):null})}catch{}throw T}let E=Date.now()-d;try{(E>1e3||l<3||l===t.length-1)&&f("[GitHistoryStore] native hash-object done",{traceId:a,repoDir:this.repoDir,index:l+1,total:t.length,logicalPath:c,bytes:S.length,durationMs:E,oid:D})}catch{}m.set(c,D)}try{f("[GitHistoryStore] native hash-object phase complete",{traceId:a,repoDir:this.repoDir,memberCount:t.length,durationMs:Date.now()-u})}catch{}let b=I.join(this.repoDir,`.pando-index-${process.pid}-${Date.now()}`),h={...process.env,GIT_INDEX_FILE:b};try{let l=Date.now();try{f("[GitHistoryStore] native read-tree begin",{traceId:a,repoDir:this.repoDir,tmpIndex:b})}catch{}v("git",["read-tree","--empty"],{cwd:this.repoDir,env:h});try{f("[GitHistoryStore] native read-tree complete",{traceId:a,repoDir:this.repoDir,durationMs:Date.now()-l})}catch{}let y=Array.from(m.keys()).sort((k,O)=>k.localeCompare(O)),S=Date.now();for(let k of y){let O=m.get(k);v("git",["update-index","--add","--cacheinfo","100644",O,k],{cwd:this.repoDir,env:h})}try{f("[GitHistoryStore] native update-index complete",{traceId:a,repoDir:this.repoDir,entryCount:y.length,durationMs:Date.now()-S})}catch{}let c=Date.now();try{f("[GitHistoryStore] native write-tree begin",{traceId:a,repoDir:this.repoDir,entryCount:y.length})}catch{}let d=v("git",["write-tree"],{cwd:this.repoDir,env:h}).toString("utf8").trim();try{f("[GitHistoryStore] native write-tree complete",{traceId:a,repoDir:this.repoDir,treeOid:d,durationMs:Date.now()-c})}catch{}let D=["commit-tree",d];p&&D.push("-p",p),n&&D.push("-m",n);let E=Date.now();try{f("[GitHistoryStore] native commit-tree begin",{traceId:a,repoDir:this.repoDir,treeOid:d,parentOid:p||null})}catch{}let T=v("git",D,{cwd:this.repoDir}).toString("utf8").trim();try{f("[GitHistoryStore] native commit-tree complete",{traceId:a,repoDir:this.repoDir,commitOid:T,durationMs:Date.now()-E})}catch{}let j=Date.now();try{f("[GitHistoryStore] native update-ref begin",{traceId:a,repoDir:this.repoDir,commitOid:T})}catch{}v("git",["update-ref","refs/heads/master",T],{cwd:this.repoDir});try{f("[GitHistoryStore] native update-ref complete",{traceId:a,repoDir:this.repoDir,commitOid:T,durationMs:Date.now()-j})}catch{}return{snapshotId:T,parent:p}}finally{try{o.unlinkSync(b)}catch{}try{o.unlinkSync(`${b}.lock`)}catch{}}}async readObject(t){let{object:e}=await g.readObject({fs:o,dir:this.repoDir,oid:t});return Buffer.from(e)}async hasObject(t){try{return await g.readObject({fs:o,dir:this.repoDir,oid:t}),!0}catch{return!1}}async createSnapshot(t,e){P(e,"Snapshot cancelled"),await this.ensureInitialized(),f(`[${new Date().toISOString()}] [GitHistoryStore] Creating snapshot (streaming) with ${t.members.length} members`);let n=[...t.members].map(w=>({...w,logicalPath:this.normalizeLogicalPath(w.logicalPath)})).filter(w=>!!w.logicalPath).sort((w,x)=>w.logicalPath.localeCompare(x.logicalPath)),i=this.gitExists()&&!e;try{i?B.info("[GitHistoryStore] Using native git snapshot path",{members:n.length}):B.info("[GitHistoryStore] Using JS snapshot path",{members:n.length,git:!1,cancellable:!!e})}catch{}if(i)try{return this.createSnapshotNative(n,t.parent,t.message,t.when).snapshotId}catch(w){try{B.warn(`[GitHistoryStore] Native git path failed; falling back to JS path: ${w?.message||w}`)}catch{}}let s=Date.now(),a=w=>w.toString("hex"),p=w=>Tt("crypto").createHash("sha1").update(w).digest(),m=w=>{let x=Buffer.from(`blob ${w.length}\0`,"utf8"),A=Buffer.concat([x,w]);return a(p(A))},u=Math.max(1,Math.min(64,Number(process.env.SNAPSHOT_BLOB_CONCURRENCY||16))),b=String(process.env.SNAPSHOT_PRECOMPUTE_OIDS||"1")!=="0";try{B.info("[GitHistoryStore] JS snapshot settings",{SNAPSHOT_BLOB_CONCURRENCY:u,SNAPSHOT_PRECOMPUTE_OIDS:b})}catch{}let h=new Map,l=0,y=0,S=0,c=n.map(w=>({path:w.logicalPath,buf:Buffer.isBuffer(w.content)?w.content:Buffer.from(w.content)})),d=async()=>{for(;;){P(e,"Snapshot cancelled");let w;if(l<c.length)w=c[l++];else break;let x;if(b)try{let A=m(w.buf);await this.hasObject(A)&&(x=A,S++)}catch{}if(x||(x=await g.writeBlob({fs:o,dir:this.repoDir,blob:w.buf}),y++),P(e,"Snapshot cancelled"),!x)throw new Error("Failed to compute blob object id");h.set(w.path,x)}},D=Array.from({length:Math.min(u,c.length)},()=>d());await Promise.all(D),P(e,"Snapshot cancelled"),f(`[GitHistoryStore] Blobs ready wrote=${y} skipped=${S} in ${Date.now()-s}ms`);let E=new F(this.repoDir),T=Array.from(h.keys()).sort((w,x)=>w.localeCompare(x));for(let w of T)P(e,"Snapshot cancelled"),await E.addFile(w,h.get(w));P(e,"Snapshot cancelled");let j=Date.now(),k=await E.finish();f(`[GitHistoryStore] Wrote tree(s). root=${k} in ${Date.now()-j}ms`);let O=t.parent;if(!O)try{O=await g.resolveRef({fs:o,dir:this.repoDir,ref:"HEAD"})}catch{}P(e,"Snapshot cancelled");let N=t.when?Math.floor(t.when/1e3):Math.floor(Date.now()/1e3),G=new Date(N*1e3).getTimezoneOffset(),_=await g.commit({fs:o,dir:this.repoDir,message:t.message,parent:O?[O]:[],tree:k,author:{name:"ast-db",email:"ast-db@example.com",timestamp:N,timezoneOffset:G},committer:{name:"ast-db",email:"ast-db@example.com",timestamp:N,timezoneOffset:G}});return await g.writeRef({fs:o,dir:this.repoDir,ref:"refs/heads/master",value:_,force:!0}),f(`[GitHistoryStore] Snapshot commit oid ${_}`),_}async listSnapshotMembers(t){await this.ensureInitialized();let e=s=>Math.round((s||0)/(1024*1024)),n=()=>{let s=process.memoryUsage();return`rss=${e(s.rss)}MB heapUsed=${e(s.heapUsed)}MB heapTotal=${e(s.heapTotal)}MB`},i=[];return f(`[${new Date().toISOString()}] [GitHistoryStore] listSnapshotMembers(${t}) start (${n()})`),await g.walk({fs:o,dir:this.repoDir,trees:[g.TREE({ref:t})],map:async(s,[a])=>{if(!a)return;if(await a.type()==="blob"){let m=await a.oid();i.push({logicalPath:s,objectId:m})}}}),f(`[${new Date().toISOString()}] [GitHistoryStore] listSnapshotMembers(${t}) -> ${i.length} blobs`),i.filter(s=>s.logicalPath&&s.logicalPath!==".").map(s=>({logicalPath:s.logicalPath.replace(/^\.\//,""),objectId:s.objectId}))}async readCommit(t){let{commit:e}=await g.readCommit({fs:o,dir:this.repoDir,oid:t});return{message:e.message,committer:e.committer}}async readCommitParent(t){let{commit:e}=await g.readCommit({fs:o,dir:this.repoDir,oid:t});return Array.isArray(e.parent)&&e.parent.length>0?String(e.parent[0]):void 0}async createSnapshotFromDisk(t,e){P(e,"Snapshot cancelled"),await this.ensureInitialized(),f(`[${new Date().toISOString()}] [GitHistoryStore] Creating snapshot from disk (streaming) with ${t.relPaths.length} members`);let n=[...t.relPaths].map(y=>this.normalizeLogicalPath(y)).filter(Boolean).sort((y,S)=>y.localeCompare(S)),i=Date.now(),s=new F(this.repoDir),a=0;for(let y of n){P(e,"Snapshot cancelled");let S=I.join(this.baseDir,y);try{let c=o.readFileSync(S),d=await g.writeBlob({fs:o,dir:this.repoDir,blob:c});await s.addFile(y,d),a++}catch{}}f(`[GitHistoryStore] Wrote ${a} blobs (disk) in ${Date.now()-i}ms`),P(e,"Snapshot cancelled");let p=Date.now(),m=await s.finish();f(`[GitHistoryStore] Wrote tree(s) (disk). root=${m} in ${Date.now()-p}ms`);let u=t.parent;if(!u)try{u=await g.resolveRef({fs:o,dir:this.repoDir,ref:"HEAD"})}catch{}P(e,"Snapshot cancelled");let b=t.when?Math.floor(t.when/1e3):Math.floor(Date.now()/1e3),h=new Date(b*1e3).getTimezoneOffset(),l=await g.commit({fs:o,dir:this.repoDir,message:t.message,parent:u?[u]:[],tree:m,author:{name:"ast-db",email:"ast-db@example.com",timestamp:b,timezoneOffset:h},committer:{name:"ast-db",email:"ast-db@example.com",timestamp:b,timezoneOffset:h}});return await g.writeRef({fs:o,dir:this.repoDir,ref:"refs/heads/master",value:l,force:!0}),f(`[GitHistoryStore] Snapshot commit oid ${l}`),l}async createSnapshotFromDiskAndCapturedIfChanged(t){await this.ensureInitialized();let e=new Map;for(let c of t.capturedMembers||[]){let d=this.normalizeLogicalPath(c.logicalPath);!d||c.content==null||e.has(d)||e.set(d,Buffer.isBuffer(c.content)?c.content:Buffer.from(c.content))}f(`[${new Date().toISOString()}] [GitHistoryStore] Creating snapshot from disk+captured (diff) with ${t.relPaths.length} members, captured=${e.size}`);let n=[...t.relPaths].map(c=>this.normalizeLogicalPath(c)).filter(Boolean).sort((c,d)=>c.localeCompare(d)),i=Date.now(),s=new F(this.repoDir),a=0,p=0,m=0;for(let c of n)try{let d=e.get(c),D=d??o.readFileSync(I.join(this.baseDir,c)),E=await g.writeBlob({fs:o,dir:this.repoDir,blob:D});await s.addFile(c,E),a++,d?p++:m++}catch{}f(`[GitHistoryStore] Wrote ${a} blobs (captured=${p}, disk=${m}) in ${Date.now()-i}ms`);let u=Date.now(),b=await s.finish();f(`[GitHistoryStore] Wrote tree(s) (disk+captured). root=${b} in ${Date.now()-u}ms`);let h=t.parent;if(!h)try{h=await g.resolveRef({fs:o,dir:this.repoDir,ref:"HEAD"})}catch{}if(h)try{let{commit:c}=await g.readCommit({fs:o,dir:this.repoDir,oid:h});if(c?.tree===b){f("[GitHistoryStore] Snapshot identical to parent; skipping commit",{parentOid:h,tree:b});let d=await this.readCommitParent(h);return{snapshotId:h,identical:!0,parent:d}}}catch(c){f("[GitHistoryStore] Parent read failed; proceeding with commit",{error:c?.message||String(c)})}let l=t.when?Math.floor(t.when/1e3):Math.floor(Date.now()/1e3),y=new Date(l*1e3).getTimezoneOffset(),S=await g.commit({fs:o,dir:this.repoDir,message:t.message,parent:h?[h]:[],tree:b,author:{name:"ast-db",email:"ast-db@example.com",timestamp:l,timezoneOffset:y},committer:{name:"ast-db",email:"ast-db@example.com",timestamp:l,timezoneOffset:y}});return await g.writeRef({fs:o,dir:this.repoDir,ref:"refs/heads/master",value:S,force:!0}),f(`[GitHistoryStore] Snapshot commit oid ${S}`),{snapshotId:S,identical:!1,parent:h}}async createSnapshotFromDiskIfChanged(t){await this.ensureInitialized(),f(`[${new Date().toISOString()}] [GitHistoryStore] Creating snapshot from disk (diff) with ${t.relPaths.length} members`);let e=[...t.relPaths].map(l=>this.normalizeLogicalPath(l)).filter(Boolean).sort((l,y)=>l.localeCompare(y)),n=Date.now(),i=new F(this.repoDir),s=0;for(let l of e){let y=I.join(this.baseDir,l);try{let S=o.readFileSync(y),c=await g.writeBlob({fs:o,dir:this.repoDir,blob:S});await i.addFile(l,c),s++}catch{}}f(`[GitHistoryStore] Wrote ${s} blobs (disk) in ${Date.now()-n}ms`);let a=Date.now(),p=await i.finish();f(`[GitHistoryStore] Wrote tree(s) (disk). root=${p} in ${Date.now()-a}ms`);let m=t.parent;if(!m)try{m=await g.resolveRef({fs:o,dir:this.repoDir,ref:"HEAD"})}catch{}if(m)try{let{commit:l}=await g.readCommit({fs:o,dir:this.repoDir,oid:m});if(l?.tree===p){f("[GitHistoryStore] Snapshot identical to parent; skipping commit",{parentOid:m,tree:p});let y=await this.readCommitParent(m);return{snapshotId:m,identical:!0,parent:y}}}catch(l){f("[GitHistoryStore] Parent read failed; proceeding with commit",{error:l?.message||String(l)})}let u=t.when?Math.floor(t.when/1e3):Math.floor(Date.now()/1e3),b=new Date(u*1e3).getTimezoneOffset(),h=await g.commit({fs:o,dir:this.repoDir,message:t.message,parent:m?[m]:[],tree:p,author:{name:"ast-db",email:"ast-db@example.com",timestamp:u,timezoneOffset:b},committer:{name:"ast-db",email:"ast-db@example.com",timestamp:u,timezoneOffset:b}});return await g.writeRef({fs:o,dir:this.repoDir,ref:"refs/heads/master",value:h,force:!0}),f(`[GitHistoryStore] Snapshot commit oid ${h}`),{snapshotId:h,identical:!1,parent:m}}};function q(r){let t={},e=r.split(/\r?\n/);for(let n of e){let i=n.match(/^([A-Za-z0-9-]+):\s*(.*)$/);i&&(t[i[1]]=i[2])}return t}import Pt from"fs";import H from"path";import lt from"ignore";import{Project as Jt}from"ts-morph";var It=new Set(["node_modules",".git",".pando-data"]);function Mt(r){let t=tt(r).split("/").filter(Boolean);for(let e=0;e<t.length;e+=1)if(It.has(t[e])||t[e]===".clj-kondo"&&t[e+1]===".cache")return!0;return!1}function ht(r,t){if(!t?.length)return null;let e=t.map(i=>i.replace(/^\/+/,"").replace(/\/+$/,"")).filter(Boolean).map(i=>`${i}/`);if(!e.length)return null;let n=i=>i.replace(/\\/g,"/");return i=>{let s=n(H.relative(r,i));if(!s||s.startsWith(".."))return!1;let a=s.endsWith("/")?s:`${s}/`;return e.some(p=>a.startsWith(p))}}function pt(r,t){return Ot(r,t,null)}function Ot(r,t,e){let n=t?.shouldExclude||null,i=[],s=H.resolve(t?.gitignoreRoot??r),a=J(s,""),p=lt().add(a),m=[{dir:r,relDir:"",rules:a,ig:p}];for(;m.length;){let u=m.pop(),b=[];try{b=Pt.readdirSync(u.dir,{withFileTypes:!0})}catch{continue}for(let h of b){let l=H.join(u.dir,h.name);if(!(typeof h.isSymbolicLink=="function"&&h.isSymbolicLink())&&!Mt(l)){if(h.isDirectory()){if(n?.(l))continue;let S=u.relDir?`${u.relDir}/${h.name}`:h.name,c=tt(S);if(u.ig.ignores(c))continue;let d=u.rules.slice(),D=J(l,c);D.length&&d.push(...D);let E=D.length?lt().add(d):u.ig;m.push({dir:l,relDir:c,rules:d,ig:E})}else if(h.isFile()){if(n?.(l))continue;let S=tt(H.relative(r,l));if(u.ig.ignores(S))continue;if(e===null)i.push(l);else{let c=H.extname(h.name).toLowerCase();e.has(c)&&i.push(l)}}}}}return i}function tt(r){return r.replace(/\\/g,"/")}K();Et();K();import et from"fs";import Ct from"path";function dt(r){r.pragma("journal_mode = WAL"),r.pragma("synchronous = NORMAL"),r.pragma("busy_timeout = 10000");try{r.pragma("temp_store = MEMORY")}catch{}r.exec(`
|
|
4
8
|
CREATE TABLE IF NOT EXISTS objects (
|
|
5
9
|
object_id TEXT PRIMARY KEY,
|
|
6
10
|
kind TEXT DEFAULT 'blob',
|
|
@@ -38,4 +42,4 @@ import{a as _,h as x,i as K}from"./chunk-BD3AO7O3.mjs";import{a as Y,b as it,c a
|
|
|
38
42
|
|
|
39
43
|
CREATE INDEX IF NOT EXISTS idx_snapshots_timestamp ON snapshots(timestamp);
|
|
40
44
|
CREATE INDEX IF NOT EXISTS idx_snapshot_meta_kv ON snapshot_meta(key, value);
|
|
41
|
-
`)}function
|
|
45
|
+
`)}function rt(r,t){let e=st(r),n=Ct.dirname(e);et.existsSync(n)||et.mkdirSync(n,{recursive:!0});let i=!!t?.readonly;if(i&&!et.existsSync(e)){let a=new Q(e,{});try{dt(a)}finally{try{a.close()}catch{}}}let s=new Q(e,i?{readonly:!0}:{});if(!i)dt(s);else try{s.pragma("busy_timeout = 10000")}catch{}return s}var C="",it=[],St=null;ot();function gt(r,t){if(Array.isArray(t)){it=t.slice(),St=ht(r,it);try{R("SnapshotWorker","exclude state updated",{excludeDirs:it})}catch{}}}function kt(r){let t=pt(r,{shouldExclude:St??void 0,gitignoreRoot:r});try{R("SnapshotWorker","gatherSnapshotFiles",{count:t.length,sample:t.slice(0,20).map(e=>nt.relative(r,e).replace(/\\/g,"/"))})}catch{}return t}function mt(r){try{return r.prepare("SELECT snapshot_id FROM snapshots ORDER BY timestamp DESC, rowid DESC LIMIT 1").get()?.snapshot_id}catch{return}}function ft(r,t,e,n,i){let s=i||null;r.prepare("INSERT OR REPLACE INTO snapshots (snapshot_id, parents, timestamp, message) VALUES (?, ?, ?, ?)").run(t,s,Math.floor(e/1e3),n)}async function ut(r,t,e){try{return await r.readCommitParent(t)||e}catch{return e}}function X(r,t){let e=new Map;try{let n=r.prepare("SELECT logical_path, object_id FROM snapshot_members WHERE snapshot_id = ?").all(t);for(let i of n)e.set(i.logical_path,i.object_id)}catch{}return e}function yt(r,t,e){r.transaction(i=>{let s=r.prepare("INSERT OR REPLACE INTO snapshot_members (snapshot_id, logical_path, object_id, lang, encoding) VALUES (?, ?, ?, ?, ?)");for(let a of i)s.run(t,a.logical_path,a.object_id,a.lang??null,a.encoding??null)})(e)}$.on("message",async r=>{if(r.cmd==="init"){C=r.projectRoot,gt(C,r.excludeDirs),$.postMessage({type:"ready"});return}if(r.excludeDirs&>(C,r.excludeDirs),r.cmd==="snapshot"){let t=rt(C);try{let e=Date.now(),n=r.payload?.when||Date.now(),i=r.payload?.message||"ast: snapshot",s=r.payload?.parent||mt(t),a=Date.now(),p=r.payload?.files&&r.payload.files.length?r.payload.files:kt(C);try{R("SnapshotWorker","snapshot start",{when:n,message:i,parent:s,fileCount:p.length,filesPreview:p.slice(0,50).map(D=>nt.relative(C,D).replace(/\\/g,"/"))})}catch{}let m=Date.now()-a,u=p.map(D=>nt.relative(C,D).replace(/\\/g,"/")),b=(r.payload?.captured||[]).map(D=>({logicalPath:D.logicalPath,objectId:"unknown",content:Buffer.from(D.contentB64,"base64")})),h=new L({baseDir:C});await h.ensureInitialized();let l=Date.now(),y=b.length>0?await h.createSnapshotFromDiskAndCapturedIfChanged({message:i,when:n,relPaths:u,capturedMembers:b,parent:s}):await h.createSnapshotFromDiskIfChanged({message:i,when:n,relPaths:u,parent:s}),S=y.snapshotId,c=await ut(h,S,y.parent||s),d=Date.now()-l;if(y.identical){let D=Date.now()-e;try{R("SnapshotWorker","snapshot skipped (identical)",{snapshotId:S,parent:c,files:u.length,timingsMs:{list:m,snapshot:d,total:D}})}catch{}$.postMessage({type:"result",snapshotId:S,parent:c,files:u.length,diff:{added:0,changed:0,deleted:0}})}else{let D=Date.now();ft(t,S,n,i,c);try{let M=q(i||""),W=t.prepare("INSERT OR REPLACE INTO snapshot_meta (snapshot_id, key, value) VALUES (?, ?, ?)");t.transaction(()=>{for(let[wt,Dt]of Object.entries(M))W.run(S,wt,Dt)})()}catch{}let E=Date.now()-D,T=Date.now(),j=await h.listSnapshotMembers(S),k=Date.now()-T,O=j.map(M=>({logical_path:M.logicalPath,object_id:M.objectId})),N=Date.now();yt(t,S,O);let G=Date.now()-N,_=c?X(t,c):new Map,w=X(t,S),x=[],A=[],z=[];for(let[M,W]of w){let Y=_.get(M);Y?Y!==W&&A.push(M):x.push(M)}for(let[M]of _)w.has(M)||z.push(M);let bt=Date.now()-e;try{R("SnapshotWorker","snapshot complete",{snapshotId:S,parent:c,files:u.length,timingsMs:{list:m,snapshot:d,metadata:E,listMembers:k,membersWrite:G,total:bt},diff:{added:x.length,changed:A.length,deleted:z.length}})}catch{}$.postMessage({type:"result",snapshotId:S,parent:c,files:u.length,diff:{added:x.length,changed:A.length,deleted:z.length}})}}catch(e){$.postMessage({type:"error",message:e?.message||String(e)})}finally{t.close()}return}if(r.cmd==="snapshot-captured"){let t=rt(C);try{let e=r.payload?.when||Date.now(),n=r.payload?.message||"ast: snapshot",i=r.payload?.parent||mt(t);try{R("SnapshotWorker","snapshot-captured start",{when:e,message:n,parent:i,members:r.payload.members.length})}catch{}let s=new L({baseDir:C});await s.ensureInitialized();let a=(r.payload.members||[]).map(d=>({logicalPath:d.logicalPath,objectId:"unknown",content:Buffer.from(d.contentB64,"base64")})),p=await s.createSnapshot({message:n,when:e,members:a}),m=await ut(s,p,i);ft(t,p,e,n,m);try{let d=q(n||""),D=t.prepare("INSERT OR REPLACE INTO snapshot_meta (snapshot_id, key, value) VALUES (?, ?, ?)");t.transaction(()=>{for(let[T,j]of Object.entries(d))D.run(p,T,j)})()}catch{}let u=await s.listSnapshotMembers(p),b=u.map(d=>({logical_path:d.logicalPath,object_id:d.objectId}));yt(t,p,b);let h=m?X(t,m):new Map,l=X(t,p),y=[],S=[],c=[];for(let[d,D]of l){let E=h.get(d);E?E!==D&&S.push(d):y.push(d)}for(let[d]of h)l.has(d)||c.push(d);try{R("SnapshotWorker","snapshot-captured complete",{snapshotId:p,parent:m,members:u.length,diff:{added:y.length,changed:S.length,deleted:c.length}})}catch{}$.postMessage({type:"result",snapshotId:p,parent:m,files:u.length,diff:{added:y.length,changed:S.length,deleted:c.length}})}catch(e){$.postMessage({type:"error",message:e?.message||String(e)})}finally{t.close()}}r.cmd==="close"&&$.postMessage({type:"closed"})});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pando-ai",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.9",
|
|
4
4
|
"description": "Standalone pando MCP CLI",
|
|
5
5
|
"bin": {
|
|
6
6
|
"pando-ai": "bin/pando-ai.js"
|
|
@@ -8,15 +8,16 @@
|
|
|
8
8
|
"files": [
|
|
9
9
|
"bin/",
|
|
10
10
|
"dist/",
|
|
11
|
-
"resources/tools/
|
|
11
|
+
"resources/tools/generated_pando-tools.json",
|
|
12
|
+
"resources/tools/generated_tools.md",
|
|
12
13
|
"tools/clojure-indexer/bin/",
|
|
13
14
|
"tools/clojure-indexer/lib/*.jar",
|
|
14
15
|
"tools/clojure-editor/bin/",
|
|
15
16
|
"tools/clojure-editor/lib/*.jar",
|
|
16
17
|
"tools/csharp-indexer/CSharpIndexer.csproj",
|
|
18
|
+
"tools/csharp-indexer/src/",
|
|
17
19
|
"tools/csharp-indexer/bin/pando-csharp-indexer",
|
|
18
|
-
"tools/csharp-indexer/bin/pando-csharp-indexer.cmd"
|
|
19
|
-
"tools/csharp-indexer/bin/Release/**/*"
|
|
20
|
+
"tools/csharp-indexer/bin/pando-csharp-indexer.cmd"
|
|
20
21
|
],
|
|
21
22
|
"engines": {
|
|
22
23
|
"node": ">=22.5.0"
|
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
"_generated": {
|
|
3
3
|
"note": "Generated file. JSON does not support comments, so regeneration instructions live here.",
|
|
4
4
|
"doNotEdit": true,
|
|
5
|
-
"docs": "
|
|
5
|
+
"docs": "generated_tools.md",
|
|
6
6
|
"sourceOfTruth": "../pando-backend/src/lib/tooling/tools.d/",
|
|
7
|
-
"backendAssembledFile": "../pando-backend/src/lib/tooling/
|
|
7
|
+
"backendAssembledFile": "../pando-backend/src/lib/tooling/generated_tools.json",
|
|
8
8
|
"regenerate": {
|
|
9
9
|
"extension": "npm run tools:schema:pando",
|
|
10
10
|
"backendValidate": "cd ../pando-backend && node scripts/validate-tools.mjs",
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
"workflow": [
|
|
15
15
|
"Edit backend tool schema in ../pando-backend/src/lib/tooling/tools.d/.",
|
|
16
16
|
"If adding a tool, update ../pando-backend/src/lib/tooling/tools.d/index.json.",
|
|
17
|
-
"Validate and assemble backend
|
|
17
|
+
"Validate and assemble backend generated_tools.json.",
|
|
18
18
|
"Run npm run tools:schema:pando in this repo to refresh this file."
|
|
19
19
|
]
|
|
20
20
|
},
|
|
@@ -44,6 +44,7 @@
|
|
|
44
44
|
"delete(path, expectedHashes, forceDeleteReferencesMayBreakSyntax, page)",
|
|
45
45
|
"insert(to, code, replaceExistingNodeAtPath, expectedHash, createFileIfMissing, newFileInitialContent, forceInsertWillBreakSyntax)",
|
|
46
46
|
"replace(path, expectedHash, with, scope, forceReplaceWillBreakSyntax)",
|
|
47
|
+
"edit-file-text(file, expectedSha256, content, replacements, edits)",
|
|
47
48
|
"replace-body(path, expectedHash, with, forceReplaceWillBreakSyntax)",
|
|
48
49
|
"change-signature(path, expectedHash, parameters, returnType, makeAsync, makeSyncFromAsync, forceChangeWillBreakSyntax, boundary, batchSaves)",
|
|
49
50
|
"filter-map-reduce(query, transforms, apply)",
|
|
@@ -63,7 +64,7 @@
|
|
|
63
64
|
"name": "read-this-first",
|
|
64
65
|
"category": "pando",
|
|
65
66
|
"signature": "read-this-first()",
|
|
66
|
-
"description": "
|
|
67
|
+
"description": "Pando is an AST-aware code navigation and editing layer for large repos. It keeps a light index of supported source files, uses that index to narrow candidate files, then parses exact AST details at query or edit time.\n\nUse Pando for source-code search, navigation, references, callers, exports, renames, inserts, replacements, and deletes. Use shell/text tools for builds, tests, generated files, non-code files, and unsupported languages.\n\nRead next:\n- workspace-overview: quick inventory of indexed files and symbols.\n- find-nodes: search by language, scope, and Datalog; request include.self/topN when you need paths and hashes for edits.\n- get-content: read files or node paths returned by search tools.\n- list-exports, find-references, and find-callers: follow symbols before changing them.\n- Writers: rename, replace, replace-body, insert, delete, and edit-file-text for .clj-kondo config/hook files. Re-run find-nodes first if a path or hash is stale.\n\nUnnamed nodes can and should still be edited with Pando. Statements, returns, calls, arguments, branches, literals, and other unnamed syntax are normal AST nodes; find them by starting from a named entity or file, then narrowing by kind, text, role, parent, or child index.\n\nExamples:\n- In one find-nodes call, search for a function by name within the workspace and request include.self/topN to get the exact node path and hash.\n- To edit a statement inside a named function, find the function with include.self, then call find-nodes again with scope.node set to { path, expectedHash } for that function. Use predicates such as :node/kind \"ReturnStatement\" or :node/text \"oldValue\", then pass the returned statement path and hash without @ to replace or insert; delete uses expectedHashes.\n- For scripts or top-level code, scope find-nodes to the file path instead of a named node, find the statement by kind/text/role/index, then edit that returned node with a writer.\n- Insert code is literal: include the newline and indentation you want when inserting before or after a statement anchor.",
|
|
67
68
|
"parameters": {
|
|
68
69
|
"type": "object",
|
|
69
70
|
"properties": {},
|
|
@@ -1530,6 +1531,99 @@
|
|
|
1530
1531
|
}
|
|
1531
1532
|
]
|
|
1532
1533
|
},
|
|
1534
|
+
{
|
|
1535
|
+
"name": "edit-file-text",
|
|
1536
|
+
"category": "pando",
|
|
1537
|
+
"signature": "edit-file-text(file, expectedSha256, content, replacements, edits)",
|
|
1538
|
+
"description": "Text-only editor for .clj-kondo config and hook files that are intentionally excluded from semantic Clojure indexing. Requires expectedSha256 of the current file text. Refuses .clj-kondo/.cache. Provide exactly one of content, replacements, or edits. Use this for .clj-kondo/config.edn or .clj-kondo hook files when a Clojure change also needs lint config updates.",
|
|
1539
|
+
"parameters": {
|
|
1540
|
+
"type": "object",
|
|
1541
|
+
"properties": {
|
|
1542
|
+
"file": {
|
|
1543
|
+
"type": "string",
|
|
1544
|
+
"description": "Workspace-relative .clj-kondo file path."
|
|
1545
|
+
},
|
|
1546
|
+
"expectedSha256": {
|
|
1547
|
+
"type": "string",
|
|
1548
|
+
"description": "SHA-256 of the current file text, 64 lowercase hex characters."
|
|
1549
|
+
},
|
|
1550
|
+
"content": {
|
|
1551
|
+
"type": "string",
|
|
1552
|
+
"description": "Full replacement content. Mutually exclusive with replacements and edits."
|
|
1553
|
+
},
|
|
1554
|
+
"replacements": {
|
|
1555
|
+
"type": "array",
|
|
1556
|
+
"description": "Exact old/new string replacements. Mutually exclusive with content and edits.",
|
|
1557
|
+
"items": {
|
|
1558
|
+
"type": "object",
|
|
1559
|
+
"properties": {
|
|
1560
|
+
"old": {
|
|
1561
|
+
"type": "string",
|
|
1562
|
+
"description": "Exact current text to replace."
|
|
1563
|
+
},
|
|
1564
|
+
"new": {
|
|
1565
|
+
"type": "string",
|
|
1566
|
+
"description": "Replacement text."
|
|
1567
|
+
},
|
|
1568
|
+
"replaceAll": {
|
|
1569
|
+
"type": "boolean",
|
|
1570
|
+
"description": "Replace every occurrence instead of requiring exactly one match."
|
|
1571
|
+
}
|
|
1572
|
+
},
|
|
1573
|
+
"required": [
|
|
1574
|
+
"old",
|
|
1575
|
+
"new"
|
|
1576
|
+
],
|
|
1577
|
+
"additionalProperties": false
|
|
1578
|
+
}
|
|
1579
|
+
},
|
|
1580
|
+
"edits": {
|
|
1581
|
+
"type": "array",
|
|
1582
|
+
"description": "Character-offset edits applied from bottom to top. Mutually exclusive with content and replacements.",
|
|
1583
|
+
"items": {
|
|
1584
|
+
"type": "object",
|
|
1585
|
+
"properties": {
|
|
1586
|
+
"start": {
|
|
1587
|
+
"type": "number",
|
|
1588
|
+
"description": "Start character offset."
|
|
1589
|
+
},
|
|
1590
|
+
"end": {
|
|
1591
|
+
"type": "number",
|
|
1592
|
+
"description": "End character offset."
|
|
1593
|
+
},
|
|
1594
|
+
"with": {
|
|
1595
|
+
"type": "string",
|
|
1596
|
+
"description": "Replacement text."
|
|
1597
|
+
}
|
|
1598
|
+
},
|
|
1599
|
+
"required": [
|
|
1600
|
+
"start",
|
|
1601
|
+
"end",
|
|
1602
|
+
"with"
|
|
1603
|
+
],
|
|
1604
|
+
"additionalProperties": false
|
|
1605
|
+
}
|
|
1606
|
+
}
|
|
1607
|
+
},
|
|
1608
|
+
"required": [
|
|
1609
|
+
"file",
|
|
1610
|
+
"expectedSha256"
|
|
1611
|
+
],
|
|
1612
|
+
"additionalProperties": false
|
|
1613
|
+
},
|
|
1614
|
+
"examples": [
|
|
1615
|
+
{
|
|
1616
|
+
"file": ".clj-kondo/config.edn",
|
|
1617
|
+
"expectedSha256": "0000000000000000000000000000000000000000000000000000000000000000",
|
|
1618
|
+
"replacements": [
|
|
1619
|
+
{
|
|
1620
|
+
"old": ":old/ns",
|
|
1621
|
+
"new": ":new/ns"
|
|
1622
|
+
}
|
|
1623
|
+
]
|
|
1624
|
+
}
|
|
1625
|
+
]
|
|
1626
|
+
},
|
|
1533
1627
|
{
|
|
1534
1628
|
"name": "replace-body",
|
|
1535
1629
|
"category": "pando",
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
# Tool Schema Pipeline
|
|
2
|
+
|
|
3
|
+
`resources/tools/generated_pando-tools.json` in this repo is generated. Do not edit it directly.
|
|
4
|
+
|
|
5
|
+
## Source of Truth
|
|
6
|
+
|
|
7
|
+
The canonical tool definitions live in the backend repo:
|
|
8
|
+
|
|
9
|
+
- Backend per-tool files: [`../pando-backend/src/lib/tooling/tools.d/`](/Users/george/Documents/GitHub/pando-backend/src/lib/tooling/tools.d)
|
|
10
|
+
- Backend assembled file: [`../pando-backend/src/lib/tooling/generated_tools.json`](/Users/george/Documents/GitHub/pando-backend/src/lib/tooling/generated_tools.json)
|
|
11
|
+
- Extension bundled subset: [`resources/tools/generated_pando-tools.json`](/Users/george/Documents/GitHub/pando-extension/resources/tools/generated_pando-tools.json)
|
|
12
|
+
- CLI package bundled subset: [`packages/pando-cli/resources/tools/generated_pando-tools.json`](/Users/george/Documents/GitHub/pando-extension/packages/pando-cli/resources/tools/generated_pando-tools.json)
|
|
13
|
+
|
|
14
|
+
Each tool has its own JSON file in `tools.d`. `tools.d/index.json` controls ordering and the assembled signature list.
|
|
15
|
+
|
|
16
|
+
## Backend Workflow
|
|
17
|
+
|
|
18
|
+
When changing tool schemas:
|
|
19
|
+
|
|
20
|
+
1. Edit or add the relevant `tools.d/*.json` file in `../pando-backend/src/lib/tooling/tools.d/`.
|
|
21
|
+
2. If it is a new tool, update `tools.d/index.json`:
|
|
22
|
+
- add its signature to `signatures`
|
|
23
|
+
- add its name to `order`
|
|
24
|
+
3. Keep the generated signatures aligned with the live MCP surface. If a parameter is removed from a tool implementation, remove it from the backend `tools.d/*.json` schema first, then regenerate the assembled and bundled JSON files.
|
|
25
|
+
4. Validate schemas:
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
cd ../pando-backend
|
|
29
|
+
node scripts/validate-tools.mjs
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
5. Re-assemble `generated_tools.json`:
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
cd ../pando-backend
|
|
36
|
+
node scripts/assemble-tools.mjs
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
If you ever need to rebuild `tools.d/` from an edited backend `generated_tools.json`, use:
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
cd ../pando-backend
|
|
43
|
+
node scripts/split-tools.mjs
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
## Extension Workflow
|
|
47
|
+
|
|
48
|
+
The extension bundles only the Pando-prefixed subset of the backend tool catalog.
|
|
49
|
+
|
|
50
|
+
Generate the bundled file with:
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
cd /Users/george/Documents/GitHub/pando-extension
|
|
54
|
+
npm run tools:schema:pando
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
This runs [`scripts/generate-pando-tools.mjs`](/Users/george/Documents/GitHub/pando-extension/scripts/generate-pando-tools.mjs), which:
|
|
58
|
+
|
|
59
|
+
- reads `../pando-backend/src/lib/tooling/generated_tools.json` by default
|
|
60
|
+
- keeps only `pando_*` / `pando-*` tools
|
|
61
|
+
- normalizes names like `pando_find_nodes` to `find-nodes`
|
|
62
|
+
- writes [`resources/tools/generated_pando-tools.json`](/Users/george/Documents/GitHub/pando-extension/resources/tools/generated_pando-tools.json)
|
|
63
|
+
- writes the same bundled schema to [`packages/pando-cli/resources/tools/generated_pando-tools.json`](/Users/george/Documents/GitHub/pando-extension/packages/pando-cli/resources/tools/generated_pando-tools.json)
|
|
64
|
+
- fails if the backend assembled `generated_tools.json` cannot be found, so builds do not silently reuse a stale bundled schema
|
|
65
|
+
|
|
66
|
+
To point the extension generator at a different backend file temporarily:
|
|
67
|
+
|
|
68
|
+
```bash
|
|
69
|
+
PANDO_BACKEND_TOOLS_JSON=/abs/path/to/generated_tools.json npm run tools:schema:pando
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
## Build Integration
|
|
73
|
+
|
|
74
|
+
These extension scripts already regenerate the bundled schema:
|
|
75
|
+
|
|
76
|
+
- `npm run compile`
|
|
77
|
+
- `npm run vscode:prepublish`
|
|
78
|
+
|
|
79
|
+
Both flow through `npm run tools:schema:pando`.
|
|
80
|
+
|
|
81
|
+
## Runtime Loading
|
|
82
|
+
|
|
83
|
+
The extension reads the bundled schema from:
|
|
84
|
+
|
|
85
|
+
- [`resources/tools/generated_pando-tools.json`](/Users/george/Documents/GitHub/pando-extension/resources/tools/generated_pando-tools.json)
|
|
86
|
+
|
|
87
|
+
Relevant code paths:
|
|
88
|
+
|
|
89
|
+
- webview loading: [`src/extension/webview/ChatViewProvider.ts`](/Users/george/Documents/GitHub/pando-extension/src/extension/webview/ChatViewProvider.ts)
|
|
90
|
+
- MCP server loading: [`src/extension/mcp/PandoMcpServer.ts`](/Users/george/Documents/GitHub/pando-extension/src/extension/mcp/PandoMcpServer.ts)
|
|
91
|
+
- refresh helper: [`src/extension/utils/toolsSchemaCache.ts`](/Users/george/Documents/GitHub/pando-extension/src/extension/utils/toolsSchemaCache.ts)
|
|
92
|
+
|
|
93
|
+
`toolsSchemaCache.ts` is currently a no-op refresh path, so the bundled file is the normal source at runtime.
|
|
Binary file
|
|
Binary file
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<Project Sdk="Microsoft.NET.Sdk">
|
|
2
2
|
<PropertyGroup>
|
|
3
3
|
<OutputType>Exe</OutputType>
|
|
4
|
-
<TargetFrameworks>net8.0;net10.0</TargetFrameworks>
|
|
4
|
+
<TargetFrameworks>net8.0;net9.0;net10.0</TargetFrameworks>
|
|
5
5
|
<Nullable>enable</Nullable>
|
|
6
6
|
<LangVersion>latest</LangVersion>
|
|
7
7
|
</PropertyGroup>
|
|
@@ -2,31 +2,89 @@
|
|
|
2
2
|
set -euo pipefail
|
|
3
3
|
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
5
|
+
if ! command -v dotnet >/dev/null 2>&1; then
|
|
6
|
+
echo "CSharpIndexer requires the .NET SDK on PATH so it can build against the host SDK on first run." >&2
|
|
7
|
+
echo "Install .NET SDK from https://dotnet.microsoft.com/download" >&2
|
|
8
|
+
exit 1
|
|
9
|
+
fi
|
|
10
|
+
|
|
11
|
+
if [ ! -f "$ROOT_DIR/CSharpIndexer.csproj" ] || [ ! -f "$ROOT_DIR/src/Program.cs" ]; then
|
|
12
|
+
echo "CSharpIndexer source is missing from $ROOT_DIR." >&2
|
|
13
|
+
exit 1
|
|
14
|
+
fi
|
|
15
|
+
|
|
16
|
+
pick_sdk_major() {
|
|
17
|
+
local major
|
|
18
|
+
for major in 10 9 8; do
|
|
19
|
+
if dotnet --list-sdks 2>/dev/null | grep -q "^${major}\\."; then
|
|
20
|
+
echo "$major"
|
|
21
|
+
return
|
|
22
|
+
fi
|
|
23
|
+
done
|
|
24
|
+
dotnet --version 2>/dev/null | sed -E 's/^([0-9]+).*/\1/'
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
hash_source() {
|
|
28
|
+
local hasher
|
|
29
|
+
if command -v sha256sum >/dev/null 2>&1; then
|
|
30
|
+
hasher=sha256sum
|
|
31
|
+
else
|
|
32
|
+
hasher="shasum -a 256"
|
|
16
33
|
fi
|
|
17
|
-
|
|
34
|
+
(
|
|
35
|
+
cd "$ROOT_DIR"
|
|
36
|
+
printf '%s\n' "v2"
|
|
37
|
+
find src -type f -name '*.cs' -print | LC_ALL=C sort | while IFS= read -r file; do
|
|
38
|
+
$hasher "$file"
|
|
39
|
+
done
|
|
40
|
+
$hasher CSharpIndexer.csproj
|
|
41
|
+
) | $hasher | awk '{print $1}'
|
|
18
42
|
}
|
|
19
43
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
44
|
+
SDK_MAJOR="$(pick_sdk_major)"
|
|
45
|
+
if ! [[ "$SDK_MAJOR" =~ ^[0-9]+$ ]] || [ "$SDK_MAJOR" -lt 8 ]; then
|
|
46
|
+
echo "CSharpIndexer requires .NET SDK 8.0 or newer; found: $(dotnet --version 2>/dev/null || echo unknown)." >&2
|
|
47
|
+
exit 1
|
|
48
|
+
fi
|
|
49
|
+
|
|
50
|
+
TFM="net${SDK_MAJOR}.0"
|
|
51
|
+
SOURCE_HASH="$(hash_source)"
|
|
52
|
+
CACHE_BASE="${PANDO_CSHARP_INDEXER_CACHE_DIR:-${XDG_CACHE_HOME:-$HOME/.cache}/pando/csharp-indexer}"
|
|
53
|
+
BUILD_DIR="$CACHE_BASE/$SOURCE_HASH/$TFM"
|
|
54
|
+
DLL="$BUILD_DIR/CSharpIndexer.dll"
|
|
55
|
+
INTERMEDIATE_DIR="$BUILD_DIR/obj/"
|
|
56
|
+
BASE_OUTPUT_DIR="$BUILD_DIR/bin/"
|
|
57
|
+
|
|
58
|
+
if [ ! -f "$DLL" ]; then
|
|
59
|
+
mkdir -p "$BUILD_DIR"
|
|
60
|
+
LOCK_DIR="$BUILD_DIR.lock"
|
|
61
|
+
LOCK_ACQUIRED=0
|
|
62
|
+
while ! mkdir "$LOCK_DIR" 2>/dev/null; do
|
|
63
|
+
if [ -f "$DLL" ]; then
|
|
64
|
+
break
|
|
65
|
+
fi
|
|
66
|
+
sleep 0.2
|
|
67
|
+
done
|
|
68
|
+
if [ ! -f "$DLL" ]; then
|
|
69
|
+
LOCK_ACQUIRED=1
|
|
70
|
+
trap 'rmdir "$LOCK_DIR" 2>/dev/null || true' EXIT
|
|
71
|
+
fi
|
|
72
|
+
if [ ! -f "$DLL" ]; then
|
|
73
|
+
echo "Building CSharpIndexer for $TFM in $BUILD_DIR" >&2
|
|
74
|
+
dotnet publish "$ROOT_DIR/CSharpIndexer.csproj" \
|
|
75
|
+
-c Release \
|
|
76
|
+
-f "$TFM" \
|
|
77
|
+
-o "$BUILD_DIR" \
|
|
78
|
+
/p:TargetFrameworks="$TFM" \
|
|
79
|
+
/p:BaseIntermediateOutputPath="$INTERMEDIATE_DIR" \
|
|
80
|
+
/p:MSBuildProjectExtensionsPath="$INTERMEDIATE_DIR" \
|
|
81
|
+
/p:BaseOutputPath="$BASE_OUTPUT_DIR" \
|
|
82
|
+
--nologo >&2
|
|
83
|
+
fi
|
|
84
|
+
if [ "$LOCK_ACQUIRED" = "1" ]; then
|
|
85
|
+
rmdir "$LOCK_DIR" 2>/dev/null || true
|
|
86
|
+
trap - EXIT
|
|
26
87
|
fi
|
|
27
|
-
|
|
88
|
+
fi
|
|
28
89
|
|
|
29
|
-
|
|
30
|
-
echo "Build it with:" >&2
|
|
31
|
-
echo " dotnet build \"$ROOT_DIR/CSharpIndexer.csproj\" -c Release -f net10.0" >&2
|
|
32
|
-
exit 1
|
|
90
|
+
exec dotnet "$DLL" "$@"
|