pi-forge 0.0.0 → 1.1.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +48 -4
- package/bin/pi-forge.mjs +37 -0
- package/dist/client/assets/CodeMirrorEditor-BqaaP1EE.js +34 -0
- package/dist/client/assets/CodeMirrorEditor-BqaaP1EE.js.map +1 -0
- package/dist/client/assets/index-B-529kgJ.css +32 -0
- package/dist/client/assets/index-BzKzxXFs.js +392 -0
- package/dist/client/assets/index-BzKzxXFs.js.map +1 -0
- package/dist/client/assets/workbox-window.prod.es5-BBnX5xw4.js +3 -0
- package/dist/client/assets/workbox-window.prod.es5-BBnX5xw4.js.map +1 -0
- package/dist/client/icons/icon-192.png +0 -0
- package/dist/client/icons/icon-512.png +0 -0
- package/dist/client/icons/icon-maskable-512.png +0 -0
- package/dist/client/icons/icon.svg +9 -0
- package/dist/client/index.html +24 -0
- package/dist/client/manifest.webmanifest +1 -0
- package/dist/client/offline.html +142 -0
- package/dist/client/sw.js +3 -0
- package/dist/client/sw.js.map +1 -0
- package/dist/client/workbox-6d7155ed.js +3 -0
- package/dist/client/workbox-6d7155ed.js.map +1 -0
- package/dist/server/agent-resource-loader.js +126 -0
- package/dist/server/agent-resource-loader.js.map +1 -0
- package/dist/server/attachment-converters.js +96 -0
- package/dist/server/attachment-converters.js.map +1 -0
- package/dist/server/auth.js +209 -0
- package/dist/server/auth.js.map +1 -0
- package/dist/server/compaction-history.js +106 -0
- package/dist/server/compaction-history.js.map +1 -0
- package/dist/server/concurrency.js +49 -0
- package/dist/server/concurrency.js.map +1 -0
- package/dist/server/config-export.js +220 -0
- package/dist/server/config-export.js.map +1 -0
- package/dist/server/config-manager.js +528 -0
- package/dist/server/config-manager.js.map +1 -0
- package/dist/server/config.js +326 -0
- package/dist/server/config.js.map +1 -0
- package/dist/server/conversion-worker.mjs +90 -0
- package/dist/server/diagnostics.js +137 -0
- package/dist/server/diagnostics.js.map +1 -0
- package/dist/server/extensions-discovery.js +147 -0
- package/dist/server/extensions-discovery.js.map +1 -0
- package/dist/server/file-manager.js +734 -0
- package/dist/server/file-manager.js.map +1 -0
- package/dist/server/file-references.js +215 -0
- package/dist/server/file-references.js.map +1 -0
- package/dist/server/file-searcher.js +385 -0
- package/dist/server/file-searcher.js.map +1 -0
- package/dist/server/git-runner.js +684 -0
- package/dist/server/git-runner.js.map +1 -0
- package/dist/server/index.js +468 -0
- package/dist/server/index.js.map +1 -0
- package/dist/server/mcp/config.js +133 -0
- package/dist/server/mcp/config.js.map +1 -0
- package/dist/server/mcp/manager.js +351 -0
- package/dist/server/mcp/manager.js.map +1 -0
- package/dist/server/mcp/tool-bridge.js +173 -0
- package/dist/server/mcp/tool-bridge.js.map +1 -0
- package/dist/server/project-manager.js +301 -0
- package/dist/server/project-manager.js.map +1 -0
- package/dist/server/pty-manager.js +354 -0
- package/dist/server/pty-manager.js.map +1 -0
- package/dist/server/routes/_schemas.js +73 -0
- package/dist/server/routes/_schemas.js.map +1 -0
- package/dist/server/routes/auth.js +164 -0
- package/dist/server/routes/auth.js.map +1 -0
- package/dist/server/routes/config.js +1163 -0
- package/dist/server/routes/config.js.map +1 -0
- package/dist/server/routes/control.js +464 -0
- package/dist/server/routes/control.js.map +1 -0
- package/dist/server/routes/exec.js +217 -0
- package/dist/server/routes/exec.js.map +1 -0
- package/dist/server/routes/files.js +847 -0
- package/dist/server/routes/files.js.map +1 -0
- package/dist/server/routes/git.js +837 -0
- package/dist/server/routes/git.js.map +1 -0
- package/dist/server/routes/health.js +97 -0
- package/dist/server/routes/health.js.map +1 -0
- package/dist/server/routes/mcp.js +300 -0
- package/dist/server/routes/mcp.js.map +1 -0
- package/dist/server/routes/projects.js +259 -0
- package/dist/server/routes/projects.js.map +1 -0
- package/dist/server/routes/prompt.js +496 -0
- package/dist/server/routes/prompt.js.map +1 -0
- package/dist/server/routes/sessions.js +783 -0
- package/dist/server/routes/sessions.js.map +1 -0
- package/dist/server/routes/stream.js +69 -0
- package/dist/server/routes/stream.js.map +1 -0
- package/dist/server/routes/terminal.js +335 -0
- package/dist/server/routes/terminal.js.map +1 -0
- package/dist/server/session-registry.js +1197 -0
- package/dist/server/session-registry.js.map +1 -0
- package/dist/server/skill-overrides.js +151 -0
- package/dist/server/skill-overrides.js.map +1 -0
- package/dist/server/skills-export.js +257 -0
- package/dist/server/skills-export.js.map +1 -0
- package/dist/server/sse-bridge.js +220 -0
- package/dist/server/sse-bridge.js.map +1 -0
- package/dist/server/tool-overrides.js +277 -0
- package/dist/server/tool-overrides.js.map +1 -0
- package/dist/server/turn-diff-builder.js +280 -0
- package/dist/server/turn-diff-builder.js.map +1 -0
- package/package.json +53 -12
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"file-manager.js","sourceRoot":"","sources":["../src/file-manager.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,EACL,IAAI,IAAI,MAAM,EACd,QAAQ,IAAI,UAAU,EACtB,OAAO,EACP,QAAQ,EACR,MAAM,IAAI,QAAQ,EAClB,EAAE,EACF,KAAK,EACL,IAAI,EACJ,MAAM,EACN,SAAS,IAAI,WAAW,GACzB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAC;AAC9D,OAAO,EAAE,IAAI,EAAE,MAAM,aAAa,CAAC;AACnC,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,WAAW,CAAC;AACrF,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACrD,OAAO,EAAE,MAAM,IAAI,SAAS,EAAE,MAAM,KAAK,CAAC;AAG1C;;;;;;;;;;;;GAYG;AAEH,wEAAwE;AAExE,MAAM,OAAO,oBAAqB,SAAQ,KAAK;IAC7C,YAAY,MAAc,EAAE,IAAY;QACtC,KAAK,CAAC,8BAA8B,MAAM,UAAU,IAAI,GAAG,CAAC,CAAC;QAC7D,IAAI,CAAC,IAAI,GAAG,sBAAsB,CAAC;IACrC,CAAC;CACF;AAED,MAAM,OAAO,aAAc,SAAQ,KAAK;IACtC,YAAY,IAAY;QACtB,KAAK,CAAC,cAAc,IAAI,EAAE,CAAC,CAAC;QAC5B,IAAI,CAAC,IAAI,GAAG,eAAe,CAAC;IAC9B,CAAC;CACF;AAED,MAAM,OAAO,aAAc,SAAQ,KAAK;IACtC,YAAY,IAAY;QACtB,KAAK,CAAC,eAAe,IAAI,EAAE,CAAC,CAAC;QAC7B,IAAI,CAAC,IAAI,GAAG,eAAe,CAAC;IAC9B,CAAC;CACF;AAED,MAAM,OAAO,iBAAkB,SAAQ,KAAK;IACjC,IAAI,CAAS;IACb,KAAK,CAAS;IACvB,YAAY,IAAY,EAAE,IAAY,EAAE,KAAa;QACnD,KAAK,CAAC,mBAAmB,IAAI,KAAK,IAAI,MAAM,KAAK,GAAG,CAAC,CAAC;QACtD,IAAI,CAAC,IAAI,GAAG,mBAAmB,CAAC;QAChC,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;IACrB,CAAC;CACF;AAED,MAAM,OAAO,sBAAuB,SAAQ,KAAK;IAC/C,YAAY,IAAY;QACtB,KAAK,CAAC,wBAAwB,IAAI,EAAE,CAAC,CAAC;QACtC,IAAI,CAAC,IAAI,GAAG,wBAAwB,CAAC;IACvC,CAAC;CACF;AAED,MAAM,OAAO,gBAAiB,SAAQ,KAAK;IACzC,YAAY,OAAO,GAAG,mBAAmB;QACvC,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,kBAAkB,CAAC;IACjC,CAAC;CACF;AAED,MAAM,OAAO,qBAAsB,SAAQ,KAAK;IACrC,MAAM,CAAS;IACf,QAAQ,CAAS;IACjB,MAAM,CAAS;IACxB,YAAY,MAAc,EAAE,QAAgB,EAAE,MAAc;QAC1D,KAAK,CAAC,wBAAwB,MAAM,cAAc,QAAQ,SAAS,MAAM,GAAG,CAAC,CAAC;QAC9E,IAAI,CAAC,IAAI,GAAG,uBAAuB,CAAC;QACpC,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;QACzB,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;IACvB,CAAC;CACF;AAED,MAAM,OAAO,iBAAkB,SAAQ,KAAK;IAC1C,YAAY,IAAY;QACtB,KAAK,CAAC,0BAA0B,IAAI,EAAE,CAAC,CAAC;QACxC,IAAI,CAAC,IAAI,GAAG,mBAAmB,CAAC;IAClC,CAAC;CACF;AAED,wEAAwE;AAExE;;;;;GAKG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,GAAG,IAAI,GAAG,IAAI,CAAC;AAE9C;;;;;;GAMG;AACH,MAAM,cAAc,GAAG,IAAI,GAAG,CAAC;IAC7B,cAAc;IACd,MAAM;IACN,MAAM;IACN,OAAO;IACP,aAAa;IACb,OAAO;IACP,OAAO;IACP,UAAU;IACV,OAAO;IACP,QAAQ;IACR,QAAQ;CACT,CAAC,CAAC;AAEH;;;;;GAKG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAwB,cAAc,CAAC;AAEpE,MAAM,kBAAkB,GAAG,CAAC,CAAC;AAE7B,wEAAwE;AAExE;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,UAAU,gBAAgB,CAAC,MAAc,EAAE,IAAY;IAC3D,IAAI,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC;QAAE,MAAM,IAAI,oBAAoB,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;IACxE,MAAM,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IACvC,MAAM,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACnC,IAAI,cAAc,KAAK,YAAY;QAAE,OAAO,cAAc,CAAC;IAC3D,MAAM,GAAG,GAAG,QAAQ,CAAC,YAAY,EAAE,cAAc,CAAC,CAAC;IACnD,IAAI,GAAG,CAAC,MAAM,KAAK,CAAC,IAAI,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,GAAG,CAAC,UAAU,CAAC,KAAK,GAAG,EAAE,CAAC,EAAE,CAAC;QAC3E,MAAM,IAAI,oBAAoB,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;IAC/C,CAAC;IACD,OAAO,cAAc,CAAC;AACxB,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,KAAK,UAAU,cAAc,CAAC,MAAc,EAAE,IAAY;IACxD,+DAA+D;IAC/D,8DAA8D;IAC9D,oCAAoC;IACpC,gBAAgB,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;IAC/B,MAAM,QAAQ,GAAG,MAAM,QAAQ,CAAC,IAAI,CAAC,CAAC;IACtC,MAAM,aAAa,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IACtC,IAAI,MAAM,GAAG,aAAa,CAAC;IAC3B,OAAO,IAAI,EAAE,CAAC;QACZ,IAAI,CAAC;YACH,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,MAAM,CAAC,CAAC;YACpC,gBAAgB,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;YACjC,OAAO,aAAa,CAAC;QACvB,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,IAAI,GAAI,GAA6B,CAAC,IAAI,CAAC;YACjD,IAAI,IAAI,KAAK,QAAQ;gBAAE,MAAM,GAAG,CAAC;YACjC,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;YAC/B,IAAI,MAAM,KAAK,MAAM,EAAE,CAAC;gBACtB,4DAA4D;gBAC5D,8DAA8D;gBAC9D,0BAA0B;gBAC1B,MAAM,IAAI,oBAAoB,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;YAC/C,CAAC;YACD,MAAM,GAAG,MAAM,CAAC;QAClB,CAAC;IACH,CAAC;AACH,CAAC;AAED;;;;;GAKG;AACH,SAAS,YAAY,CAAC,IAAY;IAChC,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;IAC5B,IACE,OAAO,CAAC,MAAM,KAAK,CAAC;QACpB,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC;QACrB,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC;QACtB,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC;QACtB,OAAO,KAAK,GAAG;QACf,OAAO,KAAK,IAAI,EAChB,CAAC;QACD,MAAM,IAAI,gBAAgB,EAAE,CAAC;IAC/B,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC;AAmBD,MAAM,CAAC,KAAK,UAAU,OAAO,CAAC,QAAgB,EAAE,OAAuB,EAAE;IACvE,MAAM,IAAI,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;IAC/B,sEAAsE;IACtE,4DAA4D;IAC5D,MAAM,EAAE,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;IACnD,IAAI,CAAC,EAAE,EAAE,WAAW,EAAE,EAAE,CAAC;QACvB,MAAM,IAAI,aAAa,CAAC,IAAI,CAAC,CAAC;IAChC,CAAC;IACD,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,IAAI,kBAAkB,CAAC;IACrD,OAAO,IAAI,CAAC,IAAI,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,EAAE,QAAQ,CAAC,CAAC;AAC3C,CAAC;AAED,KAAK,UAAU,IAAI,CACjB,GAAW,EACX,IAAY,EACZ,OAAe,EACf,KAAa,EACb,QAAgB;IAEhB,MAAM,IAAI,GAAG,OAAO,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,IAAI,EAAE,CAAC,CAAC;IACpE,MAAM,IAAI,GAAa;QACrB,IAAI;QACJ,IAAI,EAAE,OAAO;QACb,IAAI,EAAE,WAAW;QACjB,QAAQ,EAAE,EAAE;KACb,CAAC;IACF,IAAI,KAAK,IAAI,QAAQ,EAAE,CAAC;QACtB,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC;QACtB,OAAO,IAAI,CAAC,QAAQ,CAAC;QACrB,OAAO,IAAI,CAAC;IACd,CAAC;IACD,IAAI,OAAO,CAAC;IACZ,IAAI,CAAC;QACH,OAAO,GAAG,MAAM,OAAO,CAAC,GAAG,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;IACxD,CAAC;IAAC,MAAM,CAAC;QACP,qEAAqE;QACrE,mEAAmE;QACnE,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC;QACtB,OAAO,IAAI,CAAC,QAAQ,CAAC;QACrB,OAAO,IAAI,CAAC;IACd,CAAC;IACD,sEAAsE;IACtE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;QACpB,MAAM,EAAE,GAAG,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QACnC,MAAM,EAAE,GAAG,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QACnC,IAAI,EAAE,KAAK,EAAE;YAAE,OAAO,EAAE,GAAG,EAAE,CAAC;QAC9B,OAAO,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,EAAE,SAAS,EAAE,EAAE,WAAW,EAAE,MAAM,EAAE,CAAC,CAAC;IAC1E,CAAC,CAAC,CAAC;IACH,KAAK,MAAM,GAAG,IAAI,OAAO,EAAE,CAAC;QAC1B,IAAI,GAAG,CAAC,WAAW,EAAE,IAAI,cAAc,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC;YAAE,SAAS;QAChE,MAAM,QAAQ,GAAG,OAAO,KAAK,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,OAAO,GAAG,GAAG,GAAG,GAAG,CAAC,IAAI,EAAE,CAAC;QAC3E,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,CAAC,IAAI,CAAC,CAAC;QACrC,IAAI,GAAG,CAAC,WAAW,EAAE,EAAE,CAAC;YACtB,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,QAAQ,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,GAAG,CAAC,EAAE,QAAQ,CAAC,CAAC;YACtE,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC;QAC3B,CAAC;aAAM,IAAI,GAAG,CAAC,MAAM,EAAE,EAAE,CAAC;YACxB,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC;gBAClB,IAAI,EAAE,GAAG,CAAC,IAAI;gBACd,IAAI,EAAE,QAAQ;gBACd,IAAI,EAAE,MAAM;aACb,CAAC,CAAC;QACL,CAAC;QACD,sEAAsE;QACtE,iEAAiE;QACjE,mBAAmB;IACrB,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAcD;;;;;;;;;;;;GAYG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,QAAgB;IACjD,MAAM,IAAI,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;IAC/B,MAAM,EAAE,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;IACnD,IAAI,CAAC,EAAE,EAAE,WAAW,EAAE;QAAE,MAAM,IAAI,aAAa,CAAC,IAAI,CAAC,CAAC;IACtD,MAAM,GAAG,GAAa,EAAE,CAAC;IACzB,MAAM,QAAQ,CAAC,IAAI,EAAE,IAAI,EAAE,EAAE,EAAE,GAAG,CAAC,CAAC;IACpC,OAAO,GAAG,CAAC;AACb,CAAC;AAED,KAAK,UAAU,QAAQ,CAAC,GAAW,EAAE,IAAY,EAAE,OAAe,EAAE,GAAa;IAC/E,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,GAAG,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC;IAC5E,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;QAC5B,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC;QACxB,IAAI,KAAK,CAAC,WAAW,EAAE,EAAE,CAAC;YACxB,IAAI,cAAc,CAAC,GAAG,CAAC,IAAI,CAAC;gBAAE,SAAS;YACvC,MAAM,QAAQ,CAAC,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,EAAE,IAAI,EAAE,OAAO,KAAK,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,OAAO,IAAI,IAAI,EAAE,EAAE,GAAG,CAAC,CAAC;QAC3F,CAAC;aAAM,IAAI,KAAK,CAAC,MAAM,EAAE,EAAE,CAAC;YAC1B,GAAG,CAAC,IAAI,CAAC,OAAO,KAAK,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,OAAO,IAAI,IAAI,EAAE,CAAC,CAAC;QACzD,CAAC;QACD,gEAAgE;QAChE,+DAA+D;QAC/D,2CAA2C;IAC7C,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,QAAQ,CAAC,OAAe,EAAE,IAAY;IAC1D,MAAM,QAAQ,GAAG,MAAM,cAAc,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;IACrD,MAAM,EAAE,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;IACvD,IAAI,EAAE,KAAK,SAAS;QAAE,MAAM,IAAI,aAAa,CAAC,QAAQ,CAAC,CAAC;IACxD,IAAI,CAAC,EAAE,CAAC,MAAM,EAAE;QAAE,MAAM,IAAI,aAAa,CAAC,QAAQ,CAAC,CAAC;IACpD,IAAI,EAAE,CAAC,IAAI,GAAG,cAAc;QAAE,MAAM,IAAI,iBAAiB,CAAC,QAAQ,EAAE,EAAE,CAAC,IAAI,EAAE,cAAc,CAAC,CAAC;IAC7F,MAAM,GAAG,GAAG,MAAM,UAAU,CAAC,QAAQ,CAAC,CAAC;IACvC,MAAM,MAAM,GAAG,WAAW,CAAC,GAAG,CAAC,CAAC;IAChC,OAAO;QACL,IAAI,EAAE,QAAQ;QACd,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,QAAQ,CAAC,MAAM,CAAC;QAC3C,IAAI,EAAE,EAAE,CAAC,IAAI;QACb,QAAQ,EAAE,cAAc,CAAC,QAAQ,CAAC;QAClC,MAAM;KACP,CAAC;AACJ,CAAC;AAED;;;;GAIG;AACH,SAAS,WAAW,CAAC,GAAW;IAC9B,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;IACzC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,EAAE,CAAC,EAAE,EAAE,CAAC;QAC/B,IAAI,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC;YAAE,OAAO,IAAI,CAAC;IAChC,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAsBD,MAAM,CAAC,KAAK,UAAU,kBAAkB,CACtC,OAAe,EACf,IAAY;IAEZ,MAAM,QAAQ,GAAG,MAAM,cAAc,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;IACrD,MAAM,EAAE,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;IACvD,IAAI,EAAE,KAAK,SAAS;QAAE,MAAM,IAAI,aAAa,CAAC,QAAQ,CAAC,CAAC;IACxD,IAAI,CAAC,EAAE,CAAC,MAAM,EAAE;QAAE,MAAM,IAAI,aAAa,CAAC,QAAQ,CAAC,CAAC;IACpD,iEAAiE;IACjE,kEAAkE;IAClE,yBAAyB;IACzB,MAAM,EAAE,GAAG,MAAM,MAAM,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC;IACvC,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAC/B,MAAM,EAAE,SAAS,EAAE,GAAG,MAAM,EAAE,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;QACrD,OAAO;YACL,IAAI,EAAE,QAAQ;YACd,IAAI,EAAE,EAAE,CAAC,IAAI;YACb,MAAM,EAAE,WAAW,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,EAAE,SAAS,CAAC,CAAC;SAChD,CAAC;IACJ,CAAC;YAAS,CAAC;QACT,MAAM,EAAE,CAAC,KAAK,EAAE,CAAC;IACnB,CAAC;AACH,CAAC;AAED,uEAAuE;AAEvE,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,OAAe,EAAE,IAAY,EAAE,OAAe;IAC5E,MAAM,QAAQ,GAAG,MAAM,cAAc,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;IACrD,oEAAoE;IACpE,sEAAsE;IACtE,+DAA+D;IAC/D,4DAA4D;IAC5D,MAAM,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACpD,qEAAqE;IACrE,uEAAuE;IACvE,uBAAuB;IACvB,MAAM,GAAG,GAAG,GAAG,QAAQ,IAAI,UAAU,EAAE,MAAM,CAAC;IAC9C,MAAM,WAAW,CAAC,GAAG,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC;IACxC,MAAM,QAAQ,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC;AAChC,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,OAAe,EACf,IAAY;IAKZ,MAAM,QAAQ,GAAG,MAAM,cAAc,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;IACrD,MAAM,EAAE,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;IACvD,IAAI,EAAE,KAAK,SAAS;QAAE,MAAM,IAAI,aAAa,CAAC,QAAQ,CAAC,CAAC;IACxD,IAAI,EAAE,CAAC,MAAM,EAAE,EAAE,CAAC;QAChB,OAAO;YACL,IAAI,EAAE,MAAM;YACZ,QAAQ,EAAE,QAAQ,CAAC,QAAQ,CAAC;YAC5B,IAAI,EAAE,EAAE,CAAC,IAAI;YACb,MAAM,EAAE,gBAAgB,CAAC,QAAQ,CAAC;SACnC,CAAC;IACJ,CAAC;IACD,IAAI,EAAE,CAAC,WAAW,EAAE,EAAE,CAAC;QACrB,MAAM,OAAO,GAAG,QAAQ,CAAC,QAAQ,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;QAC/E,6DAA6D;QAC7D,4DAA4D;QAC5D,+DAA+D;QAC/D,oBAAoB;QACpB,MAAM,MAAM,GAAG,SAAS,CACtB;YACE,IAAI,EAAE,IAAI;YACV,GAAG,EAAE,OAAO,CAAC,QAAQ,CAAC;YACtB,QAAQ,EAAE,IAAI;YACd,qEAAqE;YACrE,iEAAiE;YACjE,+DAA+D;YAC/D,iEAAiE;YACjE,mDAAmD;YACnD,MAAM,EAAE,KAAK;YACb,MAAM,EAAE,CAAC,IAAY,EAAE,EAAE;gBACvB,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC;oBACvC,IAAI,cAAc,CAAC,GAAG,CAAC,IAAI,CAAC;wBAAE,OAAO,KAAK,CAAC;gBAC7C,CAAC;gBACD,OAAO,IAAI,CAAC;YACd,CAAC;SACF,EACD,CAAC,OAAO,CAAC,CACa,CAAC;QACzB,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,QAAQ,EAAE,GAAG,OAAO,SAAS,EAAE,MAAM,EAAE,CAAC;IACtE,CAAC;IACD,MAAM,IAAI,aAAa,CAAC,QAAQ,CAAC,CAAC;AACpC,CAAC;AAED;;;;;;;;;;;;;;GAcG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,aAAqB,EACrB,IAAY,EACZ,IAAY,EACZ,MAA0C,EAC1C,IAAuD;IAEvD,MAAM,MAAM,GAAG,MAAM,cAAc,CAAC,aAAa,EAAE,IAAI,CAAC,CAAC;IACzD,MAAM,OAAO,GAAG,YAAY,CAAC,IAAI,CAAC,CAAC;IACnC,MAAM,MAAM,GAAG,MAAM,cAAc,CAAC,IAAI,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,IAAI,CAAC,CAAC;IACjE,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;IAC3D,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;QAC3B,IAAI,IAAI,EAAE,SAAS,KAAK,IAAI;YAAE,MAAM,IAAI,iBAAiB,CAAC,MAAM,CAAC,CAAC;QAClE,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE;YAAE,MAAM,IAAI,gBAAgB,CAAC,uBAAuB,CAAC,CAAC;IAC9E,CAAC;IACD,MAAM,KAAK,CAAC,MAAM,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACzC,MAAM,GAAG,GAAG,GAAG,MAAM,IAAI,UAAU,EAAE,aAAa,CAAC;IACnD,MAAM,IAAI,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAC;IAClC,IAAI,IAAI,GAAG,CAAC,CAAC;IACb,MAAM,GAAG,GAAG,iBAAiB,CAAC,GAAG,CAAC,CAAC;IACnC,IAAI,CAAC;QACH,IAAI,KAAK,EAAE,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;YACjC,MAAM,GAAG,GAAG,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YAChE,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YACjB,IAAI,IAAI,GAAG,CAAC,UAAU,CAAC;YACvB,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC;gBAAE,MAAM,IAAI,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;QAChD,CAAC;QACD,GAAG,CAAC,GAAG,EAAE,CAAC;QACV,MAAM,IAAI,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;IAC3B,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,GAAG,CAAC,OAAO,EAAE,CAAC;QACd,MAAM,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;QACzC,MAAM,GAAG,CAAC;IACZ,CAAC;IACD,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IAClC,MAAM,QAAQ,GAAG,IAAI,EAAE,cAAc,EAAE,WAAW,EAAE,CAAC;IACrD,IAAI,QAAQ,KAAK,SAAS,IAAI,QAAQ,KAAK,MAAM,EAAE,CAAC;QAClD,MAAM,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;QACzC,MAAM,IAAI,qBAAqB,CAAC,MAAM,EAAE,QAAQ,EAAE,MAAM,CAAC,CAAC;IAC5D,CAAC;IACD,MAAM,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;IAC5B,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC;AAChD,CAAC;AAED,uEAAuE;AAEvE,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,aAAqB,EACrB,IAAY,EACZ,IAAY;IAEZ,MAAM,OAAO,GAAG,YAAY,CAAC,IAAI,CAAC,CAAC;IACnC,MAAM,MAAM,GAAG,MAAM,cAAc,CAAC,aAAa,EAAE,IAAI,CAAC,CAAC;IACzD,MAAM,MAAM,GAAG,MAAM,cAAc,CAAC,IAAI,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,IAAI,CAAC,CAAC;IACjE,uEAAuE;IACvE,wDAAwD;IACxD,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;IACzD,IAAI,MAAM,KAAK,SAAS;QAAE,MAAM,IAAI,iBAAiB,CAAC,MAAM,CAAC,CAAC;IAC9D,MAAM,KAAK,CAAC,MAAM,EAAE,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC,CAAC;IAC1C,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,+EAA+E;AAE/E,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,OAAe,EAAE,IAAY,EAAE,OAAe;IAC9E,MAAM,QAAQ,GAAG,MAAM,cAAc,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;IACrD,MAAM,OAAO,GAAG,YAAY,CAAC,OAAO,CAAC,CAAC;IACtC,MAAM,MAAM,GAAG,MAAM,cAAc,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC,EAAE,IAAI,CAAC,CAAC;IAC5E,MAAM,EAAE,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;IACvD,IAAI,EAAE,KAAK,SAAS;QAAE,MAAM,IAAI,aAAa,CAAC,QAAQ,CAAC,CAAC;IACxD,IAAI,QAAQ,KAAK,MAAM;QAAE,OAAO,MAAM,CAAC;IACvC,sEAAsE;IACtE,qEAAqE;IACrE,kEAAkE;IAClE,iEAAiE;IACjE,mEAAmE;IACnE,iEAAiE;IACjE,EAAE;IACF,mEAAmE;IACnE,mEAAmE;IACnE,iEAAiE;IACjE,mEAAmE;IACnE,gEAAgE;IAChE,iEAAiE;IACjE,8DAA8D;IAC9D,YAAY;IACZ,IAAI,QAAQ,CAAC,WAAW,EAAE,KAAK,MAAM,CAAC,WAAW,EAAE,EAAE,CAAC;QACpD,MAAM,GAAG,GAAG,GAAG,QAAQ,YAAY,UAAU,EAAE,EAAE,CAAC;QAClD,MAAM,QAAQ,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC;QAC9B,IAAI,CAAC;YACH,wDAAwD;YACxD,8DAA8D;YAC9D,0DAA0D;YAC1D,mCAAmC;YACnC,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;YAC3D,IAAI,QAAQ,KAAK,SAAS;gBAAE,MAAM,IAAI,iBAAiB,CAAC,MAAM,CAAC,CAAC;YAChE,MAAM,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;QAC9B,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,2DAA2D;YAC3D,8DAA8D;YAC9D,4DAA4D;YAC5D,yDAAyD;YACzD,WAAW;YACX,MAAM,QAAQ,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;YACrD,MAAM,GAAG,CAAC;QACZ,CAAC;QACD,OAAO,MAAM,CAAC;IAChB,CAAC;IACD,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;IACzD,IAAI,MAAM,KAAK,SAAS;QAAE,MAAM,IAAI,iBAAiB,CAAC,MAAM,CAAC,CAAC;IAC9D,MAAM,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;IACjC,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,SAAS,CAC7B,UAAkB,EAClB,WAAmB,EACnB,IAAY;IAEZ,MAAM,GAAG,GAAG,MAAM,cAAc,CAAC,UAAU,EAAE,IAAI,CAAC,CAAC;IACnD,MAAM,IAAI,GAAG,MAAM,cAAc,CAAC,WAAW,EAAE,IAAI,CAAC,CAAC;IACrD,MAAM,EAAE,GAAG,MAAM,IAAI,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;IAClD,IAAI,EAAE,KAAK,SAAS;QAAE,MAAM,IAAI,aAAa,CAAC,GAAG,CAAC,CAAC;IACnD,+DAA+D;IAC/D,IAAI,EAAE,CAAC,WAAW,EAAE,EAAE,CAAC;QACrB,MAAM,GAAG,GAAG,QAAQ,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;QAChC,IAAI,GAAG,KAAK,EAAE,IAAI,CAAC,CAAC,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,KAAK,GAAG,EAAE,CAAC,CAAC,EAAE,CAAC;YACzE,MAAM,IAAI,gBAAgB,CAAC,qCAAqC,CAAC,CAAC;QACpE,CAAC;IACH,CAAC;IACD,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;IACvD,IAAI,MAAM,KAAK,SAAS;QAAE,MAAM,IAAI,iBAAiB,CAAC,IAAI,CAAC,CAAC;IAC5D,MAAM,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAChD,MAAM,QAAQ,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;IAC1B,OAAO,IAAI,CAAC;AACd,CAAC;AAED,wEAAwE;AAExE,MAAM,CAAC,KAAK,UAAU,WAAW,CAC/B,OAAe,EACf,IAAY,EACZ,IAA8B;IAE9B,MAAM,QAAQ,GAAG,MAAM,cAAc,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;IACrD,qEAAqE;IACrE,sEAAsE;IACtE,IAAI,QAAQ,KAAK,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;QAC/B,MAAM,IAAI,oBAAoB,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;IAChD,CAAC;IACD,MAAM,EAAE,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;IACvD,IAAI,EAAE,KAAK,SAAS;QAAE,MAAM,IAAI,aAAa,CAAC,QAAQ,CAAC,CAAC;IACxD,IAAI,EAAE,CAAC,WAAW,EAAE,EAAE,CAAC;QACrB,kEAAkE;QAClE,gEAAgE;QAChE,mEAAmE;QACnE,+DAA+D;QAC/D,kEAAkE;QAClE,IAAI,IAAI,EAAE,SAAS,KAAK,IAAI,EAAE,CAAC;YAC7B,MAAM,EAAE,CAAC,QAAQ,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC;YACtD,OAAO;QACT,CAAC;QACD,IAAI,CAAC;YACH,MAAM,KAAK,CAAC,QAAQ,CAAC,CAAC;QACxB,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,IAAK,GAA6B,CAAC,IAAI,KAAK,WAAW,EAAE,CAAC;gBACxD,MAAM,IAAI,sBAAsB,CAAC,QAAQ,CAAC,CAAC;YAC7C,CAAC;YACD,MAAM,GAAG,CAAC;QACZ,CAAC;IACH,CAAC;SAAM,CAAC;QACN,MAAM,EAAE,CAAC,QAAQ,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC;IACvC,CAAC;AACH,CAAC;AAED,oFAAoF;AAEpF,MAAM,WAAW,GAA2B;IAC1C,KAAK,EAAE,YAAY;IACnB,MAAM,EAAE,YAAY;IACpB,KAAK,EAAE,YAAY;IACnB,MAAM,EAAE,YAAY;IACpB,MAAM,EAAE,YAAY;IACpB,MAAM,EAAE,YAAY;IACpB,KAAK,EAAE,QAAQ;IACf,MAAM,EAAE,QAAQ;IAChB,KAAK,EAAE,MAAM;IACb,MAAM,EAAE,KAAK;IACb,KAAK,EAAE,KAAK;IACZ,MAAM,EAAE,KAAK;IACb,IAAI,EAAE,GAAG;IACT,IAAI,EAAE,GAAG;IACT,MAAM,EAAE,KAAK;IACb,OAAO,EAAE,MAAM;IACf,KAAK,EAAE,QAAQ;IACf,MAAM,EAAE,QAAQ;IAChB,KAAK,EAAE,IAAI;IACX,KAAK,EAAE,MAAM;IACb,MAAM,EAAE,KAAK;IACb,KAAK,EAAE,QAAQ;IACf,QAAQ,EAAE,OAAO;IACjB,MAAM,EAAE,KAAK;IACb,OAAO,EAAE,MAAM;IACf,OAAO,EAAE,MAAM;IACf,OAAO,EAAE,KAAK;IACd,OAAO,EAAE,MAAM;IACf,MAAM,EAAE,MAAM;IACd,MAAM,EAAE,KAAK;IACb,MAAM,EAAE,KAAK;IACb,QAAQ,EAAE,KAAK;IACf,OAAO,EAAE,MAAM;IACf,QAAQ,EAAE,MAAM;IAChB,OAAO,EAAE,MAAM;IACf,MAAM,EAAE,MAAM;IACd,OAAO,EAAE,MAAM;IACf,KAAK,EAAE,UAAU;IACjB,WAAW,EAAE,UAAU;IACvB,KAAK,EAAE,OAAO;IACd,OAAO,EAAE,OAAO;IAChB,MAAM,EAAE,OAAO;IACf,OAAO,EAAE,OAAO;IAChB,MAAM,EAAE,KAAK;IACb,aAAa,EAAE,YAAY;IAC3B,aAAa;IACb,QAAQ,EAAE,QAAQ;IAClB,SAAS,EAAE,QAAQ;IACnB,KAAK,EAAE,QAAQ;IACf,sBAAsB;IACtB,MAAM,EAAE,YAAY;IACpB,MAAM,EAAE,YAAY;IACpB,MAAM,EAAE,YAAY;IACpB,OAAO,EAAE,YAAY;IACrB,aAAa,EAAE,YAAY;IAC3B,YAAY,EAAE,MAAM;IACpB,mBAAmB;IACnB,MAAM,EAAE,KAAK;IACb,KAAK,EAAE,MAAM;IACb,KAAK,EAAE,MAAM;IACb,IAAI,EAAE,GAAG;IACT,MAAM,EAAE,YAAY;IACpB,OAAO,EAAE,YAAY;IACrB,eAAe;IACf,OAAO,EAAE,MAAM;IACf,QAAQ,EAAE,MAAM;IAChB,mBAAmB;IACnB,MAAM,EAAE,SAAS;IACjB,OAAO,EAAE,SAAS;IAClB,OAAO,EAAE,SAAS;IAClB,MAAM,EAAE,SAAS;IACjB,QAAQ,EAAE,OAAO;IACjB,KAAK,EAAE,OAAO;IACd,SAAS,EAAE,QAAQ;IACnB,SAAS,EAAE,QAAQ;IACnB,KAAK,EAAE,SAAS;IAChB,KAAK,EAAE,OAAO;IACd,MAAM,EAAE,OAAO;IACf,eAAe;IACf,UAAU,EAAE,SAAS;IACrB,MAAM,EAAE,SAAS;IACjB,QAAQ,EAAE,UAAU;IACpB,QAAQ;IACR,QAAQ,EAAE,OAAO;IACjB,KAAK,EAAE,UAAU;CAClB,CAAC;AAEF,SAAS,cAAc,CAAC,OAAe;IACrC,MAAM,IAAI,GAAG,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,IAAI,OAAO,CAAC;IACjD,iEAAiE;IACjE,6DAA6D;IAC7D,IAAI,IAAI,KAAK,YAAY,IAAI,IAAI,CAAC,QAAQ,CAAC,aAAa,CAAC;QAAE,OAAO,YAAY,CAAC;IAC/E,IAAI,IAAI,KAAK,UAAU,IAAI,IAAI,KAAK,UAAU,IAAI,IAAI,KAAK,aAAa;QAAE,OAAO,UAAU,CAAC;IAC5F,IAAI,IAAI,KAAK,YAAY;QAAE,OAAO,OAAO,CAAC;IAC1C,IAAI,IAAI,KAAK,MAAM,IAAI,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC;QAAE,OAAO,YAAY,CAAC;IACrE,IACE,IAAI,KAAK,YAAY;QACrB,IAAI,KAAK,eAAe;QACxB,IAAI,KAAK,YAAY;QACrB,IAAI,KAAK,iBAAiB;QAC1B,IAAI,KAAK,eAAe,EACxB,CAAC;QACD,OAAO,YAAY,CAAC;IACtB,CAAC;IACD,IAAI,IAAI,KAAK,gBAAgB;QAAE,OAAO,OAAO,CAAC;IAC9C,MAAM,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,WAAW,EAAE,CAAC;IACxC,OAAO,WAAW,CAAC,GAAG,CAAC,IAAI,WAAW,CAAC;AACzC,CAAC"}
|
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
import { extname, join } from "node:path";
|
|
2
|
+
import { checkFileReference, readFile } from "./file-manager.js";
|
|
3
|
+
/**
|
|
4
|
+
* Process `@<path>` references in user input. The chat input's
|
|
5
|
+
* `@`-autocomplete inserts these markers; this helper transforms them
|
|
6
|
+
* server-side before the prompt reaches pi's `session.prompt()`.
|
|
7
|
+
*
|
|
8
|
+
* Threshold-based design: small files get inlined as fenced code blocks
|
|
9
|
+
* (the model has the content immediately, no tool round-trip); large
|
|
10
|
+
* files stay as the literal `@<path>` reference (the model loads what
|
|
11
|
+
* it needs via its read/grep/find tools, no context-burn on a 50 MB
|
|
12
|
+
* log we'd otherwise inhale wholesale).
|
|
13
|
+
*
|
|
14
|
+
* The chat UI renders BOTH forms as collapsed file badges in the user
|
|
15
|
+
* message bubble, so visually the user sees a chip either way; the
|
|
16
|
+
* difference is purely whether the LLM has the content in-prompt or
|
|
17
|
+
* has to fetch it.
|
|
18
|
+
*
|
|
19
|
+
* Behaviour:
|
|
20
|
+
* - Markers must be at start-of-string OR preceded by whitespace
|
|
21
|
+
* (avoid expanding `email@example.com`).
|
|
22
|
+
* - Two path forms accepted:
|
|
23
|
+
* `@<path>` — greedy non-whitespace; common case.
|
|
24
|
+
* `@"<path with spaces>"` — anything that isn't a `"` or newline.
|
|
25
|
+
* - Resolved against the project's workspace root via file-manager's
|
|
26
|
+
* path-traversal-safe `checkFileReference`. Three outcomes:
|
|
27
|
+
* inline → file ≤ INLINE_THRESHOLD; replace marker with a fenced
|
|
28
|
+
* code block. Language hint derived from extension.
|
|
29
|
+
* defer → file > INLINE_THRESHOLD; leave the literal `@<path>`
|
|
30
|
+
* reference for the model to load on demand.
|
|
31
|
+
* error → missing / outside root / directory / binary. Replace
|
|
32
|
+
* marker with `[@<path> not included: <reason>]` so
|
|
33
|
+
* neither user nor model is left guessing.
|
|
34
|
+
*
|
|
35
|
+
* Multiple markers in one prompt all process independently.
|
|
36
|
+
*/
|
|
37
|
+
/**
|
|
38
|
+
* Inlining cutoff. Files at or under this byte count are inlined as
|
|
39
|
+
* fenced blocks; larger files are left as `@<path>` for the model to
|
|
40
|
+
* fetch. 128 KB is roughly 32K tokens — small enough to be safe in a
|
|
41
|
+
* 200K-token context window and large enough to cover most real
|
|
42
|
+
* source files (a 1k-line TS file is typically ~50 KB).
|
|
43
|
+
*/
|
|
44
|
+
const INLINE_THRESHOLD_BYTES = 128 * 1024;
|
|
45
|
+
/**
|
|
46
|
+
* Regex shared by `findRefs` and `parseFileReferences`. Match `@` at
|
|
47
|
+
* start-or-after-whitespace then either a `"path with spaces"` quoted
|
|
48
|
+
* form or a bare non-whitespace token.
|
|
49
|
+
*
|
|
50
|
+
* The bare alternation is lazy + uses a lookahead so trailing
|
|
51
|
+
* sentence punctuation (`?`, `,`, `;`, `:`, `!`, `)`, `]`) followed by
|
|
52
|
+
* whitespace or end-of-string isn't pulled into the path. Without
|
|
53
|
+
* this, `@README.md?` matches `README.md?` and the server can't
|
|
54
|
+
* resolve the file. The `.` is intentionally NOT in the strip set
|
|
55
|
+
* because dots are common in filenames (`README.md`, `tsconfig.json`)
|
|
56
|
+
* — users who want a literal trailing period should use the quoted
|
|
57
|
+
* form (`@"file.txt".`), same escape hatch as filenames with spaces.
|
|
58
|
+
*/
|
|
59
|
+
const REF_RE = /(^|\s)@(?:"([^"\n]+)"|([^\s]+?))(?=[?,;:!)\]]?(?:\s|$))/g;
|
|
60
|
+
function findRefs(text) {
|
|
61
|
+
const matches = [];
|
|
62
|
+
let m;
|
|
63
|
+
// Reset the regex state between calls — REF_RE is module-level with
|
|
64
|
+
// the `g` flag, so it carries `lastIndex` across invocations.
|
|
65
|
+
REF_RE.lastIndex = 0;
|
|
66
|
+
while ((m = REF_RE.exec(text)) !== null) {
|
|
67
|
+
matches.push({
|
|
68
|
+
start: m.index,
|
|
69
|
+
end: m.index + m[0].length,
|
|
70
|
+
lead: m[1] ?? "",
|
|
71
|
+
path: m[2] ?? m[3] ?? "",
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
return matches;
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Parse `@<path>` references out of a text without touching it. Used
|
|
78
|
+
* by the chat input to surface badges of what's about to be sent.
|
|
79
|
+
*/
|
|
80
|
+
export function parseFileReferences(text) {
|
|
81
|
+
return findRefs(text).map((m) => m.path);
|
|
82
|
+
}
|
|
83
|
+
export async function expandFileReferences(text, workspacePath) {
|
|
84
|
+
const matches = findRefs(text);
|
|
85
|
+
if (matches.length === 0)
|
|
86
|
+
return text;
|
|
87
|
+
const outcomes = await Promise.all(matches.map(async (mm) => {
|
|
88
|
+
try {
|
|
89
|
+
const abs = join(workspacePath, mm.path);
|
|
90
|
+
// Cheap up-front check (path safety + stat + 8 KB sniff) so we
|
|
91
|
+
// can decide inline-vs-defer without reading large files.
|
|
92
|
+
const check = await checkFileReference(abs, workspacePath);
|
|
93
|
+
if (check.binary)
|
|
94
|
+
return { kind: "error", reason: "binary file" };
|
|
95
|
+
if (check.size > INLINE_THRESHOLD_BYTES)
|
|
96
|
+
return { kind: "defer" };
|
|
97
|
+
// Small enough to inline — read the whole file and emit a
|
|
98
|
+
// fenced block.
|
|
99
|
+
const result = await readFile(abs, workspacePath);
|
|
100
|
+
if (result.binary)
|
|
101
|
+
return { kind: "error", reason: "binary file" };
|
|
102
|
+
return { kind: "inline", text: formatExpansion(mm.path, result.content) };
|
|
103
|
+
}
|
|
104
|
+
catch (err) {
|
|
105
|
+
const e = err;
|
|
106
|
+
if (e.name === "FileTooLargeError") {
|
|
107
|
+
// readFile's own 5 MB cap fired — defer to model tool use.
|
|
108
|
+
// Shouldn't normally hit this since the size-check above
|
|
109
|
+
// catches anything bigger than INLINE_THRESHOLD_BYTES, but
|
|
110
|
+
// belt-and-suspenders for cases where the file grew between
|
|
111
|
+
// check and read.
|
|
112
|
+
return { kind: "defer" };
|
|
113
|
+
}
|
|
114
|
+
if (e.name === "NotFoundError" || e.code === "ENOENT") {
|
|
115
|
+
return { kind: "error", reason: "file not found" };
|
|
116
|
+
}
|
|
117
|
+
if (e.name === "PathOutsideRootError") {
|
|
118
|
+
return { kind: "error", reason: "path is outside the project root" };
|
|
119
|
+
}
|
|
120
|
+
if (e.name === "NotAFileError") {
|
|
121
|
+
return { kind: "error", reason: "path is a directory, not a file" };
|
|
122
|
+
}
|
|
123
|
+
return { kind: "error", reason: "unreadable" };
|
|
124
|
+
}
|
|
125
|
+
}));
|
|
126
|
+
// Walk in reverse so earlier indices stay valid as we splice.
|
|
127
|
+
let out = text;
|
|
128
|
+
for (let i = matches.length - 1; i >= 0; i--) {
|
|
129
|
+
const outcome = outcomes[i];
|
|
130
|
+
const mm = matches[i];
|
|
131
|
+
if (outcome === undefined || mm === undefined)
|
|
132
|
+
continue;
|
|
133
|
+
const before = out.slice(0, mm.start) + mm.lead;
|
|
134
|
+
const after = out.slice(mm.end);
|
|
135
|
+
// Re-emit the marker (preserve quoting if path has whitespace) so
|
|
136
|
+
// the user's prose still reads "look at @src/foo.ts and explain"
|
|
137
|
+
// after expansion. Previously the inline branch dropped the marker
|
|
138
|
+
// entirely and only kept the fenced block, which broke the flow of
|
|
139
|
+
// the surrounding sentence in the chat history.
|
|
140
|
+
const marker = /\s/.test(mm.path) ? `@"${mm.path}"` : `@${mm.path}`;
|
|
141
|
+
if (outcome.kind === "inline") {
|
|
142
|
+
out = `${before}${marker}\n${outcome.text}\n${after}`;
|
|
143
|
+
}
|
|
144
|
+
else if (outcome.kind === "defer") {
|
|
145
|
+
out = `${before}${marker}${after}`;
|
|
146
|
+
}
|
|
147
|
+
else {
|
|
148
|
+
out = `${before}[${marker} not included: ${outcome.reason}]${after}`;
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
return out;
|
|
152
|
+
}
|
|
153
|
+
function formatExpansion(path, content) {
|
|
154
|
+
const lang = languageHintForPath(path);
|
|
155
|
+
// Pick a fence longer than any backtick run inside the content so
|
|
156
|
+
// the block can't be terminated by source that itself contains
|
|
157
|
+
// ``` (markdown / docs files do this).
|
|
158
|
+
const fence = pickFence(content);
|
|
159
|
+
return `${fence}${lang} file: ${path}\n${content}\n${fence}`;
|
|
160
|
+
}
|
|
161
|
+
function pickFence(content) {
|
|
162
|
+
let max = 0;
|
|
163
|
+
let run = 0;
|
|
164
|
+
for (const ch of content) {
|
|
165
|
+
if (ch === "`") {
|
|
166
|
+
run += 1;
|
|
167
|
+
if (run > max)
|
|
168
|
+
max = run;
|
|
169
|
+
}
|
|
170
|
+
else {
|
|
171
|
+
run = 0;
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
return "`".repeat(Math.max(3, max + 1));
|
|
175
|
+
}
|
|
176
|
+
const LANG_BY_EXT = {
|
|
177
|
+
".ts": "ts",
|
|
178
|
+
".tsx": "tsx",
|
|
179
|
+
".js": "js",
|
|
180
|
+
".jsx": "jsx",
|
|
181
|
+
".mjs": "js",
|
|
182
|
+
".cjs": "js",
|
|
183
|
+
".json": "json",
|
|
184
|
+
".py": "python",
|
|
185
|
+
".rb": "ruby",
|
|
186
|
+
".go": "go",
|
|
187
|
+
".rs": "rust",
|
|
188
|
+
".java": "java",
|
|
189
|
+
".kt": "kotlin",
|
|
190
|
+
".swift": "swift",
|
|
191
|
+
".c": "c",
|
|
192
|
+
".h": "c",
|
|
193
|
+
".cpp": "cpp",
|
|
194
|
+
".cc": "cpp",
|
|
195
|
+
".hpp": "cpp",
|
|
196
|
+
".cs": "csharp",
|
|
197
|
+
".php": "php",
|
|
198
|
+
".sh": "bash",
|
|
199
|
+
".bash": "bash",
|
|
200
|
+
".zsh": "bash",
|
|
201
|
+
".yml": "yaml",
|
|
202
|
+
".yaml": "yaml",
|
|
203
|
+
".toml": "toml",
|
|
204
|
+
".md": "markdown",
|
|
205
|
+
".html": "html",
|
|
206
|
+
".css": "css",
|
|
207
|
+
".scss": "scss",
|
|
208
|
+
".sql": "sql",
|
|
209
|
+
".xml": "xml",
|
|
210
|
+
};
|
|
211
|
+
export function languageHintForPath(path) {
|
|
212
|
+
const ext = extname(path).toLowerCase();
|
|
213
|
+
return LANG_BY_EXT[ext] ?? "";
|
|
214
|
+
}
|
|
215
|
+
//# sourceMappingURL=file-references.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"file-references.js","sourceRoot":"","sources":["../src/file-references.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,385 @@
|
|
|
1
|
+
import { execFile, spawn } from "node:child_process";
|
|
2
|
+
import { readFile, readdir, stat } from "node:fs/promises";
|
|
3
|
+
import { join, relative, resolve } from "node:path";
|
|
4
|
+
import { promisify } from "node:util";
|
|
5
|
+
import { MAX_READ_BYTES, SEARCH_SKIP_DIRS } from "./file-manager.js";
|
|
6
|
+
const execFileAsync = promisify(execFile);
|
|
7
|
+
/* ----------------------------- detection ----------------------------- */
|
|
8
|
+
let cachedRipgrepAvailable;
|
|
9
|
+
export async function ripgrepAvailable() {
|
|
10
|
+
if (cachedRipgrepAvailable !== undefined)
|
|
11
|
+
return cachedRipgrepAvailable;
|
|
12
|
+
try {
|
|
13
|
+
await execFileAsync("rg", ["--version"], { timeout: 2_000 });
|
|
14
|
+
cachedRipgrepAvailable = true;
|
|
15
|
+
}
|
|
16
|
+
catch {
|
|
17
|
+
// ENOENT (not installed), timeout, non-zero exit — all collapse to
|
|
18
|
+
// "no". A single warn-once log lives at the route layer so the
|
|
19
|
+
// operator notices a busted install.
|
|
20
|
+
cachedRipgrepAvailable = false;
|
|
21
|
+
}
|
|
22
|
+
return cachedRipgrepAvailable;
|
|
23
|
+
}
|
|
24
|
+
/** Reset the detection cache. Test-only; do not call from app code. */
|
|
25
|
+
export function _resetRipgrepCache() {
|
|
26
|
+
cachedRipgrepAvailable = undefined;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Thrown when a search mode requires the ripgrep engine that isn't
|
|
30
|
+
* available on this host. Specifically: regex queries against the
|
|
31
|
+
* Node fallback engine are vulnerable to ReDoS (catastrophic
|
|
32
|
+
* backtracking pegs the event loop for the entire opts.timeoutMs
|
|
33
|
+
* window — the timeout is checked between iterations, not inside the
|
|
34
|
+
* regex engine), so we refuse them rather than silently DoS the
|
|
35
|
+
* server. Substring queries against the Node fallback are fine.
|
|
36
|
+
*/
|
|
37
|
+
export class SearchEngineUnavailableError extends Error {
|
|
38
|
+
constructor(msg) {
|
|
39
|
+
super(msg);
|
|
40
|
+
this.name = "SearchEngineUnavailableError";
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
/* ----------------------------- entry point ----------------------------- */
|
|
44
|
+
export async function searchFiles(projectPath, opts) {
|
|
45
|
+
if (await ripgrepAvailable()) {
|
|
46
|
+
return searchWithRipgrep(projectPath, opts);
|
|
47
|
+
}
|
|
48
|
+
if (opts.regex) {
|
|
49
|
+
throw new SearchEngineUnavailableError("regex search requires ripgrep, which isn't installed on this host");
|
|
50
|
+
}
|
|
51
|
+
return searchInProcess(projectPath, opts);
|
|
52
|
+
}
|
|
53
|
+
async function searchWithRipgrep(projectPath, opts) {
|
|
54
|
+
const args = [
|
|
55
|
+
"--json",
|
|
56
|
+
"--no-heading",
|
|
57
|
+
"--max-filesize",
|
|
58
|
+
"5M",
|
|
59
|
+
// Hard match-count cap as a backstop; we stop reading earlier if we
|
|
60
|
+
// hit our own `limit`, but `--max-count` per file keeps a single
|
|
61
|
+
// pathological file (e.g. `.*` against a 100k-line CSV) from
|
|
62
|
+
// dominating the output.
|
|
63
|
+
"--max-count",
|
|
64
|
+
String(Math.max(1, Math.min(opts.limit, 1000))),
|
|
65
|
+
];
|
|
66
|
+
if (!opts.regex)
|
|
67
|
+
args.push("--fixed-strings");
|
|
68
|
+
if (!opts.caseSensitive)
|
|
69
|
+
args.push("-i");
|
|
70
|
+
if (opts.includeGitignored) {
|
|
71
|
+
// -uu: don't honor .gitignore + show hidden files. We deliberately
|
|
72
|
+
// don't go to -uuu (also includes binary) — the binary-file skip
|
|
73
|
+
// is desired regardless.
|
|
74
|
+
args.push("-uu");
|
|
75
|
+
}
|
|
76
|
+
if (opts.include !== undefined && opts.include.length > 0) {
|
|
77
|
+
args.push("--glob", opts.include);
|
|
78
|
+
}
|
|
79
|
+
if (opts.exclude !== undefined && opts.exclude.length > 0) {
|
|
80
|
+
args.push("--glob", `!${opts.exclude}`);
|
|
81
|
+
}
|
|
82
|
+
args.push("--", opts.query, ".");
|
|
83
|
+
return new Promise((resolveFn) => {
|
|
84
|
+
const matches = [];
|
|
85
|
+
let truncated = false;
|
|
86
|
+
const child = spawn("rg", args, { cwd: projectPath });
|
|
87
|
+
const timer = setTimeout(() => {
|
|
88
|
+
truncated = true;
|
|
89
|
+
child.kill("SIGTERM");
|
|
90
|
+
}, opts.timeoutMs);
|
|
91
|
+
let buf = "";
|
|
92
|
+
let currentFile;
|
|
93
|
+
const finish = () => {
|
|
94
|
+
clearTimeout(timer);
|
|
95
|
+
resolveFn({ engine: "ripgrep", matches, truncated });
|
|
96
|
+
};
|
|
97
|
+
child.stdout.setEncoding("utf8");
|
|
98
|
+
child.stdout.on("data", (chunk) => {
|
|
99
|
+
buf += chunk;
|
|
100
|
+
let nl = buf.indexOf("\n");
|
|
101
|
+
while (nl !== -1) {
|
|
102
|
+
const line = buf.slice(0, nl);
|
|
103
|
+
buf = buf.slice(nl + 1);
|
|
104
|
+
if (line.length > 0)
|
|
105
|
+
handleEvent(line);
|
|
106
|
+
nl = buf.indexOf("\n");
|
|
107
|
+
}
|
|
108
|
+
});
|
|
109
|
+
child.on("error", () => finish()); // ENOENT or fork failure → empty result
|
|
110
|
+
child.on("close", () => finish());
|
|
111
|
+
const handleEvent = (jsonLine) => {
|
|
112
|
+
let event;
|
|
113
|
+
try {
|
|
114
|
+
event = JSON.parse(jsonLine);
|
|
115
|
+
}
|
|
116
|
+
catch {
|
|
117
|
+
// Non-JSON line from ripgrep (shouldn't happen with --json
|
|
118
|
+
// but defensive). Skip without aborting the whole search.
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
121
|
+
if (event.type === "begin") {
|
|
122
|
+
const data = event.data;
|
|
123
|
+
currentFile = data?.path?.text;
|
|
124
|
+
}
|
|
125
|
+
else if (event.type === "match") {
|
|
126
|
+
if (matches.length >= opts.limit) {
|
|
127
|
+
truncated = true;
|
|
128
|
+
child.kill("SIGTERM");
|
|
129
|
+
return;
|
|
130
|
+
}
|
|
131
|
+
const data = event.data;
|
|
132
|
+
if (data === undefined || currentFile === undefined)
|
|
133
|
+
return;
|
|
134
|
+
const lineText = data.lines?.text ?? "";
|
|
135
|
+
const lineNumber = data.line_number ?? 0;
|
|
136
|
+
const sub = data.submatches?.[0];
|
|
137
|
+
const start = sub?.start ?? 0;
|
|
138
|
+
const matchText = sub?.match?.text ?? "";
|
|
139
|
+
matches.push({
|
|
140
|
+
path: currentFile,
|
|
141
|
+
line: lineNumber,
|
|
142
|
+
column: start + 1,
|
|
143
|
+
length: matchText.length,
|
|
144
|
+
lineSnippet: stripTrailingNewline(lineText),
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
};
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
/* ----------------------------- in-process path ----------------------------- */
|
|
151
|
+
async function searchInProcess(projectPath, opts) {
|
|
152
|
+
const matches = [];
|
|
153
|
+
let truncated = false;
|
|
154
|
+
const deadline = Date.now() + opts.timeoutMs;
|
|
155
|
+
// Build the matcher up front so we don't reconstruct the regex per
|
|
156
|
+
// line. Plain substring uses indexOf for speed.
|
|
157
|
+
const re = opts.regex ? safeRegex(opts.query, opts.caseSensitive) : undefined;
|
|
158
|
+
if (opts.regex && re === undefined) {
|
|
159
|
+
// Bad pattern → empty result (treat like "no matches"). Caller
|
|
160
|
+
// can validate ahead of time if it wants a 400.
|
|
161
|
+
return { engine: "node", matches: [], truncated: false };
|
|
162
|
+
}
|
|
163
|
+
// Pre-compile glob predicates. Very simple — matches `*.ts` /
|
|
164
|
+
// `**/*.test.*` style patterns. Anything fancier than that we
|
|
165
|
+
// skip and rely on the user installing ripgrep.
|
|
166
|
+
const includeMatch = opts.include !== undefined ? globToRegExp(opts.include) : undefined;
|
|
167
|
+
const excludeMatch = opts.exclude !== undefined ? globToRegExp(opts.exclude) : undefined;
|
|
168
|
+
const root = resolve(projectPath);
|
|
169
|
+
const stack = [root];
|
|
170
|
+
const filesToScan = [];
|
|
171
|
+
// First pass: discover files under depth 6 honoring SEARCH_SKIP_DIRS.
|
|
172
|
+
while (stack.length > 0 && Date.now() < deadline) {
|
|
173
|
+
const dir = stack.pop();
|
|
174
|
+
if (dir === undefined)
|
|
175
|
+
break;
|
|
176
|
+
const depth = relative(root, dir)
|
|
177
|
+
.split(/[\\/]/)
|
|
178
|
+
.filter((p) => p.length > 0).length;
|
|
179
|
+
if (depth > 6)
|
|
180
|
+
continue;
|
|
181
|
+
let entries;
|
|
182
|
+
try {
|
|
183
|
+
entries = await readdir(dir, { withFileTypes: true });
|
|
184
|
+
}
|
|
185
|
+
catch {
|
|
186
|
+
// Permission denied / vanished directory — skip without
|
|
187
|
+
// aborting the whole search. Common on system-managed
|
|
188
|
+
// subdirs the user doesn't own.
|
|
189
|
+
continue;
|
|
190
|
+
}
|
|
191
|
+
for (const ent of entries) {
|
|
192
|
+
const full = join(dir, ent.name);
|
|
193
|
+
if (ent.isDirectory()) {
|
|
194
|
+
if (SEARCH_SKIP_DIRS.has(ent.name))
|
|
195
|
+
continue;
|
|
196
|
+
if (ent.name.startsWith(".") && ent.name !== ".")
|
|
197
|
+
continue;
|
|
198
|
+
stack.push(full);
|
|
199
|
+
}
|
|
200
|
+
else if (ent.isFile()) {
|
|
201
|
+
const rel = relative(root, full);
|
|
202
|
+
if (includeMatch !== undefined && !includeMatch.test(rel))
|
|
203
|
+
continue;
|
|
204
|
+
if (excludeMatch !== undefined && excludeMatch.test(rel))
|
|
205
|
+
continue;
|
|
206
|
+
filesToScan.push(rel);
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
if (Date.now() >= deadline)
|
|
211
|
+
truncated = true;
|
|
212
|
+
// Second pass: bounded-concurrency match scan. 16-wide is a
|
|
213
|
+
// reasonable default for SSDs; HDD-bound users will see the same
|
|
214
|
+
// throughput regardless because seek time dominates.
|
|
215
|
+
const CONCURRENCY = 16;
|
|
216
|
+
let cursor = 0;
|
|
217
|
+
const worker = async () => {
|
|
218
|
+
while (cursor < filesToScan.length) {
|
|
219
|
+
if (Date.now() >= deadline) {
|
|
220
|
+
truncated = true;
|
|
221
|
+
return;
|
|
222
|
+
}
|
|
223
|
+
if (matches.length >= opts.limit) {
|
|
224
|
+
truncated = true;
|
|
225
|
+
return;
|
|
226
|
+
}
|
|
227
|
+
const i = cursor++;
|
|
228
|
+
const rel = filesToScan[i];
|
|
229
|
+
if (rel === undefined)
|
|
230
|
+
continue;
|
|
231
|
+
const full = join(root, rel);
|
|
232
|
+
// Size + binary skip. The 5 MB cap mirrors file-manager's
|
|
233
|
+
// readFile cap so search and editor agree on what's a "text
|
|
234
|
+
// file." Binary detection is a NUL-byte test on the first
|
|
235
|
+
// 4 KB — same heuristic git itself uses.
|
|
236
|
+
let st;
|
|
237
|
+
try {
|
|
238
|
+
st = await stat(full);
|
|
239
|
+
}
|
|
240
|
+
catch {
|
|
241
|
+
// File vanished between discovery and stat — common when
|
|
242
|
+
// the agent edits files mid-search. Skip silently.
|
|
243
|
+
continue;
|
|
244
|
+
}
|
|
245
|
+
if (!st.isFile() || st.size > MAX_READ_BYTES)
|
|
246
|
+
continue;
|
|
247
|
+
let content;
|
|
248
|
+
try {
|
|
249
|
+
const buf = await readFile(full);
|
|
250
|
+
if (looksBinary(buf))
|
|
251
|
+
continue;
|
|
252
|
+
content = buf.toString("utf8");
|
|
253
|
+
}
|
|
254
|
+
catch {
|
|
255
|
+
// Read failure (perms, vanished mid-loop) — skip this file.
|
|
256
|
+
continue;
|
|
257
|
+
}
|
|
258
|
+
scanText(content, rel, opts, re, matches, opts.limit);
|
|
259
|
+
}
|
|
260
|
+
};
|
|
261
|
+
const workers = [];
|
|
262
|
+
for (let w = 0; w < Math.min(CONCURRENCY, filesToScan.length); w++) {
|
|
263
|
+
workers.push(worker());
|
|
264
|
+
}
|
|
265
|
+
await Promise.all(workers);
|
|
266
|
+
if (matches.length >= opts.limit)
|
|
267
|
+
truncated = true;
|
|
268
|
+
return { engine: "node", matches, truncated };
|
|
269
|
+
}
|
|
270
|
+
function scanText(content, rel, opts, re, out, limit) {
|
|
271
|
+
const lines = content.split("\n");
|
|
272
|
+
const cmpQuery = opts.caseSensitive ? opts.query : opts.query.toLowerCase();
|
|
273
|
+
for (let i = 0; i < lines.length; i++) {
|
|
274
|
+
if (out.length >= limit)
|
|
275
|
+
return;
|
|
276
|
+
const line = lines[i] ?? "";
|
|
277
|
+
if (re !== undefined) {
|
|
278
|
+
// Reuse the passed-in regex (always built with the `g` flag —
|
|
279
|
+
// see safeRegex). lastIndex carries between exec() calls so we
|
|
280
|
+
// need to reset it once per line; previously this code rebuilt
|
|
281
|
+
// the regex per line to side-step lastIndex, which on a
|
|
282
|
+
// 100-file × 1000-line search allocated 100k regex objects.
|
|
283
|
+
re.lastIndex = 0;
|
|
284
|
+
let m;
|
|
285
|
+
while ((m = re.exec(line)) !== null) {
|
|
286
|
+
out.push({
|
|
287
|
+
path: rel,
|
|
288
|
+
line: i + 1,
|
|
289
|
+
column: m.index + 1,
|
|
290
|
+
length: m[0].length,
|
|
291
|
+
lineSnippet: line,
|
|
292
|
+
});
|
|
293
|
+
if (out.length >= limit)
|
|
294
|
+
return;
|
|
295
|
+
// Avoid zero-length match infinite loop.
|
|
296
|
+
if (m.index === re.lastIndex)
|
|
297
|
+
re.lastIndex += 1;
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
else {
|
|
301
|
+
const haystack = opts.caseSensitive ? line : line.toLowerCase();
|
|
302
|
+
let from = 0;
|
|
303
|
+
while (from <= haystack.length) {
|
|
304
|
+
const idx = haystack.indexOf(cmpQuery, from);
|
|
305
|
+
if (idx === -1)
|
|
306
|
+
break;
|
|
307
|
+
out.push({
|
|
308
|
+
path: rel,
|
|
309
|
+
line: i + 1,
|
|
310
|
+
column: idx + 1,
|
|
311
|
+
length: opts.query.length,
|
|
312
|
+
lineSnippet: line,
|
|
313
|
+
});
|
|
314
|
+
if (out.length >= limit)
|
|
315
|
+
return;
|
|
316
|
+
from = idx + Math.max(1, opts.query.length);
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
function looksBinary(buf) {
|
|
322
|
+
// Sniff at most the first 4 KB. A NUL byte in a text file is
|
|
323
|
+
// virtually unheard of — git, ripgrep, and most editors use the
|
|
324
|
+
// same heuristic.
|
|
325
|
+
const probe = buf.subarray(0, Math.min(4096, buf.length));
|
|
326
|
+
for (let i = 0; i < probe.length; i++) {
|
|
327
|
+
if (probe[i] === 0)
|
|
328
|
+
return true;
|
|
329
|
+
}
|
|
330
|
+
return false;
|
|
331
|
+
}
|
|
332
|
+
function safeRegex(pattern, caseSensitive) {
|
|
333
|
+
try {
|
|
334
|
+
// Always include the `g` flag so scanText() can do a lastIndex-bumping
|
|
335
|
+
// exec loop without rebuilding the regex per line. Without `g`, exec()
|
|
336
|
+
// returns the same first match on every call, which would silently
|
|
337
|
+
// miss subsequent matches on the same line.
|
|
338
|
+
return new RegExp(pattern, caseSensitive ? "g" : "gi");
|
|
339
|
+
}
|
|
340
|
+
catch {
|
|
341
|
+
// Invalid regex pattern from the user. Caller treats undefined
|
|
342
|
+
// as "bad pattern" and short-circuits with an empty result.
|
|
343
|
+
return undefined;
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
function stripTrailingNewline(s) {
|
|
347
|
+
if (s.endsWith("\r\n"))
|
|
348
|
+
return s.slice(0, -2);
|
|
349
|
+
if (s.endsWith("\n"))
|
|
350
|
+
return s.slice(0, -1);
|
|
351
|
+
return s;
|
|
352
|
+
}
|
|
353
|
+
/**
|
|
354
|
+
* Translate a simple glob pattern to a RegExp anchored to the full
|
|
355
|
+
* path. Supports `*` (any chars except `/`), `**` (any chars
|
|
356
|
+
* including `/`), and `?` (single char). Anything fancier — char
|
|
357
|
+
* classes, brace expansion — is unsupported on this fallback path.
|
|
358
|
+
*/
|
|
359
|
+
function globToRegExp(glob) {
|
|
360
|
+
let out = "^";
|
|
361
|
+
for (let i = 0; i < glob.length; i++) {
|
|
362
|
+
const c = glob[i] ?? "";
|
|
363
|
+
if (c === "*") {
|
|
364
|
+
if (glob[i + 1] === "*") {
|
|
365
|
+
out += ".*";
|
|
366
|
+
i++;
|
|
367
|
+
}
|
|
368
|
+
else {
|
|
369
|
+
out += "[^/]*";
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
else if (c === "?") {
|
|
373
|
+
out += "[^/]";
|
|
374
|
+
}
|
|
375
|
+
else if (".+^$()[]{}|\\".includes(c)) {
|
|
376
|
+
out += "\\" + c;
|
|
377
|
+
}
|
|
378
|
+
else {
|
|
379
|
+
out += c;
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
out += "$";
|
|
383
|
+
return new RegExp(out);
|
|
384
|
+
}
|
|
385
|
+
//# sourceMappingURL=file-searcher.js.map
|