pando-ai 0.0.16 → 0.0.18
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/README.md +14 -14
- package/bin/pando-ai.js +38 -0
- package/dist/cli.js +182 -189
- package/dist/watcher-process.js +434 -441
- package/dist/workers/chunk-HQDE7M4W.mjs +4 -0
- package/dist/workers/chunk-UIWCIYYF.mjs +522 -0
- package/dist/workers/indexer-worker.mjs +1 -1
- package/dist/workers/snapshot-worker.mjs +4 -4
- package/dist/workers/sqlite-writer-worker.mjs +6 -8
- package/package.json +3 -2
- package/resources/tools/pando-tools.json +63 -2
- 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/dist/workers/chunk-2YGY7BLN.mjs +0 -1
- package/dist/workers/chunk-QOET4233.mjs +0 -528
|
@@ -1 +1 @@
|
|
|
1
|
-
import{c as b,
|
|
1
|
+
import{c as b,d as O,e as L,f as D,g as E,h as A,l as C}from"./chunk-UIWCIYYF.mjs";import{f as q}from"./chunk-HQDE7M4W.mjs";import{c as N}from"./chunk-AYCBSZ56.mjs";import{parentPort as i,threadId as se}from"worker_threads";import K from"fs";import z from"path";import{promises as X}from"fs";import G from"ignore";import{createHash as re}from"crypto";q();q();var ee=Math.max(1,Number(process.env.PANDO_BATCH_INDEX_MAX_FILES||"64")),te=Math.max(1,Number(process.env.PANDO_BATCH_INDEX_MAX_BYTES||`${1024*1024}`)),oe=Math.max(1,Number(process.env.PANDO_BATCH_INDEX_MAX_WAIT_MS||"15")),de=Math.max(ee,Number(process.env.PANDO_BATCH_INDEX_MAX_PENDING_FILES||"256")),le=Math.max(te,Number(process.env.PANDO_BATCH_INDEX_MAX_PENDING_BYTES||`${8*1024*1024}`));var xe=1*1024*1024,Pe=Math.max(3e4,Number(process.env.PANDO_WORKER_INIT_TIMEOUT_MS||12e4)),be=L();function U(e,t){return Buffer.from(e).toString(t)}function W(e,t,n,r,a){let l=Buffer.from(e),m=re("sha1").update(l).digest("hex"),s=l.toString(a),h=s?s.split(/\r?\n/).length:0;return{relPath:t,size:n,mtime:r,objectId:m,lineCount:h,encoding:a}}if(!i)throw new Error("Indexer worker must be spawned as a worker thread");N();function u(e,t){try{if(t===void 0){console.error(`[${new Date().toISOString()}] [IndexerWorker] ${e}`);return}console.error(`[${new Date().toISOString()}] [IndexerWorker] ${e} ${JSON.stringify({pid:process.pid,threadId:se,...t&&typeof t=="object"&&!Array.isArray(t)?t:{details:t}})}`)}catch{}}u("module loaded",{cwd:process.cwd(),hasParentPort:!!i,envWorkerRoot:process.env.PANDO_WORKER_SCRIPT_DIR??null,envRuntimeRoot:process.env.PANDO_RUNTIME_ROOT??null});var H=new Map,B="",F="index",I=new Map,S=new Set;function Y(e,t){return z.relative(e,t).replace(/\\/g,"/")}function ie(e,t){let n=(t||[]).map(r=>typeof r=="string"?r.trim():"").filter(Boolean).map(r=>r.replace(/^[\\/]+/,"").replace(/[\\/]+$/,"")).map(r=>r.endsWith("/")?r:`${r}/`);return n.length?r=>{let a=Y(e,r);if(!a||a.startsWith(".."))return!1;let l=a.endsWith("/")?a:`${a}/`;return n.some(m=>l.startsWith(m))}:null}async function ne(e){await new Promise(t=>{I.set(e,t)})}i.on("message",async e=>{if(e.cmd==="scan-ack"){let t=I.get(e.requestId);if(t){I.delete(e.requestId);try{t()}catch{}}return}if(e.cmd==="scan-cancel"){S.add(e.requestId);let t=I.get(e.requestId);if(t){I.delete(e.requestId);try{t()}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"&&(B=e.projectRoot),F=e.mode??"index",u("init completed",{mode:F,projectRoot:B}),i.postMessage({type:"ready"})}catch(t){u("init failed",{error:t?.message||String(t),stack:t?.stack??null}),i.postMessage({type:"error",message:`init failed: ${t?.message||t}`,stack:t?.stack})}return}if(e.cmd==="scan"){let t=e.requestId,n=typeof e.projectRoot=="string"?e.projectRoot:B;if(u("scan received",{requestId:t,projectRoot:n||null,batchSize:e.batchSize??null,maxFileBytes:e.maxFileBytes??null,excludeDirs:Array.isArray(e.excludeDirs)?e.excludeDirs.slice(0,20):[]}),!n){i.postMessage({type:"error",requestId:t,message:"worker not initialized"});return}let r=Math.max(1,Math.min(500,Number(e.batchSize||100))),a=Math.max(1,Number(e.maxFileBytes||1*1024*1024)),l=e.languageSupport,m=A(l),s=ie(n,e.excludeDirs??[]),h=new Set(["node_modules",".git",".pando-data"]),g=d=>d.replace(/\\/g,"/"),y=await C(n,""),w=G().add(y),o=[{dir:n,relDir:"",rules:y,ig:w}],p=0,c=0,v=[],$=async()=>{v.length&&(i.postMessage({type:"scan:batch",requestId:t,files:v}),v=[],await ne(t))};try{for(;o.length&&!S.has(t);){let d=o.pop(),j=[];try{j=await X.readdir(d.dir,{withFileTypes:!0})}catch{c+=1;continue}for(let f of j){if(S.has(t))break;let k=z.join(d.dir,f.name);if(f.isSymbolicLink?.()){c+=1;continue}if(f.isDirectory()){if(h.has(f.name)){c+=1;continue}if(s?.(k)){c+=1;continue}let Q=d.relDir?`${d.relDir}/${f.name}`:f.name,M=g(Q);if(d.ig.ignores(M)){c+=1;continue}let R=d.rules.slice(),T=await C(k,M);T.length&&R.push(...T);let V=G().add(R);o.push({dir:k,relDir:M,rules:R,ig:V});continue}if(!f.isFile()){c+=1;continue}if(s?.(k)){c+=1;continue}let x=Y(n,k);if(!x||x.startsWith("..")){c+=1;continue}if(d.ig.ignores(x)){c+=1;continue}let J=z.extname(f.name).toLowerCase();if(!m.has(J)){c+=1;continue}let _=D(x);if(!_){c+=1;continue}let P;try{P=await X.stat(k)}catch{c+=1;continue}if(P.size>a){c+=1;continue}v.push({relPath:x,absPath:k,mtimeMs:Math.floor(P.mtimeMs),size:P.size,lang:_}),p+=1,v.length>=r&&await $()}}S.has(t)||await $(),i.postMessage({type:"scan:done",requestId:t,discovered:p,skipped:c,cancelled:S.has(t)}),u("scan complete",{requestId:t,discovered:p,skipped:c,cancelled:S.has(t)})}catch(d){u("scan failed",{requestId:t,error:d?.message||String(d),stack:d?.stack??null}),i.postMessage({type:"error",requestId:t,message:d?.message||String(d),stack:d?.stack})}finally{S.delete(t),I.delete(t)}return}if(e.cmd==="process"){let t=e.role??F,n=typeof e.projectRoot=="string"?e.projectRoot:B;if(!n){i.postMessage({type:"error",requestId:e.requestId,message:"worker not initialized"});return}let{file:r}=e,a=r.encoding??"utf8",l=r.sharedBuffer,m={size:r.size,mtime:r.mtime};try{if(t==="index"){let s=r.lang??"ts",h=`${n}:${s}`,g=H.get(h);if(!g)try{u("creating language indexer",{role:t,requestId:e.requestId,lang:s,projectRoot:n});let o=E(s);if(!O(o))throw new Error(`${s} is not a worker-indexed language`);g=o.createIndexer(n),H.set(h,g),u("language indexer ready",{role:t,requestId:e.requestId,lang:s,projectRoot:n})}catch(o){if(u("language indexer create failed",{role:t,requestId:e.requestId,lang:s,error:o?.message||String(o),stack:o?.stack??null}),s!=="ts"&&s!=="js"){let p=b(s,r.relPath,m);i.postMessage({type:"result",requestId:e.requestId,role:"index",relPath:r.relPath,result:{payload:p.payload,meta:{size:p.fileSize,mtime:p.mtime}}});return}throw o}let y;l instanceof SharedArrayBuffer?y=U(l,a):l instanceof ArrayBuffer?y=Buffer.from(l).toString(a):y=K.readFileSync(r.absPath,a);let w;try{w=await g.process({absPath:r.absPath,relPath:r.relPath,content:y,meta:m,preDeleted:!!r.preDeleted,lang:s})}catch(o){if(u("process failed",{role:t,requestId:e.requestId,lang:s,relPath:r.relPath,error:o?.message||String(o),stack:o?.stack??null}),s!=="ts"&&s!=="js"){let p=b(s,r.relPath,m);i.postMessage({type:"result",requestId:e.requestId,role:"index",relPath:r.relPath,result:{payload:p.payload,meta:{size:p.fileSize,mtime:p.mtime}}});return}throw o}i.postMessage({type:"result",requestId:e.requestId,role:"index",relPath:r.relPath,result:{payload:w.payload,meta:{size:w.fileSize,mtime:w.mtime}}})}else if(l instanceof SharedArrayBuffer){let s=W(l,r.relPath,r.size,r.mtime,a);i.postMessage({type:"result",requestId:e.requestId,role:"snapshot",relPath:r.relPath,result:s})}else if(l instanceof ArrayBuffer){let s=Buffer.from(l),h=new SharedArrayBuffer(s.byteLength);new Uint8Array(h).set(s);let g=W(h,r.relPath,r.size,r.mtime,a);i.postMessage({type:"result",requestId:e.requestId,role:"snapshot",relPath:r.relPath,result:g})}else{let s=K.readFileSync(r.absPath),h=new SharedArrayBuffer(s.byteLength);new Uint8Array(h).set(s);let g=W(h,r.relPath,r.size,r.mtime,a);i.postMessage({type:"result",requestId:e.requestId,role:"snapshot",relPath:r.relPath,result:g})}}catch(s){u("process wrapper failed",{role:t,requestId:e.requestId,relPath:r.relPath,error:s?.message||String(s),stack:s?.stack??null}),i.postMessage({type:"error",requestId:e.requestId,message:s?.message||String(s),stack:s?.stack})}return}e.cmd==="close"&&i.postMessage({type:"closed"})});process.on("uncaughtException",e=>{try{i.postMessage({type:"error",message:e?.message||String(e),stack:e?.stack})}catch{}});process.on("unhandledRejection",e=>{try{i.postMessage({type:"error",message:String(e)})}catch{}});
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import{a as N,b as
|
|
2
|
-
`),
|
|
3
|
-
`,"utf8");try{await g.add({fs:o,dir:this.repoDir,filepath:".gitignore"})}catch{}m(`[GitHistoryStore] restored missing .gitignore at ${t}`)}catch(e){at(`[GitHistoryStore] failed to recreate .gitignore: ${e?.message||e}`)}}normalizeLogicalPath(t){return String(t||"").replace(/\\/g,"/").replace(/^(?:\.\/)+/,"").replace(/^\/+/,"")}gitExists(){try{return j("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,l=e;if(!l)try{l=j("git",["rev-parse","HEAD"],{cwd:this.repoDir,encoding:"utf8"}).trim()}catch{l=void 0}let p=new Map,f=Date.now();try{m("[GitHistoryStore] native snapshot start",{traceId:a,repoDir:this.repoDir,memberCount:t.length,parentOid:l||null})}catch{}for(let c=0;c<t.length;c++){let h=t[c];if(h.content==null)throw new Error(`Direct snapshot requires content for ${h.logicalPath}`);let b=Buffer.isBuffer(h.content)?h.content:Buffer.from(h.content),w=this.normalizeLogicalPath(h.logicalPath);if(!w)throw new Error("Direct snapshot requires non-empty logicalPath");let y=Date.now();try{m("[GitHistoryStore] native hash-object start",{traceId:a,repoDir:this.repoDir,index:c+1,total:t.length,logicalPath:w,bytes:b.length})}catch{}let T;try{T=j("git",["hash-object","-w","--stdin"],{cwd:this.repoDir,input:b}).toString("utf8").trim()}catch(D){try{at("[GitHistoryStore] native hash-object failed",{traceId:a,repoDir:this.repoDir,index:c+1,total:t.length,logicalPath:w,bytes:b.length,durationMs:Date.now()-y,message:D?.message||String(D),status:D?.status??null,signal:D?.signal??null,stdout:D?.stdout?String(D.stdout).slice(0,500):null,stderr:D?.stderr?String(D.stderr).slice(0,500):null})}catch{}throw D}let I=Date.now()-y;try{(I>1e3||c<3||c===t.length-1)&&m("[GitHistoryStore] native hash-object done",{traceId:a,repoDir:this.repoDir,index:c+1,total:t.length,logicalPath:w,bytes:b.length,durationMs:I,oid:T})}catch{}p.set(w,T)}try{m("[GitHistoryStore] native hash-object phase complete",{traceId:a,repoDir:this.repoDir,memberCount:t.length,durationMs:Date.now()-f})}catch{}let u=x.join(this.repoDir,`.pando-index-${process.pid}-${Date.now()}`),S={...process.env,GIT_INDEX_FILE:u};try{let c=Date.now();try{m("[GitHistoryStore] native read-tree begin",{traceId:a,repoDir:this.repoDir,tmpIndex:u})}catch{}j("git",["read-tree","--empty"],{cwd:this.repoDir,env:S});try{m("[GitHistoryStore] native read-tree complete",{traceId:a,repoDir:this.repoDir,durationMs:Date.now()-c})}catch{}let h=Array.from(p.keys()).sort((C,M)=>C.localeCompare(M)),b=Date.now();for(let C of h){let M=p.get(C);j("git",["update-index","--add","--cacheinfo","100644",M,C],{cwd:this.repoDir,env:S})}try{m("[GitHistoryStore] native update-index complete",{traceId:a,repoDir:this.repoDir,entryCount:h.length,durationMs:Date.now()-b})}catch{}let w=Date.now();try{m("[GitHistoryStore] native write-tree begin",{traceId:a,repoDir:this.repoDir,entryCount:h.length})}catch{}let y=j("git",["write-tree"],{cwd:this.repoDir,env:S}).toString("utf8").trim();try{m("[GitHistoryStore] native write-tree complete",{traceId:a,repoDir:this.repoDir,treeOid:y,durationMs:Date.now()-w})}catch{}let T=["commit-tree",y];l&&T.push("-p",l),n&&T.push("-m",n);let I=Date.now();try{m("[GitHistoryStore] native commit-tree begin",{traceId:a,repoDir:this.repoDir,treeOid:y,parentOid:l||null})}catch{}let D=j("git",T,{cwd:this.repoDir}).toString("utf8").trim();try{m("[GitHistoryStore] native commit-tree complete",{traceId:a,repoDir:this.repoDir,commitOid:D,durationMs:Date.now()-I})}catch{}let R=Date.now();try{m("[GitHistoryStore] native update-ref begin",{traceId:a,repoDir:this.repoDir,commitOid:D})}catch{}j("git",["update-ref","refs/heads/master",D],{cwd:this.repoDir});try{m("[GitHistoryStore] native update-ref complete",{traceId:a,repoDir:this.repoDir,commitOid:D,durationMs:Date.now()-R})}catch{}return{snapshotId:D,parent:l}}finally{try{o.unlinkSync(u)}catch{}try{o.unlinkSync(`${u}.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){v(e,"Snapshot cancelled"),await this.ensureInitialized(),m(`[${new Date().toISOString()}] [GitHistoryStore] Creating snapshot (streaming) with ${t.members.length} members`);let n=[...t.members].map(d=>({...d,logicalPath:this.normalizeLogicalPath(d.logicalPath)})).filter(d=>!!d.logicalPath).sort((d,E)=>d.logicalPath.localeCompare(E.logicalPath)),r=this.gitExists()&&!e;try{r?N.info("[GitHistoryStore] Using native git snapshot path",{members:n.length}):N.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(d){try{N.warn(`[GitHistoryStore] Native git path failed; falling back to JS path: ${d?.message||d}`)}catch{}}let i=Date.now(),a=d=>d.toString("hex"),l=d=>bt("crypto").createHash("sha1").update(d).digest(),p=d=>{let E=Buffer.from(`blob ${d.length}\0`,"utf8"),A=Buffer.concat([E,d]);return a(l(A))},f=Math.max(1,Math.min(64,Number(process.env.SNAPSHOT_BLOB_CONCURRENCY||16))),u=String(process.env.SNAPSHOT_PRECOMPUTE_OIDS||"1")!=="0";try{N.info("[GitHistoryStore] JS snapshot settings",{SNAPSHOT_BLOB_CONCURRENCY:f,SNAPSHOT_PRECOMPUTE_OIDS:u})}catch{}let S=new Map,c=0,h=0,b=0,w=n.map(d=>({path:d.logicalPath,buf:Buffer.isBuffer(d.content)?d.content:Buffer.from(d.content)})),y=async()=>{for(;;){v(e,"Snapshot cancelled");let d;if(c<w.length)d=w[c++];else break;let E;if(u)try{let A=p(d.buf);await this.hasObject(A)&&(E=A,b++)}catch{}if(E||(E=await g.writeBlob({fs:o,dir:this.repoDir,blob:d.buf}),h++),v(e,"Snapshot cancelled"),!E)throw new Error("Failed to compute blob object id");S.set(d.path,E)}},T=Array.from({length:Math.min(f,w.length)},()=>y());await Promise.all(T),v(e,"Snapshot cancelled"),m(`[GitHistoryStore] Blobs ready wrote=${h} skipped=${b} in ${Date.now()-i}ms`);let I=new H(this.repoDir),D=Array.from(S.keys()).sort((d,E)=>d.localeCompare(E));for(let d of D)v(e,"Snapshot cancelled"),await I.addFile(d,S.get(d));v(e,"Snapshot cancelled");let R=Date.now(),C=await I.finish();m(`[GitHistoryStore] Wrote tree(s). root=${C} in ${Date.now()-R}ms`);let M=t.parent;if(!M)try{M=await g.resolveRef({fs:o,dir:this.repoDir,ref:"HEAD"})}catch{}v(e,"Snapshot cancelled");let L=t.when?Math.floor(t.when/1e3):Math.floor(Date.now()/1e3),B=new Date(L*1e3).getTimezoneOffset(),$=await g.commit({fs:o,dir:this.repoDir,message:t.message,parent:M?[M]:[],tree:C,author:{name:"ast-db",email:"ast-db@example.com",timestamp:L,timezoneOffset:B},committer:{name:"ast-db",email:"ast-db@example.com",timestamp:L,timezoneOffset:B}});return await g.writeRef({fs:o,dir:this.repoDir,ref:"refs/heads/master",value:$,force:!0}),m(`[GitHistoryStore] Snapshot commit oid ${$}`),$}async listSnapshotMembers(t){await this.ensureInitialized();let e=i=>Math.round((i||0)/(1024*1024)),n=()=>{let i=process.memoryUsage();return`rss=${e(i.rss)}MB heapUsed=${e(i.heapUsed)}MB heapTotal=${e(i.heapTotal)}MB`},r=[];return m(`[${new Date().toISOString()}] [GitHistoryStore] listSnapshotMembers(${t}) start (${n()})`),await g.walk({fs:o,dir:this.repoDir,trees:[g.TREE({ref:t})],map:async(i,[a])=>{if(!a)return;if(await a.type()==="blob"){let p=await a.oid();r.push({logicalPath:i,objectId:p})}}}),m(`[${new Date().toISOString()}] [GitHistoryStore] listSnapshotMembers(${t}) -> ${r.length} blobs`),r.filter(i=>i.logicalPath&&i.logicalPath!==".").map(i=>({logicalPath:i.logicalPath.replace(/^\.\//,""),objectId:i.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){await this.ensureInitialized(),m(`[${new Date().toISOString()}] [GitHistoryStore] Creating snapshot from disk (streaming) with ${t.relPaths.length} members`);let e=[...t.relPaths].map(c=>this.normalizeLogicalPath(c)).filter(Boolean).sort((c,h)=>c.localeCompare(h)),n=Date.now(),r=new H(this.repoDir),i=0;for(let c of e){let h=x.join(this.baseDir,c);try{let b=o.readFileSync(h),w=await g.writeBlob({fs:o,dir:this.repoDir,blob:b});await r.addFile(c,w),i++}catch{}}m(`[GitHistoryStore] Wrote ${i} blobs (disk) in ${Date.now()-n}ms`);let a=Date.now(),l=await r.finish();m(`[GitHistoryStore] Wrote tree(s) (disk). root=${l} in ${Date.now()-a}ms`);let p;try{p=await g.resolveRef({fs:o,dir:this.repoDir,ref:"HEAD"})}catch{}let f=t.when?Math.floor(t.when/1e3):Math.floor(Date.now()/1e3),u=new Date(f*1e3).getTimezoneOffset(),S=await g.commit({fs:o,dir:this.repoDir,message:t.message,parent:p?[p]:[],tree:l,author:{name:"ast-db",email:"ast-db@example.com",timestamp:f,timezoneOffset:u},committer:{name:"ast-db",email:"ast-db@example.com",timestamp:f,timezoneOffset:u}});return m(`[GitHistoryStore] Snapshot commit oid ${S}`),S}async createSnapshotFromDiskIfChanged(t){await this.ensureInitialized(),m(`[${new Date().toISOString()}] [GitHistoryStore] Creating snapshot from disk (diff) with ${t.relPaths.length} members`);let e=[...t.relPaths].map(c=>this.normalizeLogicalPath(c)).filter(Boolean).sort((c,h)=>c.localeCompare(h)),n=Date.now(),r=new H(this.repoDir),i=0;for(let c of e){let h=x.join(this.baseDir,c);try{let b=o.readFileSync(h),w=await g.writeBlob({fs:o,dir:this.repoDir,blob:b});await r.addFile(c,w),i++}catch{}}m(`[GitHistoryStore] Wrote ${i} blobs (disk) in ${Date.now()-n}ms`);let a=Date.now(),l=await r.finish();m(`[GitHistoryStore] Wrote tree(s) (disk). root=${l} in ${Date.now()-a}ms`);let p=t.parent;if(!p)try{p=await g.resolveRef({fs:o,dir:this.repoDir,ref:"HEAD"})}catch{}if(p)try{let{commit:c}=await g.readCommit({fs:o,dir:this.repoDir,oid:p});if(c?.tree===l){m("[GitHistoryStore] Snapshot identical to parent; skipping commit",{parentOid:p,tree:l});let h=await this.readCommitParent(p);return{snapshotId:p,identical:!0,parent:h}}}catch(c){m("[GitHistoryStore] Parent read failed; proceeding with commit",{error:c?.message||String(c)})}let f=t.when?Math.floor(t.when/1e3):Math.floor(Date.now()/1e3),u=new Date(f*1e3).getTimezoneOffset(),S=await g.commit({fs:o,dir:this.repoDir,message:t.message,parent:p?[p]:[],tree:l,author:{name:"ast-db",email:"ast-db@example.com",timestamp:f,timezoneOffset:u},committer:{name:"ast-db",email:"ast-db@example.com",timestamp:f,timezoneOffset:u}});return await g.writeRef({fs:o,dir:this.repoDir,ref:"refs/heads/master",value:S,force:!0}),m(`[GitHistoryStore] Snapshot commit oid ${S}`),{snapshotId:S,identical:!1,parent:p}}};function Q(s){let t={},e=s.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 Z from"fs";import G from"path";import Tt from"ignore";import{Project as Xt}from"ts-morph";function ct(s,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 i=n(G.relative(s,r));if(!i||i.startsWith(".."))return!1;let a=i.endsWith("/")?i:`${i}/`;return e.some(l=>a.startsWith(l))}}function lt(s,t,e){let n=e?.shouldExclude||null,r=[],i=new Set(Array.from(t,f=>f.toLowerCase())),a=new Set(["node_modules",".git",".pando-data"]),l=Et(e?.gitignoreRoot??s),p=[s];for(;p.length;){let f=p.pop(),u=[];try{u=Z.readdirSync(f,{withFileTypes:!0})}catch{continue}for(let S of u){let c=G.join(f,S.name);if(!(typeof S.isSymbolicLink=="function"&&S.isSymbolicLink())){if(S.isDirectory()){if(a.has(S.name)||n?.(c))continue;p.push(c)}else if(S.isFile()){if(n?.(c))continue;let b=It(G.relative(s,c));if(l&&l(b))continue;let w=G.extname(S.name).toLowerCase();i.has(w)&&r.push(c)}}}}return r}function Et(s){let t=G.join(s,".gitignore");if(!Z.existsSync(t))return null;try{let e=Tt(),n=Z.readFileSync(t,"utf8");return e.add(n.split(/\r?\n/).filter(Boolean)),r=>e.ignores(r)}catch{return null}}function It(s){return s.replace(/\\/g,"/")}Y();Dt();Y();import q from"fs";import Pt from"path";function ht(s){s.pragma("journal_mode = WAL"),s.pragma("synchronous = NORMAL"),s.pragma("busy_timeout = 10000");try{s.pragma("temp_store = MEMORY")}catch{}s.exec(`
|
|
1
|
+
import{a as N,b as Et,i as V,j as R,k as K}from"./chunk-UIWCIYYF.mjs";import{a as W,b as nt,c as Y,e as k,f as Tt}from"./chunk-HQDE7M4W.mjs";import{a as J,b as It}from"./chunk-Z5RGEDVQ.mjs";import{a as Dt,c as it}from"./chunk-AYCBSZ56.mjs";import{parentPort as j}from"worker_threads";import rt from"path";Et();import*as o from"fs";import*as x from"path";import*as f from"isomorphic-git";import{execFileSync as v}from"child_process";Y();import*as Q from"path";function ot(s){let t=W(s);return{root:t,historyGit:Q.join(t,"history.git"),workdir:Q.join(t,"workdir")}}function u(s,t){try{N.info(s,t)}catch{}}function at(s,t){try{N.warn(s,t)}catch{}}var B=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((r,i)=>r.path.localeCompare(i.path));let e=await f.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,"/"),r=n.split("/").filter(Boolean);if(!r.length)return;let i=r.slice(0,-1),c=r[r.length-1],h=this.currentDirs(),g=this.lcpLen(h,i);for(let p=h.length;p>g;p--)await this.flushTop();for(let p=g;p<i.length;p++){let w=i[p];if(this.stack[this.stack.length-1].fileNames.has(w))throw new Error(`Path conflict: file exists where directory expected: ${i.slice(0,p+1).join("/")}`);this.stack.push({name:w,entries:[],dirNames:new Set,fileNames:new Set})}let y=this.stack[this.stack.length-1];if(y.dirNames.has(c))throw new Error(`Path conflict: directory exists where file expected: ${n}`);y.entries.push({mode:"100644",path:c,oid:e,type:"blob"}),y.fileNames.add(c)}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)),f.writeTree({fs:o,dir:this.repoDir,tree:t.entries})}},F=class{constructor(t){this.baseDir=t.baseDir;let e=ot(t.shadowDir??t.baseDir);this.repoDir=x.join(e.root,"history")}async ensureInitialized(){o.mkdirSync(this.repoDir,{recursive:!0});let t=x.join(this.repoDir,".git");if(o.existsSync(t)){await this.ensureDefaultGitignore();return}let e=x.join(this.repoDir,".init.lock"),n=i=>new Promise(c=>setTimeout(c,i)),r=null;try{try{r=o.openSync(e,"wx"),o.writeFileSync(r,String(Date.now()))}catch{let i=Date.now(),c=3e4;for(;!o.existsSync(t);){try{let h=o.statSync(e);if(Date.now()-h.mtimeMs>c){try{o.unlinkSync(e)}catch{}break}}catch{}if(Date.now()-i>c)break;await n(200)}if(o.existsSync(t))return;r=o.openSync(e,"wx"),o.writeFileSync(r,String(Date.now()))}if(o.existsSync(t))return;u(`[${new Date().toISOString()}] [GitHistoryStore] Initializing history repo at ${this.repoDir}`),await f.init({fs:o,dir:this.repoDir}),u(`[${new Date().toISOString()}] [GitHistoryStore] git.init OK`),await f.setConfig({fs:o,dir:this.repoDir,path:"user.name",value:"ast-db"}),await f.setConfig({fs:o,dir:this.repoDir,path:"user.email",value:"ast-db@example.com"}),u(`[${new Date().toISOString()}] [GitHistoryStore] git config set (user.name/user.email)`),o.writeFileSync(x.join(this.repoDir,".gitignore"),`# ast history repo
|
|
2
|
+
`),u(`[${new Date().toISOString()}] [GitHistoryStore] wrote .gitignore`)}finally{try{r!=null&&o.closeSync(r)}catch{}try{o.existsSync(e)&&o.unlinkSync(e)}catch{}}await this.ensureDefaultGitignore()}async ensureDefaultGitignore(){let t=x.join(this.repoDir,".gitignore");if(!o.existsSync(t))try{o.mkdirSync(x.dirname(t),{recursive:!0}),o.writeFileSync(t,`# ast history repo
|
|
3
|
+
`,"utf8");try{await f.add({fs:o,dir:this.repoDir,filepath:".gitignore"})}catch{}u(`[GitHistoryStore] restored missing .gitignore at ${t}`)}catch(e){at(`[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 c=(typeof n=="string"?n.match(/^AST-Restore-Trace-Id:\s*(.+)$/m):null)?.[1]?.trim()||null,h=e;if(!h)try{h=v("git",["rev-parse","HEAD"],{cwd:this.repoDir,encoding:"utf8"}).trim()}catch{h=void 0}let g=new Map,y=Date.now();try{u("[GitHistoryStore] native snapshot start",{traceId:c,repoDir:this.repoDir,memberCount:t.length,parentOid:h||null})}catch{}for(let a=0;a<t.length;a++){let l=t[a];if(l.content==null)throw new Error(`Direct snapshot requires content for ${l.logicalPath}`);let S=Buffer.isBuffer(l.content)?l.content:Buffer.from(l.content),b=this.normalizeLogicalPath(l.logicalPath);if(!b)throw new Error("Direct snapshot requires non-empty logicalPath");let d=Date.now();try{u("[GitHistoryStore] native hash-object start",{traceId:c,repoDir:this.repoDir,index:a+1,total:t.length,logicalPath:b,bytes:S.length})}catch{}let T;try{T=v("git",["hash-object","-w","--stdin"],{cwd:this.repoDir,input:S}).toString("utf8").trim()}catch(D){try{at("[GitHistoryStore] native hash-object failed",{traceId:c,repoDir:this.repoDir,index:a+1,total:t.length,logicalPath:b,bytes:S.length,durationMs:Date.now()-d,message:D?.message||String(D),status:D?.status??null,signal:D?.signal??null,stdout:D?.stdout?String(D.stdout).slice(0,500):null,stderr:D?.stderr?String(D.stderr).slice(0,500):null})}catch{}throw D}let E=Date.now()-d;try{(E>1e3||a<3||a===t.length-1)&&u("[GitHistoryStore] native hash-object done",{traceId:c,repoDir:this.repoDir,index:a+1,total:t.length,logicalPath:b,bytes:S.length,durationMs:E,oid:T})}catch{}g.set(b,T)}try{u("[GitHistoryStore] native hash-object phase complete",{traceId:c,repoDir:this.repoDir,memberCount:t.length,durationMs:Date.now()-y})}catch{}let p=x.join(this.repoDir,`.pando-index-${process.pid}-${Date.now()}`),w={...process.env,GIT_INDEX_FILE:p};try{let a=Date.now();try{u("[GitHistoryStore] native read-tree begin",{traceId:c,repoDir:this.repoDir,tmpIndex:p})}catch{}v("git",["read-tree","--empty"],{cwd:this.repoDir,env:w});try{u("[GitHistoryStore] native read-tree complete",{traceId:c,repoDir:this.repoDir,durationMs:Date.now()-a})}catch{}let l=Array.from(g.keys()).sort((A,M)=>A.localeCompare(M)),S=Date.now();for(let A of l){let M=g.get(A);v("git",["update-index","--add","--cacheinfo","100644",M,A],{cwd:this.repoDir,env:w})}try{u("[GitHistoryStore] native update-index complete",{traceId:c,repoDir:this.repoDir,entryCount:l.length,durationMs:Date.now()-S})}catch{}let b=Date.now();try{u("[GitHistoryStore] native write-tree begin",{traceId:c,repoDir:this.repoDir,entryCount:l.length})}catch{}let d=v("git",["write-tree"],{cwd:this.repoDir,env:w}).toString("utf8").trim();try{u("[GitHistoryStore] native write-tree complete",{traceId:c,repoDir:this.repoDir,treeOid:d,durationMs:Date.now()-b})}catch{}let T=["commit-tree",d];h&&T.push("-p",h),n&&T.push("-m",n);let E=Date.now();try{u("[GitHistoryStore] native commit-tree begin",{traceId:c,repoDir:this.repoDir,treeOid:d,parentOid:h||null})}catch{}let D=v("git",T,{cwd:this.repoDir}).toString("utf8").trim();try{u("[GitHistoryStore] native commit-tree complete",{traceId:c,repoDir:this.repoDir,commitOid:D,durationMs:Date.now()-E})}catch{}let _=Date.now();try{u("[GitHistoryStore] native update-ref begin",{traceId:c,repoDir:this.repoDir,commitOid:D})}catch{}v("git",["update-ref","refs/heads/master",D],{cwd:this.repoDir});try{u("[GitHistoryStore] native update-ref complete",{traceId:c,repoDir:this.repoDir,commitOid:D,durationMs:Date.now()-_})}catch{}return{snapshotId:D,parent:h}}finally{try{o.unlinkSync(p)}catch{}try{o.unlinkSync(`${p}.lock`)}catch{}}}async readObject(t){let{object:e}=await f.readObject({fs:o,dir:this.repoDir,oid:t});return Buffer.from(e)}async hasObject(t){try{return await f.readObject({fs:o,dir:this.repoDir,oid:t}),!0}catch{return!1}}async createSnapshot(t,e){R(e,"Snapshot cancelled"),await this.ensureInitialized(),u(`[${new Date().toISOString()}] [GitHistoryStore] Creating snapshot (streaming) with ${t.members.length} members`);let n=[...t.members].map(m=>({...m,logicalPath:this.normalizeLogicalPath(m.logicalPath)})).filter(m=>!!m.logicalPath).sort((m,I)=>m.logicalPath.localeCompare(I.logicalPath)),r=this.gitExists()&&!e;try{r?N.info("[GitHistoryStore] Using native git snapshot path",{members:n.length}):N.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(m){try{N.warn(`[GitHistoryStore] Native git path failed; falling back to JS path: ${m?.message||m}`)}catch{}}let i=Date.now(),c=m=>m.toString("hex"),h=m=>Dt("crypto").createHash("sha1").update(m).digest(),g=m=>{let I=Buffer.from(`blob ${m.length}\0`,"utf8"),C=Buffer.concat([I,m]);return c(h(C))},y=Math.max(1,Math.min(64,Number(process.env.SNAPSHOT_BLOB_CONCURRENCY||16))),p=String(process.env.SNAPSHOT_PRECOMPUTE_OIDS||"1")!=="0";try{N.info("[GitHistoryStore] JS snapshot settings",{SNAPSHOT_BLOB_CONCURRENCY:y,SNAPSHOT_PRECOMPUTE_OIDS:p})}catch{}let w=new Map,a=0,l=0,S=0,b=n.map(m=>({path:m.logicalPath,buf:Buffer.isBuffer(m.content)?m.content:Buffer.from(m.content)})),d=async()=>{for(;;){R(e,"Snapshot cancelled");let m;if(a<b.length)m=b[a++];else break;let I;if(p)try{let C=g(m.buf);await this.hasObject(C)&&(I=C,S++)}catch{}if(I||(I=await f.writeBlob({fs:o,dir:this.repoDir,blob:m.buf}),l++),R(e,"Snapshot cancelled"),!I)throw new Error("Failed to compute blob object id");w.set(m.path,I)}},T=Array.from({length:Math.min(y,b.length)},()=>d());await Promise.all(T),R(e,"Snapshot cancelled"),u(`[GitHistoryStore] Blobs ready wrote=${l} skipped=${S} in ${Date.now()-i}ms`);let E=new B(this.repoDir),D=Array.from(w.keys()).sort((m,I)=>m.localeCompare(I));for(let m of D)R(e,"Snapshot cancelled"),await E.addFile(m,w.get(m));R(e,"Snapshot cancelled");let _=Date.now(),A=await E.finish();u(`[GitHistoryStore] Wrote tree(s). root=${A} in ${Date.now()-_}ms`);let M=t.parent;if(!M)try{M=await f.resolveRef({fs:o,dir:this.repoDir,ref:"HEAD"})}catch{}R(e,"Snapshot cancelled");let H=t.when?Math.floor(t.when/1e3):Math.floor(Date.now()/1e3),L=new Date(H*1e3).getTimezoneOffset(),$=await f.commit({fs:o,dir:this.repoDir,message:t.message,parent:M?[M]:[],tree:A,author:{name:"ast-db",email:"ast-db@example.com",timestamp:H,timezoneOffset:L},committer:{name:"ast-db",email:"ast-db@example.com",timestamp:H,timezoneOffset:L}});return await f.writeRef({fs:o,dir:this.repoDir,ref:"refs/heads/master",value:$,force:!0}),u(`[GitHistoryStore] Snapshot commit oid ${$}`),$}async listSnapshotMembers(t){await this.ensureInitialized();let e=i=>Math.round((i||0)/(1024*1024)),n=()=>{let i=process.memoryUsage();return`rss=${e(i.rss)}MB heapUsed=${e(i.heapUsed)}MB heapTotal=${e(i.heapTotal)}MB`},r=[];return u(`[${new Date().toISOString()}] [GitHistoryStore] listSnapshotMembers(${t}) start (${n()})`),await f.walk({fs:o,dir:this.repoDir,trees:[f.TREE({ref:t})],map:async(i,[c])=>{if(!c)return;if(await c.type()==="blob"){let g=await c.oid();r.push({logicalPath:i,objectId:g})}}}),u(`[${new Date().toISOString()}] [GitHistoryStore] listSnapshotMembers(${t}) -> ${r.length} blobs`),r.filter(i=>i.logicalPath&&i.logicalPath!==".").map(i=>({logicalPath:i.logicalPath.replace(/^\.\//,""),objectId:i.objectId}))}async readCommit(t){let{commit:e}=await f.readCommit({fs:o,dir:this.repoDir,oid:t});return{message:e.message,committer:e.committer}}async readCommitParent(t){let{commit:e}=await f.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){await this.ensureInitialized(),u(`[${new Date().toISOString()}] [GitHistoryStore] Creating snapshot from disk (streaming) with ${t.relPaths.length} members`);let e=[...t.relPaths].map(a=>this.normalizeLogicalPath(a)).filter(Boolean).sort((a,l)=>a.localeCompare(l)),n=Date.now(),r=new B(this.repoDir),i=0;for(let a of e){let l=x.join(this.baseDir,a);try{let S=o.readFileSync(l),b=await f.writeBlob({fs:o,dir:this.repoDir,blob:S});await r.addFile(a,b),i++}catch{}}u(`[GitHistoryStore] Wrote ${i} blobs (disk) in ${Date.now()-n}ms`);let c=Date.now(),h=await r.finish();u(`[GitHistoryStore] Wrote tree(s) (disk). root=${h} in ${Date.now()-c}ms`);let g;try{g=await f.resolveRef({fs:o,dir:this.repoDir,ref:"HEAD"})}catch{}let y=t.when?Math.floor(t.when/1e3):Math.floor(Date.now()/1e3),p=new Date(y*1e3).getTimezoneOffset(),w=await f.commit({fs:o,dir:this.repoDir,message:t.message,parent:g?[g]:[],tree:h,author:{name:"ast-db",email:"ast-db@example.com",timestamp:y,timezoneOffset:p},committer:{name:"ast-db",email:"ast-db@example.com",timestamp:y,timezoneOffset:p}});return u(`[GitHistoryStore] Snapshot commit oid ${w}`),w}async createSnapshotFromDiskIfChanged(t){await this.ensureInitialized(),u(`[${new Date().toISOString()}] [GitHistoryStore] Creating snapshot from disk (diff) with ${t.relPaths.length} members`);let e=[...t.relPaths].map(a=>this.normalizeLogicalPath(a)).filter(Boolean).sort((a,l)=>a.localeCompare(l)),n=Date.now(),r=new B(this.repoDir),i=0;for(let a of e){let l=x.join(this.baseDir,a);try{let S=o.readFileSync(l),b=await f.writeBlob({fs:o,dir:this.repoDir,blob:S});await r.addFile(a,b),i++}catch{}}u(`[GitHistoryStore] Wrote ${i} blobs (disk) in ${Date.now()-n}ms`);let c=Date.now(),h=await r.finish();u(`[GitHistoryStore] Wrote tree(s) (disk). root=${h} in ${Date.now()-c}ms`);let g=t.parent;if(!g)try{g=await f.resolveRef({fs:o,dir:this.repoDir,ref:"HEAD"})}catch{}if(g)try{let{commit:a}=await f.readCommit({fs:o,dir:this.repoDir,oid:g});if(a?.tree===h){u("[GitHistoryStore] Snapshot identical to parent; skipping commit",{parentOid:g,tree:h});let l=await this.readCommitParent(g);return{snapshotId:g,identical:!0,parent:l}}}catch(a){u("[GitHistoryStore] Parent read failed; proceeding with commit",{error:a?.message||String(a)})}let y=t.when?Math.floor(t.when/1e3):Math.floor(Date.now()/1e3),p=new Date(y*1e3).getTimezoneOffset(),w=await f.commit({fs:o,dir:this.repoDir,message:t.message,parent:g?[g]:[],tree:h,author:{name:"ast-db",email:"ast-db@example.com",timestamp:y,timezoneOffset:p},committer:{name:"ast-db",email:"ast-db@example.com",timestamp:y,timezoneOffset:p}});return await f.writeRef({fs:o,dir:this.repoDir,ref:"refs/heads/master",value:w,force:!0}),u(`[GitHistoryStore] Snapshot commit oid ${w}`),{snapshotId:w,identical:!1,parent:g}}};function Z(s){let t={},e=s.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}Tt();import Pt from"fs";import G from"path";import ct from"ignore";import{Project as Wt}from"ts-morph";var xt=new Set(["node_modules",".git",".pando-data"]);function ht(s,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 i=n(G.relative(s,r));if(!i||i.startsWith(".."))return!1;let c=i.endsWith("/")?i:`${i}/`;return e.some(h=>c.startsWith(h))}}function pt(s,t,e){let n=e?.shouldExclude||null,r=[],i=new Set(Array.from(t,p=>p.toLowerCase())),c=G.resolve(e?.gitignoreRoot??s),h=K(c,""),g=ct().add(h),y=[{dir:s,relDir:"",rules:h,ig:g}];for(;y.length;){let p=y.pop(),w=[];try{w=Pt.readdirSync(p.dir,{withFileTypes:!0})}catch{continue}for(let a of w){let l=G.join(p.dir,a.name);if(!(typeof a.isSymbolicLink=="function"&&a.isSymbolicLink())){if(a.isDirectory()){if(xt.has(a.name)||n?.(l))continue;let b=p.relDir?`${p.relDir}/${a.name}`:a.name,d=lt(b);if(p.ig.ignores(d))continue;let T=p.rules.slice(),E=K(l,d);E.length&&T.push(...E);let D=E.length?ct().add(T):p.ig;y.push({dir:l,relDir:d,rules:T,ig:D})}else if(a.isFile()){if(n?.(l))continue;let b=lt(G.relative(s,l));if(p.ig.ignores(b))continue;let d=G.extname(a.name).toLowerCase();i.has(d)&&r.push(l)}}}}return r}function lt(s){return s.replace(/\\/g,"/")}Y();It();Y();import q from"fs";import Mt from"path";function dt(s){s.pragma("journal_mode = WAL"),s.pragma("synchronous = NORMAL"),s.pragma("busy_timeout = 10000");try{s.pragma("temp_store = MEMORY")}catch{}s.exec(`
|
|
4
4
|
CREATE TABLE IF NOT EXISTS objects (
|
|
5
5
|
object_id TEXT PRIMARY KEY,
|
|
6
6
|
kind TEXT DEFAULT 'blob',
|
|
@@ -38,4 +38,4 @@ import{a as N,b as wt,d as W,e as nt,f as Y,g as k,m as V,n as v}from"./chunk-QO
|
|
|
38
38
|
|
|
39
39
|
CREATE INDEX IF NOT EXISTS idx_snapshots_timestamp ON snapshots(timestamp);
|
|
40
40
|
CREATE INDEX IF NOT EXISTS idx_snapshot_meta_kv ON snapshot_meta(key, value);
|
|
41
|
-
`)}function tt(s,t){let e=nt(s),n=
|
|
41
|
+
`)}function tt(s,t){let e=nt(s),n=Mt.dirname(e);q.existsSync(n)||q.mkdirSync(n,{recursive:!0});let r=!!t?.readonly;if(r&&!q.existsSync(e)){let c=new J(e,{});try{dt(c)}finally{try{c.close()}catch{}}}let i=new J(e,r?{readonly:!0}:{});if(!r)dt(i);else try{i.pragma("busy_timeout = 10000")}catch{}return i}var O="",et=[],St=null;it();function gt(s,t){if(Array.isArray(t)){et=t.slice(),St=ht(s,et);try{k("SnapshotWorker","exclude state updated",{excludeDirs:et})}catch{}}}function Ot(s){let t=V(),e=pt(s,t,{shouldExclude:St??void 0,gitignoreRoot:s});try{k("SnapshotWorker","gatherIndexableFiles",{count:e.length,sample:e.slice(0,20).map(n=>rt.relative(s,n).replace(/\\/g,"/"))})}catch{}return e}function mt(s){try{return s.prepare("SELECT snapshot_id FROM snapshots ORDER BY timestamp DESC, rowid DESC LIMIT 1").get()?.snapshot_id}catch{return}}function ft(s,t,e,n,r){let i=r||null;s.prepare("INSERT OR REPLACE INTO snapshots (snapshot_id, parents, timestamp, message) VALUES (?, ?, ?, ?)").run(t,i,Math.floor(e/1e3),n)}async function ut(s,t,e){try{return await s.readCommitParent(t)||e}catch{return e}}function z(s,t){let e=new Map;try{let n=s.prepare("SELECT logical_path, object_id FROM snapshot_members WHERE snapshot_id = ?").all(t);for(let r of n)e.set(r.logical_path,r.object_id)}catch{}return e}function yt(s,t,e){s.transaction(r=>{let i=s.prepare("INSERT OR REPLACE INTO snapshot_members (snapshot_id, logical_path, object_id, lang, encoding) VALUES (?, ?, ?, ?, ?)");for(let c of r)i.run(t,c.logical_path,c.object_id,c.lang??null,c.encoding??null)})(e)}j.on("message",async s=>{if(s.cmd==="init"){O=s.projectRoot,gt(O,s.excludeDirs),j.postMessage({type:"ready"});return}if(s.excludeDirs&>(O,s.excludeDirs),s.cmd==="snapshot"){let t=tt(O);try{let e=Date.now(),n=s.payload?.when||Date.now(),r=s.payload?.message||"ast: snapshot",i=s.payload?.parent||mt(t),c=Date.now(),h=s.payload?.files&&s.payload.files.length?s.payload.files:Ot(O);try{k("SnapshotWorker","snapshot start",{when:n,message:r,parent:i,fileCount:h.length,filesPreview:h.slice(0,50).map(d=>rt.relative(O,d).replace(/\\/g,"/"))})}catch{}let g=Date.now()-c,y=h.map(d=>rt.relative(O,d).replace(/\\/g,"/")),p=new F({baseDir:O});await p.ensureInitialized();let w=Date.now(),a=await p.createSnapshotFromDiskIfChanged({message:r,when:n,relPaths:y,parent:i}),l=a.snapshotId,S=await ut(p,l,a.parent||i),b=Date.now()-w;if(a.identical){let d=Date.now()-e;try{k("SnapshotWorker","snapshot skipped (identical)",{snapshotId:l,parent:S,files:y.length,timingsMs:{list:g,snapshot:b,total:d}})}catch{}j.postMessage({type:"result",snapshotId:l,parent:S,files:y.length,diff:{added:0,changed:0,deleted:0}})}else{let d=Date.now();ft(t,l,n,r,S);try{let P=Z(r||""),X=t.prepare("INSERT OR REPLACE INTO snapshot_meta (snapshot_id, key, value) VALUES (?, ?, ?)");t.transaction(()=>{for(let[bt,wt]of Object.entries(P))X.run(l,bt,wt)})()}catch{}let T=Date.now()-d,E=Date.now(),D=await p.listSnapshotMembers(l),_=Date.now()-E,A=D.map(P=>({logical_path:P.logicalPath,object_id:P.objectId})),M=Date.now();yt(t,l,A);let H=Date.now()-M,L=S?z(t,S):new Map,$=z(t,l),m=[],I=[],C=[];for(let[P,X]of $){let U=L.get(P);U?U!==X&&I.push(P):m.push(P)}for(let[P]of L)$.has(P)||C.push(P);let st=Date.now()-e;try{k("SnapshotWorker","snapshot complete",{snapshotId:l,parent:S,files:y.length,timingsMs:{list:g,snapshot:b,metadata:T,listMembers:_,membersWrite:H,total:st},diff:{added:m.length,changed:I.length,deleted:C.length}})}catch{}j.postMessage({type:"result",snapshotId:l,parent:S,files:y.length,diff:{added:m.length,changed:I.length,deleted:C.length}})}}catch(e){j.postMessage({type:"error",message:e?.message||String(e)})}finally{t.close()}return}if(s.cmd==="snapshot-captured"){let t=tt(O);try{let e=s.payload?.when||Date.now(),n=s.payload?.message||"ast: snapshot",r=s.payload?.parent||mt(t);try{k("SnapshotWorker","snapshot-captured start",{when:e,message:n,parent:r,members:s.payload.members.length})}catch{}let i=new F({baseDir:O});await i.ensureInitialized();let c=(s.payload.members||[]).map(d=>({logicalPath:d.logicalPath,objectId:"unknown",content:Buffer.from(d.contentB64,"base64")})),h=await i.createSnapshot({message:n,when:e,members:c}),g=await ut(i,h,r);ft(t,h,e,n,g);try{let d=Z(n||""),T=t.prepare("INSERT OR REPLACE INTO snapshot_meta (snapshot_id, key, value) VALUES (?, ?, ?)");t.transaction(()=>{for(let[D,_]of Object.entries(d))T.run(h,D,_)})()}catch{}let y=await i.listSnapshotMembers(h),p=y.map(d=>({logical_path:d.logicalPath,object_id:d.objectId}));yt(t,h,p);let w=g?z(t,g):new Map,a=z(t,h),l=[],S=[],b=[];for(let[d,T]of a){let E=w.get(d);E?E!==T&&S.push(d):l.push(d)}for(let[d]of w)a.has(d)||b.push(d);try{k("SnapshotWorker","snapshot-captured complete",{snapshotId:h,parent:g,members:y.length,diff:{added:l.length,changed:S.length,deleted:b.length}})}catch{}j.postMessage({type:"result",snapshotId:h,parent:g,files:y.length,diff:{added:l.length,changed:S.length,deleted:b.length}})}catch(e){j.postMessage({type:"error",message:e?.message||String(e)})}finally{t.close()}}s.cmd==="close"&&j.postMessage({type:"closed"})});
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import{
|
|
1
|
+
import{d as Ne,e as ne,f as Be,g as k}from"./chunk-HQDE7M4W.mjs";import{a as ie,b as Ge}from"./chunk-Z5RGEDVQ.mjs";import{c as Re}from"./chunk-AYCBSZ56.mjs";Ge();import{parentPort as A,threadId as Me}from"worker_threads";import K from"path";import de from"fs";import Pe from"os";function Ye(e){e.exec(`
|
|
2
2
|
PRAGMA journal_mode=WAL;
|
|
3
3
|
PRAGMA synchronous=OFF;
|
|
4
4
|
PRAGMA temp_store=MEMORY;
|
|
5
5
|
PRAGMA busy_timeout=5000;
|
|
6
|
-
`);try{let
|
|
6
|
+
`);try{let n=Pe.totalmem(),t=Math.min(Math.floor(n*.5),30*1024*1024*1024),r=Math.min(Math.floor(n/1024*.1),4*1024*1024);e.pragma(`mmap_size = ${t}`),e.pragma(`cache_size = -${r}`),e.pragma("wal_autocheckpoint = 10000")}catch{}}function pe(e){Ye(e),e.exec(`
|
|
7
7
|
CREATE TABLE IF NOT EXISTS dict_kinds (
|
|
8
8
|
id INTEGER PRIMARY KEY,
|
|
9
9
|
text TEXT UNIQUE
|
|
@@ -240,15 +240,13 @@ import{a as M}from"./chunk-2YGY7BLN.mjs";import{a as re,b as We}from"./chunk-Z5R
|
|
|
240
240
|
CREATE INDEX IF NOT EXISTS idx_resolver_cache_symbol ON resolver_cache(symbol_id);
|
|
241
241
|
CREATE INDEX IF NOT EXISTS idx_resolver_cache_file ON resolver_cache(file_path);
|
|
242
242
|
|
|
243
|
-
`);let r=new Map,t=s=>{let l=r.get(s);if(l)return l;try{let a=e.prepare(`PRAGMA table_info(${s})`).all(),E=new Set(a.map(N=>N.name));return r.set(s,E),E}catch{let a=new Set;return r.set(s,a),a}},n=(s,l,a)=>{let E=t(s);E.has(l)||(e.exec(a),E.add(l))};n("files","lang","ALTER TABLE files ADD COLUMN lang TEXT"),n("nodes","lang","ALTER TABLE nodes ADD COLUMN lang TEXT"),n("nodes","semantic_kind_id","ALTER TABLE nodes ADD COLUMN semantic_kind_id INTEGER"),n("nodes","raw_kind","ALTER TABLE nodes ADD COLUMN raw_kind TEXT"),n("nodes","raw_kind_source","ALTER TABLE nodes ADD COLUMN raw_kind_source TEXT"),n("nodes","container_kind_id","ALTER TABLE nodes ADD COLUMN container_kind_id INTEGER"),n("nodes","container_raw_kind","ALTER TABLE nodes ADD COLUMN container_raw_kind TEXT"),n("nodes","container_raw_kind_source","ALTER TABLE nodes ADD COLUMN container_raw_kind_source TEXT"),n("nodes","qualified_name","ALTER TABLE nodes ADD COLUMN qualified_name TEXT"),n("nodes","scope_chain","ALTER TABLE nodes ADD COLUMN scope_chain TEXT"),n("nodes","symbol_key","ALTER TABLE nodes ADD COLUMN symbol_key TEXT"),e.exec("CREATE INDEX IF NOT EXISTS idx_nodes_symbol_key ON nodes(symbol_key)"),n("exports","lang","ALTER TABLE exports ADD COLUMN lang TEXT"),n("exports","target_symbol_key","ALTER TABLE exports ADD COLUMN target_symbol_key TEXT"),e.exec("CREATE INDEX IF NOT EXISTS idx_exports_target_symbol_key ON exports(target_symbol_key)"),n("node_references","lang","ALTER TABLE node_references ADD COLUMN lang TEXT"),n("node_references","receiver_name","ALTER TABLE node_references ADD COLUMN receiver_name TEXT"),n("node_references","arity","ALTER TABLE node_references ADD COLUMN arity INTEGER"),n("node_references","container_qualified_name","ALTER TABLE node_references ADD COLUMN container_qualified_name TEXT"),n("node_references","target_symbol_key","ALTER TABLE node_references ADD COLUMN target_symbol_key TEXT"),n("node_references","confidence","ALTER TABLE node_references ADD COLUMN confidence TEXT"),n("file_imports","lang","ALTER TABLE file_imports ADD COLUMN lang TEXT"),n("file_import_bindings","lang","ALTER TABLE file_import_bindings ADD COLUMN lang TEXT"),n("blobs_nodes","lang","ALTER TABLE blobs_nodes ADD COLUMN lang TEXT"),n("blobs_nodes","semantic_kind_id","ALTER TABLE blobs_nodes ADD COLUMN semantic_kind_id INTEGER"),n("blobs_nodes","raw_kind","ALTER TABLE blobs_nodes ADD COLUMN raw_kind TEXT"),n("blobs_nodes","raw_kind_source","ALTER TABLE blobs_nodes ADD COLUMN raw_kind_source TEXT"),n("blobs_symbols","lang","ALTER TABLE blobs_symbols ADD COLUMN lang TEXT"),n("blobs_rels","lang","ALTER TABLE blobs_rels ADD COLUMN lang TEXT"),n("blobs_rels","import_specifiers","ALTER TABLE blobs_rels ADD COLUMN import_specifiers TEXT")}var he=Number(process.env.PANDO_SQLITE_RETRY_MIN_MS||"100"),Me=Number(process.env.PANDO_SQLITE_RETRY_MAX_MS||"500"),Re=Math.max(0,Number(process.env.PANDO_SQLITE_RETRY_ATTEMPTS||"5")),oe=e=>{if(e==null)return!1;let r=e.trim().toLowerCase();return r!=="0"&&r!=="false"&&r!=="off"&&r!=="no"},Y=oe(process.env.PANDO_SQLITE_WRITER_DEBUG)||oe(process.env.PANDO_INDEX_TRACE);if(!b)throw new Error("SQLite writer worker must be spawned as a worker thread");Ie();function u(...e){process.env.PANDO_QUIET||console.log(`[${new Date().toISOString()}]`,...e)}function Ge(e){if(oe(process.env.PANDO_INDEX_TRACE))try{let r=`[${new Date().toISOString()}] [writer-thread:${Pe}] ${e}
|
|
244
|
-
`;H.appendFileSync(y.join(we.tmpdir(),"pando-writer-trace.log"),r)}catch{}}function pe(e){try{let r=`${JSON.stringify({ts:new Date().toISOString(),...e})}
|
|
245
|
-
`;H.appendFileSync(y.join(we.tmpdir(),"pando-clj-source-node.log"),r)}catch{}}var X=null,ge=null;function Ye(){ge||(ge=setInterval(()=>{if(!X)return;let e=Date.now()-X.startedAt;e>5e3&&u("[WriterWorker] op still running",{cmd:X.cmd,id:X.id,ms:e,fileRel:X.fileRel})},2e3))}function F(e,r,t){X={cmd:e,id:r,startedAt:Date.now(),fileRel:t},Ye()}function p(){X=null}var C=()=>({writeMs:0,writeTrackedMs:0,writePreDeleteMs:0,writeInsertExportsMs:0,writeInsertNodesMs:0,writeInsertReferencesMs:0,writeInsertImportsMs:0,writeInsertImportBindingsMs:0,writeInsertFileMs:0,writeFinalizeMs:0,writeInsertFtsMs:0,writeResidualMs:0}),P=Math.max(0,Math.min(he,Me)),Se=Math.max(P,Math.max(he,Me)),ve=e=>new Promise(r=>setTimeout(r,e));function be(e){if(!e)return!1;let r=e.code,t=e.errcode;if(r==="ERR_SQLITE_BUSY"||r==="SQLITE_BUSY"||r==="ERR_SQLITE_ERROR"&&t===5)return!0;let n=e?.message??String(e);return typeof n=="string"&&n.toLowerCase().includes("database is locked")}function Ke(){if(Se<=P)return P;let e=Se-P;return P+Math.floor(Math.random()*(e+1))}async function ie(e,r){let t=0,n=Date.now();for(;;)try{let s=e();return Y&&t>0&&u(`[WriterWorker] ${r} recovered after retry`,{attempts:t,ms:Date.now()-n}),s}catch(s){if(!be(s)||t>=Re)throw u(`[WriterWorker] ${r} failed`,{attempts:t,ms:Date.now()-n,error:s?.message??String(s),locked:be(s)}),s;t+=1;let l=Ke();u(`[WriterWorker] ${r} retry ${t}/${Re} after locked database; waiting ${l}ms`),await ve(l)}}var L=null,j=null,de=null,ce=null,_e=null,Te=null,fe=null,x=null,U=null,A=null,w=null,Q=null,V=null,G=new Map,D=new Map,v=new Map,le=new Map,ae=Math.max(1e4,Number(process.env.PANDO_DICT_CACHE_MAX_ENTRIES||"200000")),He=Math.max(64,Number(process.env.PANDO_DICT_CACHE_MAX_KEY_LENGTH||"1024")),Ae=Math.floor(ae*.7),z=0,$=null,O=null,K=null,J=null,Z=null,ee=null,Ee,W=null,q=!1;function te(){if(!L)throw new Error("writer not initialized");return L}function ze(e){j||(j=e.prepare("DELETE FROM nodes WHERE file_id = ?"),de=e.prepare("DELETE FROM exports WHERE file_id = ?"),ce=e.prepare("DELETE FROM files WHERE file_id = ?"),_e=e.prepare("DELETE FROM file_imports WHERE file_id = ?"),Te=e.prepare("DELETE FROM file_import_bindings WHERE file_id = ?"),fe=e.prepare("DELETE FROM node_references WHERE file_id = ?"))}function me(e){x||(x=e.prepare("INSERT OR IGNORE INTO dict_kinds (text) VALUES (?)"),U=e.prepare("SELECT id FROM dict_kinds WHERE text = ?")),A||(A=e.prepare("INSERT OR IGNORE INTO dict_symbols (text) VALUES (?)"),w=e.prepare("SELECT id FROM dict_symbols WHERE text = ?")),Q||(Q=e.prepare("INSERT OR IGNORE INTO dict_files (path) VALUES (?)"),V=e.prepare("SELECT id FROM dict_files WHERE path = ?"))}function S(e,r,t,n,s){if(!s)return null;let l=s.length<=He,a=l?r.get(s):void 0;if(a!=null)return a;t.run(s);let E=n.get(s);if(!E||typeof E.id!="number")return null;if(l){if(r.size>=ae){let N=0;for(let g of r.keys())if(r.delete(g),N+=1,r.size<=Ae)break;z+=1,(z<=10||z%25===0)&&u("[WriterWorker] dictionary cache trimmed",{trimCount:z,removed:N,maxEntries:ae,targetAfterTrim:Ae,cacheSizeAfter:r.size})}r.set(s,E.id)}return E.id}function Le(e,r){me(e);let t=v.get(r);if(t!=null)return t;Q.run(r);let n=V.get(r);if(!n||typeof n.id!="number")throw new Error(`Failed to resolve file id for ${r}`);return v.set(r,n.id),n.id}function $e(e,r){me(e);let t=v.get(r);if(t!=null)return t;let n=V.get(r);return!n||typeof n.id!="number"?null:(v.set(r,n.id),n.id)}function De(e,r){let t=r?.journal_mode||"WAL";e.pragma(`journal_mode=${t}`),e.pragma("synchronous=OFF"),e.pragma("temp_store=MEMORY"),e.pragma("cache_size=-20000"),e.pragma("mmap_size=268435456"),e.pragma("journal_size_limit=134217728"),e.pragma("wal_autocheckpoint=1000"),e.pragma("busy_timeout=5000")}function se(e){try{return H.statSync(e).size}catch{return null}}function B(e){if(!W)return;let r=`${W}-wal`,t=`${W}-shm`,n=se(W),s=se(r),l=se(t);u("[WriterWorker] db sizes",{reason:e,dbPath:W,dbSize:n,walSize:s,shmSize:l})}function je(e){let r=y.dirname(e),t=y.basename(e),n=t.replace(".pando-index-chunk-",".pando-fts-chunk-");return y.join(r,n===t?`${t}.fts`:n)}function ke(){if(!$)throw new Error("FTS database path not configured");if(!O){try{H.mkdirSync(y.dirname($),{recursive:!0})}catch{}O=new re($),De(O,Ee)}return O}function Qe(e){K||(e.exec("CREATE VIRTUAL TABLE IF NOT EXISTS blob_content_fts USING fts5(blob_oid UNINDEXED, content)"),e.exec("CREATE TABLE IF NOT EXISTS blob_fts_presence (blob_oid TEXT PRIMARY KEY)"),K=e.prepare("SELECT 1 FROM blob_fts_presence WHERE blob_oid = ?"),J=e.prepare("INSERT INTO blob_content_fts (blob_oid, content) VALUES (?, ?)"),Z=e.prepare("INSERT OR REPLACE INTO blob_fts_presence (blob_oid) VALUES (?)"),ee=e.prepare("DELETE FROM blob_content_fts WHERE blob_oid = ?"))}function qe(e,r){if(!e||typeof e.blobOid!="string"||e.blobOid.length===0)return;let t=ke();Qe(t);let n=Date.now();r?.inTransaction||t.exec("BEGIN");try{K.get(e.blobOid)&&ee.run(e.blobOid),J.run(e.blobOid,e.content??""),Z.run(e.blobOid),r?.inTransaction||t.exec("COMMIT")}catch(l){if(!r?.inTransaction)try{t.exec("ROLLBACK")}catch(a){console.log("[WriterWorker] rollback failed:",a?.message??a)}throw l}let s=Date.now()-n;s>2e3&&u("[WriterWorker] slow fts insert",{blobOid:e.blobOid,ms:s,contentBytes:e.content?e.content.length:0})}function Ve(e,r,t,n){let s=`${r}|${t}|${n}`,l=le.get(s);if(!l){let a=Array.from({length:n},()=>`(${new Array(t).fill("?").join(",")})`).join(","),E=`${r} VALUES ${a}`;l=e.prepare(E),le.set(s,l)}return l}function k(e,r,t,n){if(!n.length||t<=0)return;let s=Date.now(),l=Math.max(1,Math.floor(999/t));for(let E=0;E<n.length;E+=l){let N=n.slice(E,E+l);if(!N.length)continue;let g=Ve(e,r,t,N.length),_=[];for(let d of N)_.push(...d);let o=Date.now();g.run(..._);let f=Date.now()-o;f>500&&u("[WriterWorker] slow insert chunk",{sqlPrefix:r,columnCount:t,rows:N.length,ms:f})}let a=Date.now()-s;a>2e3&&u("[WriterWorker] slow insertRows",{sqlPrefix:r,columnCount:t,rows:n.length,ms:a})}function Xe(e,r){ze(e);let t=$e(e,r);t!=null&&(j.run(t),de.run(t),ce.run(t),_e.run(t),Te.run(t),fe.run(t))}function Je(e){if(!e.length)return C();let r=te(),t=C(),n=Date.now();r.exec("BEGIN");try{for(let s of e)Xe(r,s);r.exec("COMMIT")}catch(s){try{r.exec("ROLLBACK")}catch(l){console.log("[WriterWorker] rollback failed:",l?.message??l)}throw s}return t.writePreDeleteMs=Date.now()-n,t.writeTrackedMs=t.writePreDeleteMs,t.writeMs=t.writePreDeleteMs,t}function xe(e,r){let t=te();me(t);let n=C(),s=Date.now(),l=Le(t,e.fileRel),a={exports:e.exportRows.length,nodes:e.nodeRows.length,refs:e.referenceRows.length,imports:e.importRows.length,importBindings:e.importBindingRows.length,fileRow:e.fileRow?1:0,fts:e.fts?1:0},E=a.exports+a.nodes+a.refs+a.imports+a.importBindings;r?.inTransaction||t.exec("BEGIN");try{if(t.exec("SAVEPOINT idx_file"),!e.preDeleted){let _=Date.now();Xe(t,e.fileRel),n.writePreDeleteMs+=Date.now()-_}let N=(_,o,f,d)=>{let i=Date.now();Y&&u("[WriterWorker] section begin",{file:e.fileRel,label:o,count:f});let I=Date.now();d();let c=Date.now()-I;n[_]+=c,Y&&u("[WriterWorker] section end",{file:e.fileRel,label:o,count:f,ms:c,elapsedSinceWriteStartMs:Date.now()-i}),c>2e3&&u("[WriterWorker] section slow",{file:e.fileRel,label:o,count:f,ms:c})};N("writeInsertExportsMs","exports",e.exportRows.length,()=>{let _=e.exportRows.map(d=>[l,e.lang,S(t,D,A,w,d[1]),M(d[2]),d[3],d[4]??null,S(t,D,A,w,d[5]),d[6]??null,d[7]??null]),o=[],f=new Map;for(let d of _){let i=d[2];i!=null&&(f.has(i)||(f.set(i,d),o.push(d)))}o.length!==_.length&&console.log("[WriterWorker] export rows deduped",{file:e.fileRel,lang:e.lang,before:_.length,after:o.length});try{k(t,"INSERT OR REPLACE INTO exports (file_id, lang, export_name_id, node_id, is_reexport, reexport_from, reexport_name_id, export_kind, target_symbol_key)",9,o)}catch(d){try{let i=new Map;for(let c of _){let T=c[2];T!=null&&i.set(T,(i.get(T)??0)+1)}let I=Array.from(i.entries()).filter(([,c])=>c>1);if(I.length){let c=t.prepare("SELECT text FROM dict_symbols WHERE id = ?"),T=I.map(([m,ne])=>{let Ce=c.get(m)?.text??null,Fe=_.filter(h=>h[2]===m).map(h=>({node_id:h[3],is_reexport:h[4],reexport_from:h[5],reexport_name_id:h[6],export_kind:h[7],target_symbol_key:h[8]}));return{id:m,count:ne,name:Ce,rows:Fe}});console.log("[WriterWorker] export duplicates detected",{file:e.fileRel,lang:e.lang,totalExports:_.length,duplicates:T});let R=_.map(m=>{let ne=m[2]!=null?c.get(m[2]):void 0,ue=m[6]?c.get(m[6]):void 0;return{name_id:m[2],name:ne?.text??null,node_id:m[3],is_reexport:m[4],reexport_from:m[5],reexport_name_id:m[6],reexport_name:ue?.text??null,export_kind:m[7],target_symbol_key:m[8]}});console.log("[WriterWorker] export rows dump",{file:e.fileRel,lang:e.lang,rows:R})}}catch(i){console.log("[WriterWorker] failed to compute export duplicates",i?.message??i)}throw console.log("[WriterWorker] export insert failed",{file:e.fileRel,lang:e.lang,exportCount:o.length,error:d?.message??d}),d}}),N("writeInsertNodesMs","nodes",e.nodeRows.length,()=>{for(let o of e.nodeRows){let f=o[2],d=o[3],i=o[4];if(!f||!String(f).trim())throw new Error(`[WriterWorker] Missing normalized kind for node in ${e.fileRel}`);if(!d||!String(d).trim())throw new Error(`[WriterWorker] Missing raw kind for node in ${e.fileRel}`);if(!i||!String(i).trim())throw new Error(`[WriterWorker] Missing raw kind source for node in ${e.fileRel}`)}let _=e.nodeRows.map(o=>[M(o[0]),l,e.lang,S(t,D,A,w,o[1]),S(t,G,x,U,o[2]),o[3],o[4],S(t,G,x,U,o[5]),o[6],o[7],o[8],S(t,G,x,U,o[9]),o[10],o[11],o[12],o[13],o[14],o[15],o[16]]);try{k(t,"INSERT OR REPLACE INTO nodes (id, file_id, lang, name_id, kind_id, raw_kind, raw_kind_source, semantic_kind_id, start_pos, end_pos, is_exported, container_kind_id, container_raw_kind, container_raw_kind_source, param_count, qualified_name, scope_chain, symbol_key, metadata)",19,_)}catch(o){if((o?.message??String(o)).includes("UNIQUE constraint failed: nodes.id")){try{let d=new Map;for(let c of e.nodeRows){let T=M(c[0]);if(T==null)continue;let R=T.toString(),m=d.get(R);m?(m.count+=1,m.rawSample.length<3&&m.rawSample.push(c[0])):d.set(R,{count:1,rawSample:[c[0]]})}let i=Array.from(d.entries()).filter(([,c])=>c.count>1).slice(0,5).map(([c,T])=>({id:c,count:T.count,rawSample:T.rawSample})),I=i.map(c=>{let T=e.nodeRows.filter(R=>{let m=M(R[0]);return m!=null&&m.toString()===c.id}).slice(0,3);return{id:c.id,count:c.count,rows:T.map(R=>({rawId:R[0],name:R[1],kind:R[2],rawKind:R[3],semanticKind:R[5],start:R[6],end:R[7],containerKind:R[9],paramCount:R[12]}))}});u("[WriterWorker] UNIQUE nodes.id collision",{file:e.fileRel,lang:e.lang,nodeCount:_.length,duplicateCount:i.length,duplicates:i,duplicateDetails:I})}catch{}try{let d=t.prepare("SELECT id, file_id, lang, start_pos, end_pos FROM nodes WHERE id = ?"),i=t.prepare("SELECT path FROM dict_files WHERE id = ?");for(let I of _){let c=I[0];if(c==null)continue;let T=d.get(c);if(T&&typeof T.file_id=="number"){let R=i.get(T.file_id);u("[WriterWorker] nodes.id collision existing row",{file:e.fileRel,lang:e.lang,nodeId:c?.toString?.()??String(c),existingFileId:T.file_id,existingPath:R?.path,existingLang:T.lang,existingRange:{start:T.start_pos,end:T.end_pos}});break}}}catch{}}throw o}}),N("writeInsertReferencesMs","references",e.referenceRows.length,()=>{(e.referenceRows||[]).some(i=>!!i?.[13]&&!i?.[7])&&(q=!0);let o=(e.referenceRows||[]).reduce((i,I)=>i+(I?.[2]!=null?1:0),0),f=(e.referenceRows||[]).map(i=>[M(i[0]),l,e.lang,M(i[2]),S(t,D,A,w,i[3]),S(t,G,x,U,i[4]),i[5],i[6],M(i[7]),i[8]?Le(t,i[8]):null,i[9]??null,i[10]??null,i[11]??null,i[12]??null,i[13]??null,i[14]??null,i[15]??null]),d=f.reduce((i,I)=>i+(I?.[3]!=null?1:0),0);e.lang==="clojure"&&e.referenceRows.length>0&&(o>0||d>0)&&(console.log("[WriterWorker] clojure reference source-node summary",{file:e.fileRel,refs:e.referenceRows.length,payloadSourceNodeCount:o,normalizedSourceNodeCount:d,sample:f.slice(0,5).map(i=>({refId:String(i[0]),sourceNodeId:i[3]==null?null:String(i[3]),refName:i[4],refKind:i[5]}))}),pe({stage:"writer-pre-insert",file:e.fileRel,refs:e.referenceRows.length,payloadSourceNodeCount:o,normalizedSourceNodeCount:d,sample:f.slice(0,5).map(i=>({sourceNodeId:i[3]==null?null:String(i[3]),refName:i[4],refKind:i[5]}))}));try{let i=new Set,I=[];for(let c of f){let T=String(c[0]);if(i.has(T)){I.push(T);continue}i.add(T)}I.length>0&&console.log("[WriterWorker] duplicate ref_id in payload",{file:e.fileRel,lang:e.lang,total:f.length,dupes:I.slice(0,10),dupeCount:I.length})}catch(i){console.log("[WriterWorker] failed to compute reference duplicates",i?.message??i)}try{if(k(t,"INSERT INTO node_references (ref_id, file_id, lang, source_node_id, ref_name_id, ref_kind_id, start_pos, end_pos, target_node_id, target_file_id, resolution_status, receiver_name, arity, container_qualified_name, target_symbol_key, confidence, metadata)",17,f),e.lang==="clojure"&&d>0){let i=t.prepare(`
|
|
243
|
+
`);let n=new Map,t=s=>{let l=n.get(s);if(l)return l;try{let a=e.prepare(`PRAGMA table_info(${s})`).all(),E=new Set(a.map(R=>R.name));return n.set(s,E),E}catch{let a=new Set;return n.set(s,a),a}},r=(s,l,a)=>{let E=t(s);E.has(l)||(e.exec(a),E.add(l))};r("files","lang","ALTER TABLE files ADD COLUMN lang TEXT"),r("nodes","lang","ALTER TABLE nodes ADD COLUMN lang TEXT"),r("nodes","semantic_kind_id","ALTER TABLE nodes ADD COLUMN semantic_kind_id INTEGER"),r("nodes","raw_kind","ALTER TABLE nodes ADD COLUMN raw_kind TEXT"),r("nodes","raw_kind_source","ALTER TABLE nodes ADD COLUMN raw_kind_source TEXT"),r("nodes","container_kind_id","ALTER TABLE nodes ADD COLUMN container_kind_id INTEGER"),r("nodes","container_raw_kind","ALTER TABLE nodes ADD COLUMN container_raw_kind TEXT"),r("nodes","container_raw_kind_source","ALTER TABLE nodes ADD COLUMN container_raw_kind_source TEXT"),r("nodes","qualified_name","ALTER TABLE nodes ADD COLUMN qualified_name TEXT"),r("nodes","scope_chain","ALTER TABLE nodes ADD COLUMN scope_chain TEXT"),r("nodes","symbol_key","ALTER TABLE nodes ADD COLUMN symbol_key TEXT"),e.exec("CREATE INDEX IF NOT EXISTS idx_nodes_symbol_key ON nodes(symbol_key)"),r("exports","lang","ALTER TABLE exports ADD COLUMN lang TEXT"),r("exports","target_symbol_key","ALTER TABLE exports ADD COLUMN target_symbol_key TEXT"),e.exec("CREATE INDEX IF NOT EXISTS idx_exports_target_symbol_key ON exports(target_symbol_key)"),r("node_references","lang","ALTER TABLE node_references ADD COLUMN lang TEXT"),r("node_references","receiver_name","ALTER TABLE node_references ADD COLUMN receiver_name TEXT"),r("node_references","arity","ALTER TABLE node_references ADD COLUMN arity INTEGER"),r("node_references","container_qualified_name","ALTER TABLE node_references ADD COLUMN container_qualified_name TEXT"),r("node_references","target_symbol_key","ALTER TABLE node_references ADD COLUMN target_symbol_key TEXT"),r("node_references","confidence","ALTER TABLE node_references ADD COLUMN confidence TEXT"),r("file_imports","lang","ALTER TABLE file_imports ADD COLUMN lang TEXT"),r("file_import_bindings","lang","ALTER TABLE file_import_bindings ADD COLUMN lang TEXT"),r("blobs_nodes","lang","ALTER TABLE blobs_nodes ADD COLUMN lang TEXT"),r("blobs_nodes","semantic_kind_id","ALTER TABLE blobs_nodes ADD COLUMN semantic_kind_id INTEGER"),r("blobs_nodes","raw_kind","ALTER TABLE blobs_nodes ADD COLUMN raw_kind TEXT"),r("blobs_nodes","raw_kind_source","ALTER TABLE blobs_nodes ADD COLUMN raw_kind_source TEXT"),r("blobs_symbols","lang","ALTER TABLE blobs_symbols ADD COLUMN lang TEXT"),r("blobs_rels","lang","ALTER TABLE blobs_rels ADD COLUMN lang TEXT"),r("blobs_rels","import_specifiers","ALTER TABLE blobs_rels ADD COLUMN import_specifiers TEXT")}Be();var De=Number(process.env.PANDO_SQLITE_RETRY_MIN_MS||"100"),ke=Number(process.env.PANDO_SQLITE_RETRY_MAX_MS||"500"),ge=Math.max(0,Number(process.env.PANDO_SQLITE_RETRY_ATTEMPTS||"5")),S=Ne();if(!A)throw new Error("SQLite writer worker must be spawned as a worker thread");Re();function I(...e){process.env.PANDO_QUIET||console.log(`[${new Date().toISOString()}]`,...e)}function m(...e){S&&console.log(...e)}function Ke(e){S&&ne("WriterWorker",e,{threadId:Me})}function Se(e){S&&ne("WriterWorker","clojure-source-node",{threadId:Me,...e})}var y=null,be=null;function ve(){be||(be=setInterval(()=>{if(!y)return;let e=Date.now()-y.startedAt;e>5e3&&I("[WriterWorker] op still running",{cmd:y.cmd,id:y.id,ms:e,fileRel:y.fileRel})},2e3))}function W(e,n,t){y={cmd:e,id:n,startedAt:Date.now(),fileRel:t},ve()}function g(){y=null}var F=()=>({writeMs:0,writeTrackedMs:0,writePreDeleteMs:0,writeInsertExportsMs:0,writeInsertNodesMs:0,writeInsertReferencesMs:0,writeInsertImportsMs:0,writeInsertImportBindingsMs:0,writeInsertFileMs:0,writeFinalizeMs:0,writeInsertFtsMs:0,writeResidualMs:0}),P=Math.max(0,Math.min(De,ke)),Le=Math.max(P,Math.max(De,ke)),He=e=>new Promise(n=>setTimeout(n,e));function Ae(e){if(!e)return!1;let n=e.code,t=e.errcode;if(n==="ERR_SQLITE_BUSY"||n==="SQLITE_BUSY"||n==="ERR_SQLITE_ERROR"&&t===5)return!0;let r=e?.message??String(e);return typeof r=="string"&&r.toLowerCase().includes("database is locked")}function ze(){if(Le<=P)return P;let e=Le-P;return P+Math.floor(Math.random()*(e+1))}async function se(e,n){let t=0,r=Date.now();for(;;)try{let s=e();return S&&t>0&&I(`[WriterWorker] ${n} recovered after retry`,{attempts:t,ms:Date.now()-r}),s}catch(s){if(!Ae(s)||t>=ge)throw I(`[WriterWorker] ${n} failed`,{attempts:t,ms:Date.now()-r,error:s?.message??String(s),locked:Ae(s)}),s;t+=1;let l=ze();I(`[WriterWorker] ${n} retry ${t}/${ge} after locked database; waiting ${l}ms`),await He(l)}}var w=null,j=null,ce=null,_e=null,Te=null,fe=null,ue=null,C=null,B=null,O=null,M=null,Q=null,V=null,Y=new Map,X=new Map,v=new Map,le=new Map,ae=Math.max(1e4,Number(process.env.PANDO_DICT_CACHE_MAX_ENTRIES||"200000")),$e=Math.max(64,Number(process.env.PANDO_DICT_CACHE_MAX_KEY_LENGTH||"1024")),Oe=Math.floor(ae*.7),z=0,$=null,h=null,H=null,J=null,Z=null,ee=null,Ee,U=null,q=!1;function te(){if(!w)throw new Error("writer not initialized");return w}function je(e){j||(j=e.prepare("DELETE FROM nodes WHERE file_id = ?"),ce=e.prepare("DELETE FROM exports WHERE file_id = ?"),_e=e.prepare("DELETE FROM files WHERE file_id = ?"),Te=e.prepare("DELETE FROM file_imports WHERE file_id = ?"),fe=e.prepare("DELETE FROM file_import_bindings WHERE file_id = ?"),ue=e.prepare("DELETE FROM node_references WHERE file_id = ?"))}function me(e){C||(C=e.prepare("INSERT OR IGNORE INTO dict_kinds (text) VALUES (?)"),B=e.prepare("SELECT id FROM dict_kinds WHERE text = ?")),O||(O=e.prepare("INSERT OR IGNORE INTO dict_symbols (text) VALUES (?)"),M=e.prepare("SELECT id FROM dict_symbols WHERE text = ?")),Q||(Q=e.prepare("INSERT OR IGNORE INTO dict_files (path) VALUES (?)"),V=e.prepare("SELECT id FROM dict_files WHERE path = ?"))}function L(e,n,t,r,s){if(!s)return null;let l=s.length<=$e,a=l?n.get(s):void 0;if(a!=null)return a;t.run(s);let E=r.get(s);if(!E||typeof E.id!="number")return null;if(l){if(n.size>=ae){let R=0;for(let b of n.keys())if(n.delete(b),R+=1,n.size<=Oe)break;z+=1,(z<=10||z%25===0)&&I("[WriterWorker] dictionary cache trimmed",{trimCount:z,removed:R,maxEntries:ae,targetAfterTrim:Oe,cacheSizeAfter:n.size})}n.set(s,E.id)}return E.id}function we(e,n){me(e);let t=v.get(n);if(t!=null)return t;Q.run(n);let r=V.get(n);if(!r||typeof r.id!="number")throw new Error(`Failed to resolve file id for ${n}`);return v.set(n,r.id),r.id}function Qe(e,n){me(e);let t=v.get(n);if(t!=null)return t;let r=V.get(n);return!r||typeof r.id!="number"?null:(v.set(n,r.id),r.id)}function Xe(e,n){let t=n?.journal_mode||"WAL";e.pragma(`journal_mode=${t}`),e.pragma("synchronous=OFF"),e.pragma("temp_store=MEMORY"),e.pragma("cache_size=-20000"),e.pragma("mmap_size=268435456"),e.pragma("journal_size_limit=134217728"),e.pragma("wal_autocheckpoint=1000"),e.pragma("busy_timeout=5000")}function oe(e){try{return de.statSync(e).size}catch{return null}}function G(e){if(!U)return;let n=`${U}-wal`,t=`${U}-shm`,r=oe(U),s=oe(n),l=oe(t);I("[WriterWorker] db sizes",{reason:e,dbPath:U,dbSize:r,walSize:s,shmSize:l})}function qe(e){let n=K.dirname(e),t=K.basename(e),r=t.replace(".pando-index-chunk-",".pando-fts-chunk-");return K.join(n,r===t?`${t}.fts`:r)}function xe(){if(!$)throw new Error("FTS database path not configured");if(!h){try{de.mkdirSync(K.dirname($),{recursive:!0})}catch{}h=new ie($),Xe(h,Ee)}return h}function Ve(e){H||(e.exec("CREATE VIRTUAL TABLE IF NOT EXISTS blob_content_fts USING fts5(blob_oid UNINDEXED, content)"),e.exec("CREATE TABLE IF NOT EXISTS blob_fts_presence (blob_oid TEXT PRIMARY KEY)"),H=e.prepare("SELECT 1 FROM blob_fts_presence WHERE blob_oid = ?"),J=e.prepare("INSERT INTO blob_content_fts (blob_oid, content) VALUES (?, ?)"),Z=e.prepare("INSERT OR REPLACE INTO blob_fts_presence (blob_oid) VALUES (?)"),ee=e.prepare("DELETE FROM blob_content_fts WHERE blob_oid = ?"))}function Je(e,n){if(!e||typeof e.blobOid!="string"||e.blobOid.length===0)return;let t=xe();Ve(t);let r=Date.now();n?.inTransaction||t.exec("BEGIN");try{H.get(e.blobOid)&&ee.run(e.blobOid),J.run(e.blobOid,e.content??""),Z.run(e.blobOid),n?.inTransaction||t.exec("COMMIT")}catch(l){if(!n?.inTransaction)try{t.exec("ROLLBACK")}catch(a){m("[WriterWorker] rollback failed:",a?.message??a)}throw l}let s=Date.now()-r;s>2e3&&I("[WriterWorker] slow fts insert",{blobOid:e.blobOid,ms:s,contentBytes:e.content?e.content.length:0})}function Ze(e,n,t,r){let s=`${n}|${t}|${r}`,l=le.get(s);if(!l){let a=Array.from({length:r},()=>`(${new Array(t).fill("?").join(",")})`).join(","),E=`${n} VALUES ${a}`;l=e.prepare(E),le.set(s,l)}return l}function x(e,n,t,r){if(!r.length||t<=0)return;let s=Date.now(),l=Math.max(1,Math.floor(999/t));for(let E=0;E<r.length;E+=l){let R=r.slice(E,E+l);if(!R.length)continue;let b=Ze(e,n,t,R.length),_=[];for(let d of R)_.push(...d);let o=Date.now();b.run(..._);let f=Date.now()-o;f>500&&I("[WriterWorker] slow insert chunk",{sqlPrefix:n,columnCount:t,rows:R.length,ms:f})}let a=Date.now()-s;a>2e3&&I("[WriterWorker] slow insertRows",{sqlPrefix:n,columnCount:t,rows:r.length,ms:a})}function ye(e,n){je(e);let t=Qe(e,n);t!=null&&(j.run(t),ce.run(t),_e.run(t),Te.run(t),fe.run(t),ue.run(t))}function et(e){if(!e.length)return F();let n=te(),t=F(),r=Date.now();n.exec("BEGIN");try{for(let s of e)ye(n,s);n.exec("COMMIT")}catch(s){try{n.exec("ROLLBACK")}catch(l){m("[WriterWorker] rollback failed:",l?.message??l)}throw s}return t.writePreDeleteMs=Date.now()-r,t.writeTrackedMs=t.writePreDeleteMs,t.writeMs=t.writePreDeleteMs,t}function Ce(e,n){let t=te();me(t);let r=F(),s=Date.now(),l=we(t,e.fileRel),a={exports:e.exportRows.length,nodes:e.nodeRows.length,refs:e.referenceRows.length,imports:e.importRows.length,importBindings:e.importBindingRows.length,fileRow:e.fileRow?1:0,fts:e.fts?1:0},E=a.exports+a.nodes+a.refs+a.imports+a.importBindings;n?.inTransaction||t.exec("BEGIN");try{if(t.exec("SAVEPOINT idx_file"),!e.preDeleted){let _=Date.now();ye(t,e.fileRel),r.writePreDeleteMs+=Date.now()-_}let R=(_,o,f,d)=>{let i=Date.now();S&&I("[WriterWorker] section begin",{file:e.fileRel,label:o,count:f});let N=Date.now();d();let c=Date.now()-N;r[_]+=c,S&&I("[WriterWorker] section end",{file:e.fileRel,label:o,count:f,ms:c,elapsedSinceWriteStartMs:Date.now()-i}),c>2e3&&I("[WriterWorker] section slow",{file:e.fileRel,label:o,count:f,ms:c})};R("writeInsertExportsMs","exports",e.exportRows.length,()=>{let _=e.exportRows.map(d=>[l,e.lang,L(t,X,O,M,d[1]),k(d[2]),d[3],d[4]??null,L(t,X,O,M,d[5]),d[6]??null,d[7]??null]),o=[],f=new Map;for(let d of _){let i=d[2];i!=null&&(f.has(i)||(f.set(i,d),o.push(d)))}o.length!==_.length&&m("[WriterWorker] export rows deduped",{file:e.fileRel,lang:e.lang,before:_.length,after:o.length});try{x(t,"INSERT OR REPLACE INTO exports (file_id, lang, export_name_id, node_id, is_reexport, reexport_from, reexport_name_id, export_kind, target_symbol_key)",9,o)}catch(d){try{let i=new Map;for(let c of _){let T=c[2];T!=null&&i.set(T,(i.get(T)??0)+1)}let N=Array.from(i.entries()).filter(([,c])=>c>1);if(N.length){let c=t.prepare("SELECT text FROM dict_symbols WHERE id = ?"),T=N.map(([u,re])=>{let We=c.get(u)?.text??null,Ue=_.filter(D=>D[2]===u).map(D=>({node_id:D[3],is_reexport:D[4],reexport_from:D[5],reexport_name_id:D[6],export_kind:D[7],target_symbol_key:D[8]}));return{id:u,count:re,name:We,rows:Ue}});m("[WriterWorker] export duplicates detected",{file:e.fileRel,lang:e.lang,totalExports:_.length,duplicates:T});let p=_.map(u=>{let re=u[2]!=null?c.get(u[2]):void 0,Ie=u[6]?c.get(u[6]):void 0;return{name_id:u[2],name:re?.text??null,node_id:u[3],is_reexport:u[4],reexport_from:u[5],reexport_name_id:u[6],reexport_name:Ie?.text??null,export_kind:u[7],target_symbol_key:u[8]}});m("[WriterWorker] export rows dump",{file:e.fileRel,lang:e.lang,rows:p})}}catch(i){m("[WriterWorker] failed to compute export duplicates",i?.message??i)}throw m("[WriterWorker] export insert failed",{file:e.fileRel,lang:e.lang,exportCount:o.length,error:d?.message??d}),d}}),R("writeInsertNodesMs","nodes",e.nodeRows.length,()=>{for(let o of e.nodeRows){let f=o[2],d=o[3],i=o[4];if(!f||!String(f).trim())throw new Error(`[WriterWorker] Missing normalized kind for node in ${e.fileRel}`);if(!d||!String(d).trim())throw new Error(`[WriterWorker] Missing raw kind for node in ${e.fileRel}`);if(!i||!String(i).trim())throw new Error(`[WriterWorker] Missing raw kind source for node in ${e.fileRel}`)}let _=e.nodeRows.map(o=>[k(o[0]),l,e.lang,L(t,X,O,M,o[1]),L(t,Y,C,B,o[2]),o[3],o[4],L(t,Y,C,B,o[5]),o[6],o[7],o[8],L(t,Y,C,B,o[9]),o[10],o[11],o[12],o[13],o[14],o[15],o[16]]);try{x(t,"INSERT OR REPLACE INTO nodes (id, file_id, lang, name_id, kind_id, raw_kind, raw_kind_source, semantic_kind_id, start_pos, end_pos, is_exported, container_kind_id, container_raw_kind, container_raw_kind_source, param_count, qualified_name, scope_chain, symbol_key, metadata)",19,_)}catch(o){if((o?.message??String(o)).includes("UNIQUE constraint failed: nodes.id")){try{let d=new Map;for(let c of e.nodeRows){let T=k(c[0]);if(T==null)continue;let p=T.toString(),u=d.get(p);u?(u.count+=1,u.rawSample.length<3&&u.rawSample.push(c[0])):d.set(p,{count:1,rawSample:[c[0]]})}let i=Array.from(d.entries()).filter(([,c])=>c.count>1).slice(0,5).map(([c,T])=>({id:c,count:T.count,rawSample:T.rawSample})),N=i.map(c=>{let T=e.nodeRows.filter(p=>{let u=k(p[0]);return u!=null&&u.toString()===c.id}).slice(0,3);return{id:c.id,count:c.count,rows:T.map(p=>({rawId:p[0],name:p[1],kind:p[2],rawKind:p[3],semanticKind:p[5],start:p[6],end:p[7],containerKind:p[9],paramCount:p[12]}))}});I("[WriterWorker] UNIQUE nodes.id collision",{file:e.fileRel,lang:e.lang,nodeCount:_.length,duplicateCount:i.length,duplicates:i,duplicateDetails:N})}catch{}try{let d=t.prepare("SELECT id, file_id, lang, start_pos, end_pos FROM nodes WHERE id = ?"),i=t.prepare("SELECT path FROM dict_files WHERE id = ?");for(let N of _){let c=N[0];if(c==null)continue;let T=d.get(c);if(T&&typeof T.file_id=="number"){let p=i.get(T.file_id);I("[WriterWorker] nodes.id collision existing row",{file:e.fileRel,lang:e.lang,nodeId:c?.toString?.()??String(c),existingFileId:T.file_id,existingPath:p?.path,existingLang:T.lang,existingRange:{start:T.start_pos,end:T.end_pos}});break}}}catch{}}throw o}}),R("writeInsertReferencesMs","references",e.referenceRows.length,()=>{(e.referenceRows||[]).some(i=>!!i?.[13]&&!i?.[7])&&(q=!0);let o=(e.referenceRows||[]).reduce((i,N)=>i+(N?.[2]!=null?1:0),0),f=(e.referenceRows||[]).map(i=>[k(i[0]),l,e.lang,k(i[2]),L(t,X,O,M,i[3]),L(t,Y,C,B,i[4]),i[5],i[6],k(i[7]),i[8]?we(t,i[8]):null,i[9]??null,i[10]??null,i[11]??null,i[12]??null,i[13]??null,i[14]??null,i[15]??null]),d=f.reduce((i,N)=>i+(N?.[3]!=null?1:0),0);S&&e.lang==="clojure"&&e.referenceRows.length>0&&(o>0||d>0)&&(m("[WriterWorker] clojure reference source-node summary",{file:e.fileRel,refs:e.referenceRows.length,payloadSourceNodeCount:o,normalizedSourceNodeCount:d,sample:f.slice(0,5).map(i=>({refId:String(i[0]),sourceNodeId:i[3]==null?null:String(i[3]),refName:i[4],refKind:i[5]}))}),Se({stage:"writer-pre-insert",file:e.fileRel,refs:e.referenceRows.length,payloadSourceNodeCount:o,normalizedSourceNodeCount:d,sample:f.slice(0,5).map(i=>({sourceNodeId:i[3]==null?null:String(i[3]),refName:i[4],refKind:i[5]}))}));try{let i=new Set,N=[];for(let c of f){let T=String(c[0]);if(i.has(T)){N.push(T);continue}i.add(T)}S&&N.length>0&&m("[WriterWorker] duplicate ref_id in payload",{file:e.fileRel,lang:e.lang,total:f.length,dupes:N.slice(0,10),dupeCount:N.length})}catch(i){S&&m("[WriterWorker] failed to compute reference duplicates",i?.message??i)}try{if(x(t,"INSERT INTO node_references (ref_id, file_id, lang, source_node_id, ref_name_id, ref_kind_id, start_pos, end_pos, target_node_id, target_file_id, resolution_status, receiver_name, arity, container_qualified_name, target_symbol_key, confidence, metadata)",17,f),S&&e.lang==="clojure"&&d>0){let i=t.prepare(`
|
|
246
244
|
SELECT COUNT(*) AS total_refs,
|
|
247
245
|
SUM(CASE WHEN source_node_id IS NOT NULL THEN 1 ELSE 0 END) AS refs_with_source
|
|
248
246
|
FROM node_references
|
|
249
247
|
WHERE file_id = ?
|
|
250
|
-
`).setReadBigInts(!0).get(l);
|
|
251
|
-
`).slice(0,3).join(" | ")}),l)try{l.exec("ROLLBACK")}catch(E){
|
|
248
|
+
`).setReadBigInts(!0).get(l);m("[WriterWorker] clojure reference source-node verify",{file:e.fileRel,totalRefs:i?.total_refs==null?null:String(i.total_refs),refsWithSource:i?.refs_with_source==null?null:String(i.refs_with_source)}),Se({stage:"writer-post-insert",file:e.fileRel,totalRefs:i?.total_refs==null?null:String(i.total_refs),refsWithSource:i?.refs_with_source==null?null:String(i.refs_with_source)})}}catch(i){let N=i?.message??String(i);if(m("[WriterWorker] reference insert failed",{file:e.fileRel,lang:e.lang,referenceCount:f.length,sampleRefIds:f.slice(0,10).map(c=>c[0]),error:N}),N.includes("UNIQUE constraint failed: node_references.ref_id")){m("[WriterWorker] reference insert retry with INSERT OR IGNORE",{file:e.fileRel,lang:e.lang,referenceCount:f.length}),x(t,"INSERT OR IGNORE INTO node_references (ref_id, file_id, lang, source_node_id, ref_name_id, ref_kind_id, start_pos, end_pos, target_node_id, target_file_id, resolution_status, receiver_name, arity, container_qualified_name, target_symbol_key, confidence, metadata)",17,f);return}throw i}}),R("writeInsertImportsMs","imports",e.importRows.length,()=>{let _=e.importRows.map(o=>[l,e.lang,o[1]??null,o[2]]);x(t,"INSERT INTO file_imports (file_id, lang, module_spec, is_type_only)",4,_)}),R("writeInsertImportBindingsMs","import_bindings",e.importBindingRows.length,()=>{let _=e.importBindingRows.map(o=>[l,e.lang,o[1]??null,L(t,X,O,M,o[2]),L(t,X,O,M,o[3]),L(t,X,O,M,o[4]),o[5]]);x(t,"INSERT INTO file_import_bindings (file_id, lang, module_spec, binding_kind_id, local_name_id, imported_name_id, is_type_only)",7,_)}),R("writeInsertFileMs","files",e.fileRow?1:0,()=>{let _=e.fileRow,o=[l,e.lang,_[1],_[2],_[3],_[4]];x(t,"INSERT OR REPLACE INTO files (file_id, lang, last_modified, file_size, status, indexed_at)",6,[o])}),R("writeInsertFtsMs","fts",e.fts?1:0,()=>Je(e.fts,{inTransaction:n?.inTransaction}));let b=Date.now();t.exec("RELEASE SAVEPOINT idx_file"),n?.inTransaction||t.exec("COMMIT"),r.writeFinalizeMs+=Date.now()-b}catch(R){try{t.exec("ROLLBACK TO SAVEPOINT idx_file")}catch(b){m("[WriterWorker] rollback to savepoint failed:",b?.message??b)}if(!n?.inTransaction)try{t.exec("ROLLBACK")}catch(b){m("[WriterWorker] rollback failed:",b?.message??b)}throw R}return r.writeMs=Date.now()-s,r.writeTrackedMs=r.writePreDeleteMs+r.writeInsertExportsMs+r.writeInsertNodesMs+r.writeInsertImportsMs+r.writeInsertImportBindingsMs+r.writeInsertFileMs+r.writeInsertFtsMs+r.writeFinalizeMs,r.writeResidualMs=Math.max(0,r.writeMs-r.writeTrackedMs),r}function tt(e){if(!e.length)return F();let n=Date.now(),t=F(),r=te(),s=e.some(a=>a.fts&&typeof a.fts.blobOid=="string"&&a.fts.blobOid.length>0),l=null;r.exec("BEGIN");try{s&&(l=xe(),l.exec("BEGIN"));for(let a of e){let E=Ce(a,{inTransaction:!0});t.writePreDeleteMs+=E.writePreDeleteMs,t.writeInsertExportsMs+=E.writeInsertExportsMs,t.writeInsertNodesMs+=E.writeInsertNodesMs,t.writeInsertReferencesMs+=E.writeInsertReferencesMs,t.writeInsertImportsMs+=E.writeInsertImportsMs,t.writeInsertImportBindingsMs+=E.writeInsertImportBindingsMs,t.writeInsertFileMs+=E.writeInsertFileMs,t.writeFinalizeMs+=E.writeFinalizeMs,t.writeInsertFtsMs+=E.writeInsertFtsMs}l&&l.exec("COMMIT"),r.exec("COMMIT")}catch(a){if(I("[WriterWorker] handleWriteBatch error",{error:a?.message??a,stack:a?.stack?.split(`
|
|
249
|
+
`).slice(0,3).join(" | ")}),l)try{l.exec("ROLLBACK")}catch(E){m("[WriterWorker] fts batch rollback failed:",E?.message??E)}try{r.exec("ROLLBACK")}catch(E){m("[WriterWorker] batch rollback failed:",E?.message??E)}throw a}return t.writeTrackedMs=t.writePreDeleteMs+t.writeInsertExportsMs+t.writeInsertNodesMs+t.writeInsertReferencesMs+t.writeInsertImportsMs+t.writeInsertImportBindingsMs+t.writeInsertFileMs+t.writeInsertFtsMs+t.writeFinalizeMs,t.writeMs=Date.now()-n,t.writeResidualMs=Math.max(0,t.writeMs-t.writeTrackedMs),t}function Fe(){return q&&w&&(te().exec(`
|
|
252
250
|
WITH unique_symbols AS (
|
|
253
251
|
SELECT symbol_key, MIN(id) AS node_id, MIN(file_id) AS file_id, COUNT(*) AS cnt
|
|
254
252
|
FROM nodes
|
|
@@ -280,4 +278,4 @@ import{a as M}from"./chunk-2YGY7BLN.mjs";import{a as re,b as We}from"./chunk-Z5R
|
|
|
280
278
|
(target_node_id IS NULL OR target_file_id IS NULL)
|
|
281
279
|
AND target_symbol_key IS NOT NULL
|
|
282
280
|
AND target_symbol_key <> '';
|
|
283
|
-
`),q=!1),
|
|
281
|
+
`),q=!1),F()}function he(){try{Fe()}catch(e){m("[WriterWorker] backfill on shutdown failed:",e?.message??e)}if(w){try{w.close()}catch(e){m("[WriterWorker] failed to close database:",e?.message??e)}w=null}if(h){try{h.close()}catch(e){m("[WriterWorker] failed to close FTS database:",e?.message??e)}h=null}j=null,ce=null,_e=null,Te=null,fe=null,ue=null,H=null,J=null,Z=null,ee=null,C=null,B=null,O=null,M=null,Q=null,V=null,le.clear(),Y.clear(),X.clear(),v.clear(),q=!1}A.on("message",async e=>{let n=(t,r)=>{let s=r instanceof Error?r:new Error(String(r));A.postMessage({type:"error",id:t,message:s.message,stack:s.stack})};if(e.cmd==="init"){try{let t=Date.now();W("init"),w&&he();let r=e.dbPath;U=r,Ee=e.pragmas;try{de.mkdirSync(K.dirname(r),{recursive:!0})}catch{}if(w=new ie(r),Xe(w,Ee),pe(w),$=qe(r),h)try{h.close()}catch(s){m("[WriterWorker] failed to close FTS database:",s?.message??s)}h=null,H=null,J=null,Z=null,ee=null,A.postMessage({type:"ready"}),I("[WriterWorker] init complete",{dbPath:r,ms:Date.now()-t}),G("init"),g()}catch(t){g(),n(void 0,t)}return}if(e.cmd==="write"){try{let t=Date.now(),r=e.payload,s=Array.isArray(r?.fileRow)&&typeof r.fileRow[0]=="string"?r.fileRow[0]:void 0;W("write",e.id,s);let l=await se(()=>Ce(r),"write");A.postMessage({type:"response",id:e.id,metrics:l});let a=Date.now()-t;a>2e3&&(I("[WriterWorker] slow write",{id:e.id,ms:a}),G("slow write")),g()}catch(t){g(),n(e.id,t)}return}if(e.cmd==="batchPreDelete"){try{let t=Date.now();W("batchPreDelete",e.id);let r=await se(()=>et(e.files),"batchPreDelete");A.postMessage({type:"response",id:e.id,metrics:r});let s=Date.now()-t;s>2e3&&(I("[WriterWorker] slow batchPreDelete",{id:e.id,ms:s,count:Array.isArray(e.files)?e.files.length:0}),G("slow batchPreDelete")),g()}catch(t){g(),n(e.id,t)}return}if(e.cmd==="writeBatch"){try{let t=Date.now(),r=Array.isArray(e.payloads)?e.payloads:[],s=r.length?r[0].fileRel:void 0;W("writeBatch",e.id,s),Ke(`writeBatch received id=${e.id} count=${r.length} sample=${r[0]?.fileRel??""}`),S&&I("[WriterWorker] writeBatch begin",{id:e.id,count:r.length,sample:r.slice(0,5).map(E=>E.fileRel)});let l=await se(()=>tt(r),"writeBatch");A.postMessage({type:"response",id:e.id,metrics:l});let a=Date.now()-t;S&&I("[WriterWorker] writeBatch end",{id:e.id,ms:a,count:r.length,metrics:l}),a>2e3&&(I("[WriterWorker] slow write batch",{id:e.id,ms:a,count:r.length}),G("slow write batch")),g()}catch(t){g(),n(e.id,t)}return}if(e.cmd==="flush"){try{let t=Date.now();W("flush",e.id);let r=Fe();A.postMessage({type:"response",id:e.id,metrics:r});let s=Date.now()-t;s>2e3&&(I("[WriterWorker] slow flush",{id:e.id,ms:s}),G("slow flush")),g()}catch(t){g(),n(e.id,t)}return}if(e.cmd==="shutdown"){try{W("shutdown",e.id),he(),A.postMessage({type:"response",id:e.id,metrics:F()}),g()}catch(t){g(),n(e.id,t)}return}});process.on("uncaughtException",e=>{try{A.postMessage({type:"error",message:e?.message||String(e),stack:e?.stack})}catch(n){m("[WriterWorker] failed to notify parent about uncaughtException:",n?.message??n)}});process.on("unhandledRejection",e=>{try{A.postMessage({type:"error",message:String(e)})}catch(n){m("[WriterWorker] failed to notify parent about unhandledRejection:",n?.message??n)}});
|
package/package.json
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pando-ai",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.18",
|
|
4
4
|
"description": "Standalone pando MCP CLI",
|
|
5
5
|
"bin": {
|
|
6
|
-
"pando-ai": "
|
|
6
|
+
"pando-ai": "bin/pando-ai.js"
|
|
7
7
|
},
|
|
8
8
|
"files": [
|
|
9
|
+
"bin/",
|
|
9
10
|
"dist/",
|
|
10
11
|
"resources/tools/pando-tools.json",
|
|
11
12
|
"tools/clojure-indexer/bin/",
|
|
@@ -23,6 +23,8 @@
|
|
|
23
23
|
"read-this-first()",
|
|
24
24
|
"get-project-root()",
|
|
25
25
|
"set-project-root(root)",
|
|
26
|
+
"get-enabled-languages()",
|
|
27
|
+
"set-enabled-languages(languages)",
|
|
26
28
|
"find-nodes(q, qMode, name, async, exported, static, private, protected, readonly, abstract, paramCount, exportedOnly, defaultOnly, symbolKinds, hasDecorator, implements, extends, returns, asOf, scopeNode, expectedHash, limit, offset, sort, lang, semanticKind, include, cursor, datalog, boundary, reachabilityDepth, reachabilityOptions)",
|
|
27
29
|
"find-references(to, expectedHash, boundary, includeDeclaration, includeStrings, includeComments, limit, offset, relType, sort, reachabilityDepth, reachabilityOptions, asOf)",
|
|
28
30
|
"find-callers(of, expectedHash, depth, aggregate, boundary, asOf, offset, limit, relType, sort, reachabilityDepth, reachabilityOptions)",
|
|
@@ -112,11 +114,66 @@
|
|
|
112
114
|
}
|
|
113
115
|
]
|
|
114
116
|
},
|
|
117
|
+
{
|
|
118
|
+
"name": "get-enabled-languages",
|
|
119
|
+
"category": "pando",
|
|
120
|
+
"signature": "get-enabled-languages()",
|
|
121
|
+
"description": "Return the currently enabled indexing languages for the selected root, plus the full list of language ids that can be set. Example: {}",
|
|
122
|
+
"parameters": {
|
|
123
|
+
"type": "object",
|
|
124
|
+
"properties": {},
|
|
125
|
+
"required": [],
|
|
126
|
+
"additionalProperties": false
|
|
127
|
+
},
|
|
128
|
+
"examples": [
|
|
129
|
+
{}
|
|
130
|
+
]
|
|
131
|
+
},
|
|
132
|
+
{
|
|
133
|
+
"name": "set-enabled-languages",
|
|
134
|
+
"category": "pando",
|
|
135
|
+
"signature": "set-enabled-languages(languages)",
|
|
136
|
+
"description": "Persist the enabled indexing languages for the selected root. The provided array becomes the supported language list. Example: { languages: ['clojure'] }",
|
|
137
|
+
"parameters": {
|
|
138
|
+
"type": "object",
|
|
139
|
+
"properties": {
|
|
140
|
+
"languages": {
|
|
141
|
+
"type": "array",
|
|
142
|
+
"description": "Language ids to keep enabled for indexing.",
|
|
143
|
+
"items": {
|
|
144
|
+
"type": "string",
|
|
145
|
+
"enum": [
|
|
146
|
+
"ts",
|
|
147
|
+
"js",
|
|
148
|
+
"python",
|
|
149
|
+
"c",
|
|
150
|
+
"cpp",
|
|
151
|
+
"csharp",
|
|
152
|
+
"dart",
|
|
153
|
+
"java",
|
|
154
|
+
"clojure"
|
|
155
|
+
]
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
},
|
|
159
|
+
"required": [
|
|
160
|
+
"languages"
|
|
161
|
+
],
|
|
162
|
+
"additionalProperties": false
|
|
163
|
+
},
|
|
164
|
+
"examples": [
|
|
165
|
+
{
|
|
166
|
+
"languages": [
|
|
167
|
+
"clojure"
|
|
168
|
+
]
|
|
169
|
+
}
|
|
170
|
+
]
|
|
171
|
+
},
|
|
115
172
|
{
|
|
116
173
|
"name": "find-nodes",
|
|
117
174
|
"category": "pando",
|
|
118
175
|
"signature": "find-nodes(q, qMode, name, async, exported, static, private, protected, readonly, abstract, paramCount, exportedOnly, defaultOnly, symbolKinds, hasDecorator, implements, extends, returns, asOf, scopeNode, expectedHash, limit, offset, sort, lang, semanticKind, include, cursor, datalog, boundary, reachabilityDepth, reachabilityOptions)",
|
|
119
|
-
"description": "Search code nodes by symbolKinds/name/text/scope with optional enrichment. qMode: 'fts' (SQLite MATCH syntax) or 'like' (SQL LIKE with %/_). scopeNode may be a dir, file, or node path 'src/a.ts#10-20:FD'; if it includes '#', expectedHash (no @) is required to verify. limit clamps to 100 per page; offset clamps to >= 0; use limit='all' to stream pages. include can add self/body/parents for topN<=5. Examples: { symbolKinds:['function'], name:'init', limit:10 }, { q:'\"TODO\"', qMode:'fts', limit:10 }, { scopeNode:'src/services/', limit:10 }",
|
|
176
|
+
"description": "Search code nodes by symbolKinds/name/text/scope with optional enrichment. qMode: 'fts' (SQLite MATCH syntax) or 'like' (SQL LIKE with %/_). scopeNode may be a dir, file, or node path 'src/a.ts#10-20:FD'; if it includes '#', expectedHash (no @) is required to verify. limit clamps to 100 per page; offset clamps to >= 0; use limit='all' to stream pages. include can add self/body/parents/arities for topN<=5. Examples: { symbolKinds:['function'], name:'init', limit:10 }, { q:'\"TODO\"', qMode:'fts', limit:10 }, { scopeNode:'src/services/', limit:10 }",
|
|
120
177
|
"parameters": {
|
|
121
178
|
"type": "object",
|
|
122
179
|
"properties": {
|
|
@@ -334,6 +391,10 @@
|
|
|
334
391
|
"type": "boolean",
|
|
335
392
|
"description": "Include parent chain metadata."
|
|
336
393
|
},
|
|
394
|
+
"arities": {
|
|
395
|
+
"type": "boolean",
|
|
396
|
+
"description": "For Clojure, include explicit multi-arity clause targets with path/hash/ref so body edits can target a single arity."
|
|
397
|
+
},
|
|
337
398
|
"topN": {
|
|
338
399
|
"type": "integer",
|
|
339
400
|
"description": "How many results to fully enrich (0-5).",
|
|
@@ -898,7 +959,7 @@
|
|
|
898
959
|
"name": "workspace-overview",
|
|
899
960
|
"category": "pando",
|
|
900
961
|
"signature": "workspace-overview()",
|
|
901
|
-
"description": "Summarize workspace files, node counts, modules, artifacts, and
|
|
962
|
+
"description": "Summarize workspace files, node counts, modules, artifacts, indexing status, and storage paths. The result includes `storage.pandoDataDir`, `storage.chunkDbs`, and `storage.historyDir`. IMPORTANT: All modifying pando operations (insert, replace, delete, rename, filter-map-reduce, etc.) automatically create snapshots before and after execution - you do NOT need to manually call snapshot-worktree before pando operations. Only use snapshot-worktree for non-pando file modifications (e.g., when using Write, Edit, or Bash tools to modify files). Example: {}",
|
|
902
963
|
"parameters": {
|
|
903
964
|
"type": "object",
|
|
904
965
|
"properties": {},
|
|
Binary file
|
|
Binary file
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{createHash as e}from"crypto";var u=/^-?\d+$/,o=(1n<<63n)-1n;function l(n){let t=e("sha1").update(n).digest(),r=0n;for(let i=0;i<8;i+=1)r=r<<8n|BigInt(t[i]);return r&o}function f(n){if(n==null)return null;if(typeof n=="bigint")return n;if(typeof n=="number"&&Number.isFinite(n))return BigInt(Math.trunc(n));if(typeof n=="string"){let t=n.trim();if(!t)return null;if(u.test(t))try{return BigInt(t)}catch{return null}return l(t)}return null}export{f as a};
|