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.
Files changed (150) hide show
  1. package/dist/cli.js +124 -124
  2. package/dist/watcher-process.js +421 -421
  3. package/dist/workers/chunk-Z7LW7C4Z.mjs +518 -0
  4. package/dist/workers/indexer-worker.mjs +1 -1
  5. package/dist/workers/snapshot-worker.mjs +8 -4
  6. package/package.json +5 -4
  7. package/resources/tools/{pando-tools.json → generated_pando-tools.json} +98 -4
  8. package/resources/tools/generated_tools.md +93 -0
  9. package/tools/clojure-editor/lib/pando-clojure-editor-standalone.jar +0 -0
  10. package/tools/clojure-indexer/lib/pando-clojure-indexer-standalone.jar +0 -0
  11. package/tools/csharp-indexer/CSharpIndexer.csproj +1 -1
  12. package/tools/csharp-indexer/bin/pando-csharp-indexer +81 -23
  13. package/tools/csharp-indexer/bin/pando-csharp-indexer.cmd +82 -14
  14. package/tools/csharp-indexer/src/Program.cs +1860 -0
  15. package/dist/workers/chunk-BD3AO7O3.mjs +0 -522
  16. package/tools/csharp-indexer/bin/Release/net10.0/CSharpIndexer +0 -0
  17. package/tools/csharp-indexer/bin/Release/net10.0/CSharpIndexer.deps.json +0 -383
  18. package/tools/csharp-indexer/bin/Release/net10.0/CSharpIndexer.dll +0 -0
  19. package/tools/csharp-indexer/bin/Release/net10.0/CSharpIndexer.pdb +0 -0
  20. package/tools/csharp-indexer/bin/Release/net10.0/CSharpIndexer.runtimeconfig.json +0 -13
  21. package/tools/csharp-indexer/bin/Release/net10.0/Humanizer.dll +0 -0
  22. package/tools/csharp-indexer/bin/Release/net10.0/Microsoft.CodeAnalysis.CSharp.Workspaces.dll +0 -0
  23. package/tools/csharp-indexer/bin/Release/net10.0/Microsoft.CodeAnalysis.CSharp.dll +0 -0
  24. package/tools/csharp-indexer/bin/Release/net10.0/Microsoft.CodeAnalysis.Workspaces.dll +0 -0
  25. package/tools/csharp-indexer/bin/Release/net10.0/Microsoft.CodeAnalysis.dll +0 -0
  26. package/tools/csharp-indexer/bin/Release/net10.0/System.Composition.AttributedModel.dll +0 -0
  27. package/tools/csharp-indexer/bin/Release/net10.0/System.Composition.Convention.dll +0 -0
  28. package/tools/csharp-indexer/bin/Release/net10.0/System.Composition.Hosting.dll +0 -0
  29. package/tools/csharp-indexer/bin/Release/net10.0/System.Composition.Runtime.dll +0 -0
  30. package/tools/csharp-indexer/bin/Release/net10.0/System.Composition.TypedParts.dll +0 -0
  31. package/tools/csharp-indexer/bin/Release/net10.0/cs/Microsoft.CodeAnalysis.CSharp.Workspaces.resources.dll +0 -0
  32. package/tools/csharp-indexer/bin/Release/net10.0/cs/Microsoft.CodeAnalysis.CSharp.resources.dll +0 -0
  33. package/tools/csharp-indexer/bin/Release/net10.0/cs/Microsoft.CodeAnalysis.Workspaces.resources.dll +0 -0
  34. package/tools/csharp-indexer/bin/Release/net10.0/cs/Microsoft.CodeAnalysis.resources.dll +0 -0
  35. package/tools/csharp-indexer/bin/Release/net10.0/de/Microsoft.CodeAnalysis.CSharp.Workspaces.resources.dll +0 -0
  36. package/tools/csharp-indexer/bin/Release/net10.0/de/Microsoft.CodeAnalysis.CSharp.resources.dll +0 -0
  37. package/tools/csharp-indexer/bin/Release/net10.0/de/Microsoft.CodeAnalysis.Workspaces.resources.dll +0 -0
  38. package/tools/csharp-indexer/bin/Release/net10.0/de/Microsoft.CodeAnalysis.resources.dll +0 -0
  39. package/tools/csharp-indexer/bin/Release/net10.0/es/Microsoft.CodeAnalysis.CSharp.Workspaces.resources.dll +0 -0
  40. package/tools/csharp-indexer/bin/Release/net10.0/es/Microsoft.CodeAnalysis.CSharp.resources.dll +0 -0
  41. package/tools/csharp-indexer/bin/Release/net10.0/es/Microsoft.CodeAnalysis.Workspaces.resources.dll +0 -0
  42. package/tools/csharp-indexer/bin/Release/net10.0/es/Microsoft.CodeAnalysis.resources.dll +0 -0
  43. package/tools/csharp-indexer/bin/Release/net10.0/fr/Microsoft.CodeAnalysis.CSharp.Workspaces.resources.dll +0 -0
  44. package/tools/csharp-indexer/bin/Release/net10.0/fr/Microsoft.CodeAnalysis.CSharp.resources.dll +0 -0
  45. package/tools/csharp-indexer/bin/Release/net10.0/fr/Microsoft.CodeAnalysis.Workspaces.resources.dll +0 -0
  46. package/tools/csharp-indexer/bin/Release/net10.0/fr/Microsoft.CodeAnalysis.resources.dll +0 -0
  47. package/tools/csharp-indexer/bin/Release/net10.0/it/Microsoft.CodeAnalysis.CSharp.Workspaces.resources.dll +0 -0
  48. package/tools/csharp-indexer/bin/Release/net10.0/it/Microsoft.CodeAnalysis.CSharp.resources.dll +0 -0
  49. package/tools/csharp-indexer/bin/Release/net10.0/it/Microsoft.CodeAnalysis.Workspaces.resources.dll +0 -0
  50. package/tools/csharp-indexer/bin/Release/net10.0/it/Microsoft.CodeAnalysis.resources.dll +0 -0
  51. package/tools/csharp-indexer/bin/Release/net10.0/ja/Microsoft.CodeAnalysis.CSharp.Workspaces.resources.dll +0 -0
  52. package/tools/csharp-indexer/bin/Release/net10.0/ja/Microsoft.CodeAnalysis.CSharp.resources.dll +0 -0
  53. package/tools/csharp-indexer/bin/Release/net10.0/ja/Microsoft.CodeAnalysis.Workspaces.resources.dll +0 -0
  54. package/tools/csharp-indexer/bin/Release/net10.0/ja/Microsoft.CodeAnalysis.resources.dll +0 -0
  55. package/tools/csharp-indexer/bin/Release/net10.0/ko/Microsoft.CodeAnalysis.CSharp.Workspaces.resources.dll +0 -0
  56. package/tools/csharp-indexer/bin/Release/net10.0/ko/Microsoft.CodeAnalysis.CSharp.resources.dll +0 -0
  57. package/tools/csharp-indexer/bin/Release/net10.0/ko/Microsoft.CodeAnalysis.Workspaces.resources.dll +0 -0
  58. package/tools/csharp-indexer/bin/Release/net10.0/ko/Microsoft.CodeAnalysis.resources.dll +0 -0
  59. package/tools/csharp-indexer/bin/Release/net10.0/pl/Microsoft.CodeAnalysis.CSharp.Workspaces.resources.dll +0 -0
  60. package/tools/csharp-indexer/bin/Release/net10.0/pl/Microsoft.CodeAnalysis.CSharp.resources.dll +0 -0
  61. package/tools/csharp-indexer/bin/Release/net10.0/pl/Microsoft.CodeAnalysis.Workspaces.resources.dll +0 -0
  62. package/tools/csharp-indexer/bin/Release/net10.0/pl/Microsoft.CodeAnalysis.resources.dll +0 -0
  63. package/tools/csharp-indexer/bin/Release/net10.0/pt-BR/Microsoft.CodeAnalysis.CSharp.Workspaces.resources.dll +0 -0
  64. package/tools/csharp-indexer/bin/Release/net10.0/pt-BR/Microsoft.CodeAnalysis.CSharp.resources.dll +0 -0
  65. package/tools/csharp-indexer/bin/Release/net10.0/pt-BR/Microsoft.CodeAnalysis.Workspaces.resources.dll +0 -0
  66. package/tools/csharp-indexer/bin/Release/net10.0/pt-BR/Microsoft.CodeAnalysis.resources.dll +0 -0
  67. package/tools/csharp-indexer/bin/Release/net10.0/ru/Microsoft.CodeAnalysis.CSharp.Workspaces.resources.dll +0 -0
  68. package/tools/csharp-indexer/bin/Release/net10.0/ru/Microsoft.CodeAnalysis.CSharp.resources.dll +0 -0
  69. package/tools/csharp-indexer/bin/Release/net10.0/ru/Microsoft.CodeAnalysis.Workspaces.resources.dll +0 -0
  70. package/tools/csharp-indexer/bin/Release/net10.0/ru/Microsoft.CodeAnalysis.resources.dll +0 -0
  71. package/tools/csharp-indexer/bin/Release/net10.0/tr/Microsoft.CodeAnalysis.CSharp.Workspaces.resources.dll +0 -0
  72. package/tools/csharp-indexer/bin/Release/net10.0/tr/Microsoft.CodeAnalysis.CSharp.resources.dll +0 -0
  73. package/tools/csharp-indexer/bin/Release/net10.0/tr/Microsoft.CodeAnalysis.Workspaces.resources.dll +0 -0
  74. package/tools/csharp-indexer/bin/Release/net10.0/tr/Microsoft.CodeAnalysis.resources.dll +0 -0
  75. package/tools/csharp-indexer/bin/Release/net10.0/zh-Hans/Microsoft.CodeAnalysis.CSharp.Workspaces.resources.dll +0 -0
  76. package/tools/csharp-indexer/bin/Release/net10.0/zh-Hans/Microsoft.CodeAnalysis.CSharp.resources.dll +0 -0
  77. package/tools/csharp-indexer/bin/Release/net10.0/zh-Hans/Microsoft.CodeAnalysis.Workspaces.resources.dll +0 -0
  78. package/tools/csharp-indexer/bin/Release/net10.0/zh-Hans/Microsoft.CodeAnalysis.resources.dll +0 -0
  79. package/tools/csharp-indexer/bin/Release/net10.0/zh-Hant/Microsoft.CodeAnalysis.CSharp.Workspaces.resources.dll +0 -0
  80. package/tools/csharp-indexer/bin/Release/net10.0/zh-Hant/Microsoft.CodeAnalysis.CSharp.resources.dll +0 -0
  81. package/tools/csharp-indexer/bin/Release/net10.0/zh-Hant/Microsoft.CodeAnalysis.Workspaces.resources.dll +0 -0
  82. package/tools/csharp-indexer/bin/Release/net10.0/zh-Hant/Microsoft.CodeAnalysis.resources.dll +0 -0
  83. package/tools/csharp-indexer/bin/Release/net8.0/CSharpIndexer +0 -0
  84. package/tools/csharp-indexer/bin/Release/net8.0/CSharpIndexer.deps.json +0 -400
  85. package/tools/csharp-indexer/bin/Release/net8.0/CSharpIndexer.dll +0 -0
  86. package/tools/csharp-indexer/bin/Release/net8.0/CSharpIndexer.pdb +0 -0
  87. package/tools/csharp-indexer/bin/Release/net8.0/CSharpIndexer.runtimeconfig.json +0 -13
  88. package/tools/csharp-indexer/bin/Release/net8.0/Humanizer.dll +0 -0
  89. package/tools/csharp-indexer/bin/Release/net8.0/Microsoft.CodeAnalysis.CSharp.Workspaces.dll +0 -0
  90. package/tools/csharp-indexer/bin/Release/net8.0/Microsoft.CodeAnalysis.CSharp.dll +0 -0
  91. package/tools/csharp-indexer/bin/Release/net8.0/Microsoft.CodeAnalysis.Workspaces.dll +0 -0
  92. package/tools/csharp-indexer/bin/Release/net8.0/Microsoft.CodeAnalysis.dll +0 -0
  93. package/tools/csharp-indexer/bin/Release/net8.0/System.Composition.AttributedModel.dll +0 -0
  94. package/tools/csharp-indexer/bin/Release/net8.0/System.Composition.Convention.dll +0 -0
  95. package/tools/csharp-indexer/bin/Release/net8.0/System.Composition.Hosting.dll +0 -0
  96. package/tools/csharp-indexer/bin/Release/net8.0/System.Composition.Runtime.dll +0 -0
  97. package/tools/csharp-indexer/bin/Release/net8.0/System.Composition.TypedParts.dll +0 -0
  98. package/tools/csharp-indexer/bin/Release/net8.0/System.IO.Pipelines.dll +0 -0
  99. package/tools/csharp-indexer/bin/Release/net8.0/cs/Microsoft.CodeAnalysis.CSharp.Workspaces.resources.dll +0 -0
  100. package/tools/csharp-indexer/bin/Release/net8.0/cs/Microsoft.CodeAnalysis.CSharp.resources.dll +0 -0
  101. package/tools/csharp-indexer/bin/Release/net8.0/cs/Microsoft.CodeAnalysis.Workspaces.resources.dll +0 -0
  102. package/tools/csharp-indexer/bin/Release/net8.0/cs/Microsoft.CodeAnalysis.resources.dll +0 -0
  103. package/tools/csharp-indexer/bin/Release/net8.0/de/Microsoft.CodeAnalysis.CSharp.Workspaces.resources.dll +0 -0
  104. package/tools/csharp-indexer/bin/Release/net8.0/de/Microsoft.CodeAnalysis.CSharp.resources.dll +0 -0
  105. package/tools/csharp-indexer/bin/Release/net8.0/de/Microsoft.CodeAnalysis.Workspaces.resources.dll +0 -0
  106. package/tools/csharp-indexer/bin/Release/net8.0/de/Microsoft.CodeAnalysis.resources.dll +0 -0
  107. package/tools/csharp-indexer/bin/Release/net8.0/es/Microsoft.CodeAnalysis.CSharp.Workspaces.resources.dll +0 -0
  108. package/tools/csharp-indexer/bin/Release/net8.0/es/Microsoft.CodeAnalysis.CSharp.resources.dll +0 -0
  109. package/tools/csharp-indexer/bin/Release/net8.0/es/Microsoft.CodeAnalysis.Workspaces.resources.dll +0 -0
  110. package/tools/csharp-indexer/bin/Release/net8.0/es/Microsoft.CodeAnalysis.resources.dll +0 -0
  111. package/tools/csharp-indexer/bin/Release/net8.0/fr/Microsoft.CodeAnalysis.CSharp.Workspaces.resources.dll +0 -0
  112. package/tools/csharp-indexer/bin/Release/net8.0/fr/Microsoft.CodeAnalysis.CSharp.resources.dll +0 -0
  113. package/tools/csharp-indexer/bin/Release/net8.0/fr/Microsoft.CodeAnalysis.Workspaces.resources.dll +0 -0
  114. package/tools/csharp-indexer/bin/Release/net8.0/fr/Microsoft.CodeAnalysis.resources.dll +0 -0
  115. package/tools/csharp-indexer/bin/Release/net8.0/it/Microsoft.CodeAnalysis.CSharp.Workspaces.resources.dll +0 -0
  116. package/tools/csharp-indexer/bin/Release/net8.0/it/Microsoft.CodeAnalysis.CSharp.resources.dll +0 -0
  117. package/tools/csharp-indexer/bin/Release/net8.0/it/Microsoft.CodeAnalysis.Workspaces.resources.dll +0 -0
  118. package/tools/csharp-indexer/bin/Release/net8.0/it/Microsoft.CodeAnalysis.resources.dll +0 -0
  119. package/tools/csharp-indexer/bin/Release/net8.0/ja/Microsoft.CodeAnalysis.CSharp.Workspaces.resources.dll +0 -0
  120. package/tools/csharp-indexer/bin/Release/net8.0/ja/Microsoft.CodeAnalysis.CSharp.resources.dll +0 -0
  121. package/tools/csharp-indexer/bin/Release/net8.0/ja/Microsoft.CodeAnalysis.Workspaces.resources.dll +0 -0
  122. package/tools/csharp-indexer/bin/Release/net8.0/ja/Microsoft.CodeAnalysis.resources.dll +0 -0
  123. package/tools/csharp-indexer/bin/Release/net8.0/ko/Microsoft.CodeAnalysis.CSharp.Workspaces.resources.dll +0 -0
  124. package/tools/csharp-indexer/bin/Release/net8.0/ko/Microsoft.CodeAnalysis.CSharp.resources.dll +0 -0
  125. package/tools/csharp-indexer/bin/Release/net8.0/ko/Microsoft.CodeAnalysis.Workspaces.resources.dll +0 -0
  126. package/tools/csharp-indexer/bin/Release/net8.0/ko/Microsoft.CodeAnalysis.resources.dll +0 -0
  127. package/tools/csharp-indexer/bin/Release/net8.0/pl/Microsoft.CodeAnalysis.CSharp.Workspaces.resources.dll +0 -0
  128. package/tools/csharp-indexer/bin/Release/net8.0/pl/Microsoft.CodeAnalysis.CSharp.resources.dll +0 -0
  129. package/tools/csharp-indexer/bin/Release/net8.0/pl/Microsoft.CodeAnalysis.Workspaces.resources.dll +0 -0
  130. package/tools/csharp-indexer/bin/Release/net8.0/pl/Microsoft.CodeAnalysis.resources.dll +0 -0
  131. package/tools/csharp-indexer/bin/Release/net8.0/pt-BR/Microsoft.CodeAnalysis.CSharp.Workspaces.resources.dll +0 -0
  132. package/tools/csharp-indexer/bin/Release/net8.0/pt-BR/Microsoft.CodeAnalysis.CSharp.resources.dll +0 -0
  133. package/tools/csharp-indexer/bin/Release/net8.0/pt-BR/Microsoft.CodeAnalysis.Workspaces.resources.dll +0 -0
  134. package/tools/csharp-indexer/bin/Release/net8.0/pt-BR/Microsoft.CodeAnalysis.resources.dll +0 -0
  135. package/tools/csharp-indexer/bin/Release/net8.0/ru/Microsoft.CodeAnalysis.CSharp.Workspaces.resources.dll +0 -0
  136. package/tools/csharp-indexer/bin/Release/net8.0/ru/Microsoft.CodeAnalysis.CSharp.resources.dll +0 -0
  137. package/tools/csharp-indexer/bin/Release/net8.0/ru/Microsoft.CodeAnalysis.Workspaces.resources.dll +0 -0
  138. package/tools/csharp-indexer/bin/Release/net8.0/ru/Microsoft.CodeAnalysis.resources.dll +0 -0
  139. package/tools/csharp-indexer/bin/Release/net8.0/tr/Microsoft.CodeAnalysis.CSharp.Workspaces.resources.dll +0 -0
  140. package/tools/csharp-indexer/bin/Release/net8.0/tr/Microsoft.CodeAnalysis.CSharp.resources.dll +0 -0
  141. package/tools/csharp-indexer/bin/Release/net8.0/tr/Microsoft.CodeAnalysis.Workspaces.resources.dll +0 -0
  142. package/tools/csharp-indexer/bin/Release/net8.0/tr/Microsoft.CodeAnalysis.resources.dll +0 -0
  143. package/tools/csharp-indexer/bin/Release/net8.0/zh-Hans/Microsoft.CodeAnalysis.CSharp.Workspaces.resources.dll +0 -0
  144. package/tools/csharp-indexer/bin/Release/net8.0/zh-Hans/Microsoft.CodeAnalysis.CSharp.resources.dll +0 -0
  145. package/tools/csharp-indexer/bin/Release/net8.0/zh-Hans/Microsoft.CodeAnalysis.Workspaces.resources.dll +0 -0
  146. package/tools/csharp-indexer/bin/Release/net8.0/zh-Hans/Microsoft.CodeAnalysis.resources.dll +0 -0
  147. package/tools/csharp-indexer/bin/Release/net8.0/zh-Hant/Microsoft.CodeAnalysis.CSharp.Workspaces.resources.dll +0 -0
  148. package/tools/csharp-indexer/bin/Release/net8.0/zh-Hant/Microsoft.CodeAnalysis.CSharp.resources.dll +0 -0
  149. package/tools/csharp-indexer/bin/Release/net8.0/zh-Hant/Microsoft.CodeAnalysis.Workspaces.resources.dll +0 -0
  150. package/tools/csharp-indexer/bin/Release/net8.0/zh-Hant/Microsoft.CodeAnalysis.resources.dll +0 -0
@@ -1 +1 @@
1
- import{b as B,c as O,d as q,e as A,f as z,g as F,j as C}from"./chunk-BD3AO7O3.mjs";import"./chunk-ODST7O2H.mjs";import{c as L}from"./chunk-AYCBSZ56.mjs";import{parentPort as h,threadId as re}from"worker_threads";import U from"fs";import $ from"path";import{promises as K}from"fs";import X from"ignore";import{createHash as te}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,t){return Buffer.from(e).toString(t)}function M(e,t,c,r,d,p){let m=Buffer.from(e),n=te("sha1").update(m).digest("hex"),i=p??m.toString(d),l=i?i.split(/\r?\n/).length:0;return{relPath:t,size:c,mtime:r,objectId:n,lineCount:l,encoding:d}}if(!h)throw new Error("Indexer worker must be spawned as a worker thread");L();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:re,...t&&typeof t=="object"&&!Array.isArray(t)?t:{details:t}})}`)}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,t){return $.relative(e,t).replace(/\\/g,"/")}function se(e,t){let c=(t||[]).map(r=>typeof r=="string"?r.trim():"").filter(Boolean).map(r=>r.replace(/^[\\/]+/,"").replace(/[\\/]+$/,"")).map(r=>r.endsWith("/")?r:`${r}/`);return c.length?r=>{let d=H(e,r);if(!d||d.startsWith(".."))return!1;let p=d.endsWith("/")?d:`${d}/`;return c.some(m=>p.startsWith(m))}:null}async function ie(e){await new Promise(t=>{x.set(e,t)})}h.on("message",async e=>{if(e.cmd==="scan-ack"){let t=x.get(e.requestId);if(t){x.delete(e.requestId);try{t()}catch{}}return}if(e.cmd==="scan-cancel"){I.add(e.requestId);let t=x.get(e.requestId);if(t){x.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"&&(D=e.projectRoot),T=e.mode??"index",u("init completed",{mode:T,projectRoot:D}),h.postMessage({type:"ready"})}catch(t){u("init failed",{error:t?.message||String(t),stack:t?.stack??null}),h.postMessage({type:"error",message:`init failed: ${t?.message||t}`,stack:t?.stack})}return}if(e.cmd==="scan"){let t=e.requestId,c=typeof e.projectRoot=="string"?e.projectRoot:D;if(u("scan received",{requestId:t,projectRoot:c||null,batchSize:e.batchSize??null,maxFileBytes:e.maxFileBytes??null,excludeDirs:Array.isArray(e.excludeDirs)?e.excludeDirs.slice(0,20):[]}),!c){h.postMessage({type:"error",requestId:t,message:"worker not initialized"});return}let r=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(c,e.excludeDirs??[]),i=new Set(["node_modules",".git",".pando-data"]),l=o=>o.replace(/\\/g,"/"),f=await C(c,""),v=X().add(f),g=[{dir:c,relDir:"",rules:f,ig:v}],y=0,a=0,s=[],k=async()=>{s.length&&(h.postMessage({type:"scan:batch",requestId:t,files:s}),s=[],await ie(t))};try{for(;g.length&&!I.has(t);){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(t))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=l(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(c,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>=r&&await k()}}I.has(t)||await k(),h.postMessage({type:"scan:done",requestId:t,discovered:y,skipped:a,cancelled:I.has(t)}),u("scan complete",{requestId:t,discovered:y,skipped:a,cancelled:I.has(t)})}catch(o){u("scan failed",{requestId:t,error:o?.message||String(o),stack:o?.stack??null}),h.postMessage({type:"error",requestId:t,message:o?.message||String(o),stack:o?.stack})}finally{I.delete(t),x.delete(t)}return}if(e.cmd==="process"){let t=e.role??T,c=typeof e.projectRoot=="string"?e.projectRoot:D;if(!c){h.postMessage({type:"error",requestId:e.requestId,message:"worker not initialized"});return}let{file:r}=e,d=r.encoding??"utf8",p=r.sharedBuffer,m={size:r.size,mtime:r.mtime};try{let n=r.lang??"ts",i,l,f=()=>{if(l&&typeof i=="string")return{content:i,sharedBuffer:l};if(p instanceof SharedArrayBuffer)return l=p,i=N(p,d),{content:i,sharedBuffer:l};if(p instanceof ArrayBuffer){let o=Buffer.from(p),P=new SharedArrayBuffer(o.byteLength);return new Uint8Array(P).set(o),l=P,i=o.toString(d),{content:i,sharedBuffer:l}}let s=U.readFileSync(r.absPath),k=new SharedArrayBuffer(s.byteLength);return new Uint8Array(k).set(s),l=k,i=s.toString(d),{content:i,sharedBuffer:l}},v=()=>{let s=B(n,r.relPath,m),k=f();h.postMessage({type:"result",requestId:e.requestId,role:"index",relPath:r.relPath,result:{payload:s.payload,meta:{size:s.fileSize,mtime:s.mtime},snapshotSummary:M(k.sharedBuffer,r.relPath,r.size,r.mtime,d,k.content)}})},g=`${c}:${n}`,y=G.get(g);if(!y)try{u("creating language indexer",{role:t,requestId:e.requestId,lang:n,projectRoot:c});let s=z(n);if(!O(s))throw new Error(`${n} is not a worker-indexed language`);y=s.createIndexer(c),G.set(g,y),u("language indexer ready",{role:t,requestId:e.requestId,lang:n,projectRoot:c})}catch(s){u("language indexer create failed",{role:t,requestId:e.requestId,lang:n,error:s?.message||String(s),stack:s?.stack??null}),v();return}({content:i,sharedBuffer:l}=f());let a;try{a=await y.process({absPath:r.absPath,relPath:r.relPath,content:i,meta:m,preDeleted:!!r.preDeleted,lang:n,indexAllNodes:r.indexAllNodes})}catch(s){u("process failed",{role:t,requestId:e.requestId,lang:n,relPath:r.relPath,error:s?.message||String(s),stack:s?.stack??null}),v();return}h.postMessage({type:"result",requestId:e.requestId,role:"index",relPath:r.relPath,result:{payload:a.payload,meta:{size:a.fileSize,mtime:a.mtime},snapshotSummary:M(l,r.relPath,r.size,r.mtime,d,i)}})}catch(n){u("process wrapper failed",{role:t,requestId:e.requestId,relPath:r.relPath,error:n?.message||String(n),stack:n?.stack??null});try{let i=r.lang??"ts",l=U.readFileSync(r.absPath),f=new SharedArrayBuffer(l.byteLength);new Uint8Array(f).set(l);let v=l.toString(d),g=B(i,r.relPath,m);h.postMessage({type:"result",requestId:e.requestId,role:"index",relPath:r.relPath,result:{payload:g.payload,meta:{size:g.fileSize,mtime:g.mtime},snapshotSummary:M(f,r.relPath,r.size,r.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
+ 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{a as _,h as x,i as K}from"./chunk-BD3AO7O3.mjs";import{a as Y,b as it,c as V,e as R}from"./chunk-ODST7O2H.mjs";import{a as J,b as Tt}from"./chunk-Z5RGEDVQ.mjs";import{a as Dt,c as st}from"./chunk-AYCBSZ56.mjs";import{parentPort as j}from"worker_threads";import rt from"path";import*as o from"fs";import*as I from"path";import*as g from"isomorphic-git";import{execFileSync as v}from"child_process";V();import*as Q from"path";function nt(i){let t=Y(i);return{root:t,historyGit:Q.join(t,"history.git"),workdir:Q.join(t,"workdir")}}function f(i,t){try{_.info(i,t)}catch{}}function ot(i,t){try{_.warn(i,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((r,s)=>r.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,"/"),r=n.split("/").filter(Boolean);if(!r.length)return;let s=r.slice(0,-1),a=r[r.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 l=s[b];if(this.stack[this.stack.length-1].fileNames.has(l))throw new Error(`Path conflict: file exists where directory expected: ${s.slice(0,b+1).join("/")}`);this.stack.push({name:l,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})}},H=class{constructor(t){this.baseDir=t.baseDir;let e=nt(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)),r=null;try{try{r=o.openSync(e,"wx"),o.writeFileSync(r,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;r=o.openSync(e,"wx"),o.writeFileSync(r,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
2
- `),f(`[${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=I.join(this.repoDir,".gitignore");if(!o.existsSync(t))try{o.mkdirSync(I.dirname(t),{recursive:!0}),o.writeFileSync(t,`# ast history repo
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 tt(i,t){let e=it(i),n=It.dirname(e);q.existsSync(n)||q.mkdirSync(n,{recursive:!0});let r=!!t?.readonly;if(r&&!q.existsSync(e)){let a=new J(e,{});try{pt(a)}finally{try{a.close()}catch{}}}let s=new J(e,r?{readonly:!0}:{});if(!r)pt(s);else try{s.pragma("busy_timeout = 10000")}catch{}return s}var O="",et=[],yt=null;st();function dt(i,t){if(Array.isArray(t)){et=t.slice(),yt=lt(i,et);try{R("SnapshotWorker","exclude state updated",{excludeDirs:et})}catch{}}}function Mt(i){let t=ht(i,{shouldExclude:yt??void 0,gitignoreRoot:i});try{R("SnapshotWorker","gatherSnapshotFiles",{count:t.length,sample:t.slice(0,20).map(e=>rt.relative(i,e).replace(/\\/g,"/"))})}catch{}return t}function gt(i){try{return i.prepare("SELECT snapshot_id FROM snapshots ORDER BY timestamp DESC, rowid DESC LIMIT 1").get()?.snapshot_id}catch{return}}function mt(i,t,e,n,r){let s=r||null;i.prepare("INSERT OR REPLACE INTO snapshots (snapshot_id, parents, timestamp, message) VALUES (?, ?, ?, ?)").run(t,s,Math.floor(e/1e3),n)}async function ft(i,t,e){try{return await i.readCommitParent(t)||e}catch{return e}}function X(i,t){let e=new Map;try{let n=i.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 ut(i,t,e){i.transaction(r=>{let s=i.prepare("INSERT OR REPLACE INTO snapshot_members (snapshot_id, logical_path, object_id, lang, encoding) VALUES (?, ?, ?, ?, ?)");for(let a of r)s.run(t,a.logical_path,a.object_id,a.lang??null,a.encoding??null)})(e)}j.on("message",async i=>{if(i.cmd==="init"){O=i.projectRoot,dt(O,i.excludeDirs),j.postMessage({type:"ready"});return}if(i.excludeDirs&&dt(O,i.excludeDirs),i.cmd==="snapshot"){let t=tt(O);try{let e=Date.now(),n=i.payload?.when||Date.now(),r=i.payload?.message||"ast: snapshot",s=i.payload?.parent||gt(t),a=Date.now(),p=i.payload?.files&&i.payload.files.length?i.payload.files:Mt(O);try{R("SnapshotWorker","snapshot start",{when:n,message:r,parent:s,fileCount:p.length,filesPreview:p.slice(0,50).map(D=>rt.relative(O,D).replace(/\\/g,"/"))})}catch{}let m=Date.now()-a,u=p.map(D=>rt.relative(O,D).replace(/\\/g,"/")),b=(i.payload?.captured||[]).map(D=>({logicalPath:D.logicalPath,objectId:"unknown",content:Buffer.from(D.contentB64,"base64")})),l=new H({baseDir:O});await l.ensureInitialized();let h=Date.now(),y=b.length>0?await l.createSnapshotFromDiskAndCapturedIfChanged({message:r,when:n,relPaths:u,capturedMembers:b,parent:s}):await l.createSnapshotFromDiskIfChanged({message:r,when:n,relPaths:u,parent:s}),S=y.snapshotId,c=await ft(l,S,y.parent||s),d=Date.now()-h;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{}j.postMessage({type:"result",snapshotId:S,parent:c,files:u.length,diff:{added:0,changed:0,deleted:0}})}else{let D=Date.now();mt(t,S,n,r,c);try{let M=Z(r||""),U=t.prepare("INSERT OR REPLACE INTO snapshot_meta (snapshot_id, key, value) VALUES (?, ?, ?)");t.transaction(()=>{for(let[bt,wt]of Object.entries(M))U.run(S,bt,wt)})()}catch{}let E=Date.now()-D,T=Date.now(),$=await l.listSnapshotMembers(S),k=Date.now()-T,C=$.map(M=>({logical_path:M.logicalPath,object_id:M.objectId})),N=Date.now();ut(t,S,C);let G=Date.now()-N,B=c?X(t,c):new Map,w=X(t,S),P=[],A=[],z=[];for(let[M,U]of w){let W=B.get(M);W?W!==U&&A.push(M):P.push(M)}for(let[M]of B)w.has(M)||z.push(M);let St=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:St},diff:{added:P.length,changed:A.length,deleted:z.length}})}catch{}j.postMessage({type:"result",snapshotId:S,parent:c,files:u.length,diff:{added:P.length,changed:A.length,deleted:z.length}})}}catch(e){j.postMessage({type:"error",message:e?.message||String(e)})}finally{t.close()}return}if(i.cmd==="snapshot-captured"){let t=tt(O);try{let e=i.payload?.when||Date.now(),n=i.payload?.message||"ast: snapshot",r=i.payload?.parent||gt(t);try{R("SnapshotWorker","snapshot-captured start",{when:e,message:n,parent:r,members:i.payload.members.length})}catch{}let s=new H({baseDir:O});await s.ensureInitialized();let a=(i.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 ft(s,p,r);mt(t,p,e,n,m);try{let d=Z(n||""),D=t.prepare("INSERT OR REPLACE INTO snapshot_meta (snapshot_id, key, value) VALUES (?, ?, ?)");t.transaction(()=>{for(let[T,$]of Object.entries(d))D.run(p,T,$)})()}catch{}let u=await s.listSnapshotMembers(p),b=u.map(d=>({logical_path:d.logicalPath,object_id:d.objectId}));ut(t,p,b);let l=m?X(t,m):new Map,h=X(t,p),y=[],S=[],c=[];for(let[d,D]of h){let E=l.get(d);E?E!==D&&S.push(d):y.push(d)}for(let[d]of l)h.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{}j.postMessage({type:"result",snapshotId:p,parent:m,files:u.length,diff:{added:y.length,changed:S.length,deleted:c.length}})}catch(e){j.postMessage({type:"error",message:e?.message||String(e)})}finally{t.close()}}i.cmd==="close"&&j.postMessage({type:"closed"})});
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&&gt(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.4",
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/pando-tools.json",
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": "../../docs/tools.md",
5
+ "docs": "generated_tools.md",
6
6
  "sourceOfTruth": "../pando-backend/src/lib/tooling/tools.d/",
7
- "backendAssembledFile": "../pando-backend/src/lib/tooling/tools.json",
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 tools.json.",
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": "pandō tools are the required code surface for supported-language source operations in pandō benchmark runs. Use pandō for supported source-code read, search, navigation, refactor, edit, delete, insert, replace, rename, references, callers, exports, SQL index queries, and filter-map-reduce operations. Supported source languages include TypeScript, JavaScript, Python, C, C++, C#, Dart, Java, Clojure, and ClojureScript files (.cljs via the Clojure language id). Use non-pandō text/shell tools only for non-code files, unsupported languages, shell setup, builds, and tests. Current find-nodes is Datalog-only and accepts { op, lang?, snapshot?, scope, datalog, prefilter?, include?, page? }; legacy fields such as q, qMode, name, symbolKinds, scopeNode, limit, offset, and top-level cursor are rejected. Example find-nodes declaration lookup: { op:'find-nodes', lang:['ts','js'], scope:{workspace:true}, datalog:{query:'[:find ?n :where [?n :node/name \"myFunction\"]]', bindings:['?n'], result:{nodeVar:'?n'}}, include:{self:true, topN:1}, page:{limit:5} }. Then pass the returned path and hash without @ to modifying tools such as rename, replace, replace-body, insert, or delete. pandō modifying tools automatically create snapshots before and after execution; do not manually snapshot before pandō operations. If a pandō operation fails because of a stale path or hash mismatch, call find-nodes again to refresh the current path/hash and retry with pandō.",
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.
@@ -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
- pick_tfm() {
6
- local ver major
7
- ver="$(dotnet --version 2>/dev/null || true)"
8
- major="${ver%%.*}"
9
- if [ "$major" = "10" ]; then
10
- echo "net10.0"
11
- return
12
- fi
13
- if [ "$major" = "8" ]; then
14
- echo "net8.0"
15
- return
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
- echo "net8.0"
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
- TFM="$(pick_tfm)"
21
- for candidate in "$ROOT_DIR/bin/Release/$TFM/CSharpIndexer.dll" \
22
- "$ROOT_DIR/bin/Release/net10.0/CSharpIndexer.dll" \
23
- "$ROOT_DIR/bin/Release/net8.0/CSharpIndexer.dll"; do
24
- if [ -f "$candidate" ]; then
25
- exec dotnet "$candidate" "$@"
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
- done
88
+ fi
28
89
 
29
- echo "CSharpIndexer Release DLL not found." >&2
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" "$@"