@opencode-ai/core 0.0.0-dev-18334 → 0.0.0-dev-18339

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 (754) hide show
  1. package/dist/account/sql.js +2 -2
  2. package/dist/agent.js +70 -70
  3. package/dist/aisdk-native.js +3 -3
  4. package/dist/aisdk.js +4 -4
  5. package/dist/app.js +2 -2
  6. package/dist/bus.js +68 -68
  7. package/dist/catalog.js +78 -78
  8. package/dist/chunks/{pty-02dbfq60.js → kv-02dbfq60.js} +1 -1
  9. package/dist/chunks/{pty-k60er779.js → kv-0ex5w6gb.js} +10 -10
  10. package/dist/chunks/{pty-bycv9049.js → kv-0gjxv4zg.js} +89 -89
  11. package/dist/chunks/{pty-0kvmztkf.js → kv-0kvmztkf.js} +1 -1
  12. package/dist/chunks/{pty-wxw93tt2.js → kv-0nsjmygq.js} +4 -4
  13. package/dist/chunks/{pty-n57pjc8k.js → kv-0pn12ky9.js} +3 -3
  14. package/dist/chunks/{pty-q3856v5v.js → kv-0rpfwhsw.js} +3 -3
  15. package/dist/chunks/{pty-hey25ktd.js → kv-0y655g3j.js} +2 -2
  16. package/dist/chunks/{pty-yhqh92qf.js → kv-10ymxce0.js} +15 -15
  17. package/dist/chunks/{pty-sst1754h.js → kv-14d5gv1g.js} +5 -5
  18. package/dist/chunks/{pty-18pv8fg3.js → kv-18pv8fg3.js} +2 -2
  19. package/dist/chunks/{pty-ctzszweb.js → kv-1e7b7hnt.js} +8 -8
  20. package/dist/chunks/{pty-gjy076rh.js → kv-1fq4p3a0.js} +8 -8
  21. package/dist/chunks/{pty-v5r4ssgv.js → kv-1z2djtdb.js} +155 -155
  22. package/dist/chunks/{pty-csrx180a.js → kv-1znkpcva.js} +5 -5
  23. package/dist/chunks/{pty-y0k2k5v2.js → kv-2472bxjq.js} +8 -8
  24. package/dist/chunks/{pty-0e43scmx.js → kv-26hyr64a.js} +8 -8
  25. package/dist/chunks/{pty-2m0hgr65.js → kv-2m0hgr65.js} +1 -1
  26. package/dist/chunks/{pty-xc25jqxj.js → kv-2nmh62e0.js} +5 -5
  27. package/dist/chunks/{pty-2nmyybe0.js → kv-2nmyybe0.js} +1 -1
  28. package/dist/chunks/{pty-k4h7rtgr.js → kv-2r4w0tef.js} +7 -7
  29. package/dist/chunks/{pty-hchrdr4t.js → kv-2te4qfmf.js} +4 -4
  30. package/dist/chunks/{pty-2wds5nk3.js → kv-2wds5nk3.js} +1 -1
  31. package/dist/chunks/{pty-aj9m13cz.js → kv-2zvg8b5x.js} +4 -4
  32. package/dist/chunks/{pty-qy7mm8w3.js → kv-3144vz00.js} +9 -9
  33. package/dist/chunks/{pty-9yrp1ad7.js → kv-3cv4p330.js} +3 -3
  34. package/dist/chunks/{pty-3g8vftxb.js → kv-3g8vftxb.js} +2 -2
  35. package/dist/chunks/{pty-3qv8nf0b.js → kv-3qv8nf0b.js} +1 -1
  36. package/dist/chunks/{pty-b7z6w66n.js → kv-3rayhmv3.js} +3 -3
  37. package/dist/chunks/{pty-tm1k0b1t.js → kv-3t17rrv4.js} +10 -10
  38. package/dist/chunks/{pty-3thh6229.js → kv-3thh6229.js} +2 -2
  39. package/dist/chunks/{pty-k3z8bqpp.js → kv-3vpyzwc4.js} +3 -3
  40. package/dist/chunks/{pty-dapbg9ce.js → kv-3w5aym19.js} +9 -9
  41. package/dist/chunks/{pty-mzj6ydvj.js → kv-46tke73x.js} +6 -6
  42. package/dist/chunks/{pty-yqza15cy.js → kv-4ahj0kbj.js} +38 -38
  43. package/dist/chunks/{pty-8vd6pef0.js → kv-4dsn0b5s.js} +4 -4
  44. package/dist/chunks/{pty-5vbqbv2r.js → kv-4gj3z125.js} +61 -61
  45. package/dist/chunks/{pty-9bzgvrrs.js → kv-4j3sy62h.js} +6 -6
  46. package/dist/chunks/{pty-4s2xwh5d.js → kv-4s2xwh5d.js} +3 -3
  47. package/dist/chunks/{pty-09vaeaer.js → kv-4v8j4d8q.js} +5 -5
  48. package/dist/chunks/{pty-4zzdwbaz.js → kv-4zzdwbaz.js} +2 -2
  49. package/dist/chunks/{pty-50jxp3hw.js → kv-50jxp3hw.js} +1 -1
  50. package/dist/chunks/{pty-57tzwnz4.js → kv-57tzwnz4.js} +1 -1
  51. package/dist/chunks/{pty-58xdvehb.js → kv-58xdvehb.js} +1 -1
  52. package/dist/chunks/{pty-5cdnkd94.js → kv-5cdnkd94.js} +3 -3
  53. package/dist/chunks/{pty-5fe026tx.js → kv-5fe026tx.js} +3 -3
  54. package/dist/chunks/{pty-90ajpsyk.js → kv-5hsxrzr9.js} +2 -2
  55. package/dist/chunks/{pty-cbp4tzfr.js → kv-5ncymr0a.js} +4 -4
  56. package/dist/chunks/{pty-5rs65q6p.js → kv-5rs65q6p.js} +1 -1
  57. package/dist/chunks/{pty-5vcssjzn.js → kv-5vcssjzn.js} +1 -1
  58. package/dist/chunks/{pty-5z4zwtb4.js → kv-5z4zwtb4.js} +2 -2
  59. package/dist/chunks/{pty-6272rtjg.js → kv-6272rtjg.js} +1 -1
  60. package/dist/chunks/{pty-j0a8c2ah.js → kv-66r1q76g.js} +3 -3
  61. package/dist/chunks/{pty-mzcgyw1d.js → kv-671n4ec0.js} +7 -7
  62. package/dist/chunks/{pty-6ky7rqk7.js → kv-6ky7rqk7.js} +1 -1
  63. package/dist/chunks/{pty-g8qafzk6.js → kv-6m9fss13.js} +7 -7
  64. package/dist/chunks/{pty-0kx9g65f.js → kv-6q644z5w.js} +3 -3
  65. package/dist/chunks/{pty-6wkzvma0.js → kv-6wkzvma0.js} +2 -2
  66. package/dist/chunks/{pty-75h1hfe2.js → kv-75h1hfe2.js} +2 -2
  67. package/dist/chunks/{pty-gvb5fjaj.js → kv-7d1grz3f.js} +4 -4
  68. package/dist/chunks/{pty-7gqqz1s8.js → kv-7gqqz1s8.js} +1 -1
  69. package/dist/chunks/{pty-7khw64yh.js → kv-7khw64yh.js} +1 -1
  70. package/dist/chunks/{pty-7mrpdsq5.js → kv-7mrpdsq5.js} +1 -1
  71. package/dist/chunks/{pty-hhx769z4.js → kv-7pb1ad45.js} +4 -4
  72. package/dist/chunks/{pty-7thnevmq.js → kv-7thnevmq.js} +2 -2
  73. package/dist/chunks/{pty-7wcmqxrc.js → kv-7wcmqxrc.js} +1 -1
  74. package/dist/chunks/{pty-88jbfw8z.js → kv-88jbfw8z.js} +2 -2
  75. package/dist/chunks/{pty-4rqp4j7m.js → kv-88kss8rc.js} +5 -5
  76. package/dist/chunks/{pty-scwsmnvy.js → kv-8kkwgkw2.js} +15 -15
  77. package/dist/chunks/{pty-8pngjawd.js → kv-8pngjawd.js} +2 -2
  78. package/dist/chunks/{pty-83e2qdb8.js → kv-8swew0x2.js} +6 -6
  79. package/dist/chunks/{pty-3eyrwrpy.js → kv-90qyxad2.js} +4 -4
  80. package/dist/chunks/{pty-jkx2v3a9.js → kv-93tefsha.js} +3 -3
  81. package/dist/chunks/{pty-81mz04qm.js → kv-968cth0m.js} +3 -3
  82. package/dist/chunks/{pty-fqex1cwa.js → kv-98hbc7y3.js} +12 -12
  83. package/dist/chunks/{pty-999qd968.js → kv-999qd968.js} +1 -1
  84. package/dist/chunks/{pty-sxp8nh0s.js → kv-9avjhcy3.js} +3 -3
  85. package/dist/chunks/{pty-4v3afprt.js → kv-9b76fep3.js} +8 -8
  86. package/dist/chunks/{pty-9f0rnpkn.js → kv-9f0rnpkn.js} +1 -1
  87. package/dist/chunks/{pty-zrn8d1yv.js → kv-9hh2h6b5.js} +15 -15
  88. package/dist/chunks/{pty-kwaxwgcd.js → kv-9rba19kc.js} +7 -7
  89. package/dist/chunks/{pty-f5p36mn1.js → kv-9sr1rygm.js} +3 -3
  90. package/dist/chunks/{pty-a09abg6q.js → kv-a09abg6q.js} +2 -2
  91. package/dist/chunks/{pty-34f5fj0z.js → kv-a46p3x3f.js} +9 -9
  92. package/dist/chunks/{pty-4tc9kn3c.js → kv-a63dcx9e.js} +21 -21
  93. package/dist/chunks/{pty-qgedfe15.js → kv-ahhpd2qe.js} +3 -3
  94. package/dist/chunks/{pty-heeswwmn.js → kv-ar229a3r.js} +8 -8
  95. package/dist/chunks/{pty-awg5d31a.js → kv-awg5d31a.js} +1 -1
  96. package/dist/chunks/{pty-bh1wr8rq.js → kv-bh1wr8rq.js} +2 -2
  97. package/dist/chunks/{pty-bmknfyv0.js → kv-bmknfyv0.js} +2 -2
  98. package/dist/chunks/{pty-hh9129p6.js → kv-br3vd8kh.js} +2 -2
  99. package/dist/chunks/{pty-j0z5ak8k.js → kv-by0e6x5c.js} +45 -45
  100. package/dist/chunks/{pty-byab506k.js → kv-byab506k.js} +1 -1
  101. package/dist/chunks/{pty-c4wcb9vc.js → kv-c4wcb9vc.js} +2 -2
  102. package/dist/chunks/{pty-frysc0nn.js → kv-c6ct36ty.js} +9 -9
  103. package/dist/chunks/{pty-z42p5vhz.js → kv-chcr0fra.js} +5 -5
  104. package/dist/chunks/{pty-m62ssds6.js → kv-cj3mznze.js} +2 -2
  105. package/dist/chunks/{pty-5nnwbsha.js → kv-ck6a95w5.js} +3 -3
  106. package/dist/chunks/{pty-p2559na6.js → kv-ck8sth2t.js} +3 -3
  107. package/dist/chunks/{pty-4jcspr7g.js → kv-ckv7kep5.js} +5 -5
  108. package/dist/chunks/{pty-0s07mtq1.js → kv-d18w9et2.js} +5 -5
  109. package/dist/chunks/{pty-d2gk9vpf.js → kv-d2gk9vpf.js} +2 -2
  110. package/dist/chunks/{pty-d4ax61k3.js → kv-d4ax61k3.js} +2 -2
  111. package/dist/chunks/{pty-8t2hdhmm.js → kv-ddex5nyn.js} +3 -3
  112. package/dist/chunks/{pty-k8fd3zhv.js → kv-dgqp5nda.js} +3 -3
  113. package/dist/chunks/{pty-dhphtf1x.js → kv-dhphtf1x.js} +1 -1
  114. package/dist/chunks/{pty-e1z9a0ts.js → kv-e1z9a0ts.js} +2 -2
  115. package/dist/chunks/{pty-ec8vrfw5.js → kv-ec8vrfw5.js} +1 -1
  116. package/dist/chunks/{pty-enpg66yn.js → kv-enpg66yn.js} +1 -1
  117. package/dist/chunks/{pty-bv58wyct.js → kv-ert2ba1d.js} +7 -7
  118. package/dist/chunks/{pty-9gthvhr1.js → kv-etsaqhqn.js} +8 -8
  119. package/dist/chunks/{pty-f7q7a28y.js → kv-f7q7a28y.js} +4 -4
  120. package/dist/chunks/kv-f9n5fyhn.js +341 -0
  121. package/dist/chunks/{pty-f9wt0tjw.js → kv-f9wt0tjw.js} +2 -2
  122. package/dist/chunks/{pty-fb7nfzf2.js → kv-fb7nfzf2.js} +3 -3
  123. package/dist/chunks/{pty-vq4bsz4p.js → kv-ferj8240.js} +91 -91
  124. package/dist/chunks/{pty-fgyjabww.js → kv-fgyjabww.js} +2 -2
  125. package/dist/chunks/{pty-59sg178t.js → kv-fwsezdbd.js} +4 -4
  126. package/dist/chunks/{pty-njwvsg8m.js → kv-g1db1nf1.js} +14 -14
  127. package/dist/chunks/{pty-shs983jy.js → kv-g7tgpc26.js} +12 -12
  128. package/dist/chunks/{pty-gcay93cp.js → kv-gcay93cp.js} +1 -1
  129. package/dist/chunks/{pty-gd2xppx8.js → kv-gd2xppx8.js} +1 -1
  130. package/dist/chunks/{pty-gpybhmhb.js → kv-gpybhmhb.js} +3 -3
  131. package/dist/chunks/{pty-f6c1t9rd.js → kv-gsdtpdj5.js} +4 -4
  132. package/dist/chunks/{pty-h12kt9pa.js → kv-h12kt9pa.js} +2 -2
  133. package/dist/chunks/{pty-7ev5chdf.js → kv-h4sj9tha.js} +14 -14
  134. package/dist/chunks/{pty-vfaqc6pt.js → kv-h7wwd8cj.js} +8 -8
  135. package/dist/chunks/{pty-h94zdhz8.js → kv-h94zdhz8.js} +2 -2
  136. package/dist/chunks/{pty-hp6rpdnc.js → kv-hp6rpdnc.js} +1 -1
  137. package/dist/chunks/{pty-hqh8yks9.js → kv-hqh8yks9.js} +3 -3
  138. package/dist/chunks/{pty-b2ykb7j7.js → kv-j0mc065y.js} +3 -3
  139. package/dist/chunks/{pty-j2rwtkhe.js → kv-j2rwtkhe.js} +4 -4
  140. package/dist/chunks/{pty-fxq037mg.js → kv-j37e0edx.js} +11 -11
  141. package/dist/chunks/{pty-w7xyqxnp.js → kv-j7s8djnk.js} +5 -5
  142. package/dist/chunks/{pty-h1kxvktj.js → kv-jc29bebd.js} +12 -12
  143. package/dist/chunks/{pty-p26n68ww.js → kv-jm0q6ezy.js} +13 -13
  144. package/dist/chunks/{pty-5n0e25rx.js → kv-jmnt8swh.js} +8 -8
  145. package/dist/chunks/{pty-21d46bda.js → kv-jn2zfzya.js} +3 -3
  146. package/dist/chunks/{pty-051n8qej.js → kv-jvh2qagg.js} +14 -14
  147. package/dist/chunks/{pty-k42t1tha.js → kv-k42t1tha.js} +2 -2
  148. package/dist/chunks/{pty-kpag6kfh.js → kv-k9na051a.js} +6 -6
  149. package/dist/chunks/{pty-p97a0mey.js → kv-kf17v4zs.js} +6 -6
  150. package/dist/chunks/{pty-kg1345f7.js → kv-kg1345f7.js} +1 -1
  151. package/dist/chunks/{pty-kp1t5rcy.js → kv-kp1t5rcy.js} +1 -1
  152. package/dist/chunks/{pty-krsqcmnj.js → kv-krsqcmnj.js} +1 -1
  153. package/dist/chunks/{pty-36b64kw5.js → kv-kxdfg7qh.js} +9 -9
  154. package/dist/chunks/{pty-5y71y6aq.js → kv-m1padgrh.js} +4 -4
  155. package/dist/chunks/{pty-m55whf0h.js → kv-m55whf0h.js} +2 -2
  156. package/dist/chunks/{pty-qf57kmn8.js → kv-mbv1w93f.js} +4 -4
  157. package/dist/chunks/{pty-c9ts76et.js → kv-mej0nrq3.js} +3 -3
  158. package/dist/chunks/{pty-mf0hyk7z.js → kv-mf0hyk7z.js} +1 -1
  159. package/dist/chunks/{pty-mh28new4.js → kv-mh28new4.js} +2 -2
  160. package/dist/chunks/{pty-mkaeg0rc.js → kv-mkaeg0rc.js} +6 -6
  161. package/dist/chunks/{pty-yd4t93pc.js → kv-mm1csdks.js} +4 -4
  162. package/dist/chunks/{pty-mnb85w6b.js → kv-mnb85w6b.js} +2 -2
  163. package/dist/chunks/{pty-5ev5dm41.js → kv-mnzk1cqa.js} +10 -10
  164. package/dist/chunks/{pty-mxvw03gv.js → kv-mxvw03gv.js} +1 -1
  165. package/dist/chunks/{pty-02jh672z.js → kv-n67f1qxt.js} +29 -29
  166. package/dist/chunks/{pty-mr7hz5nx.js → kv-nbawqw93.js} +8 -8
  167. package/dist/chunks/{pty-nesb2rcz.js → kv-nesb2rcz.js} +2 -2
  168. package/dist/chunks/{pty-ve0df51m.js → kv-njt4z54v.js} +6 -6
  169. package/dist/chunks/{pty-5t6ev4f9.js → kv-nkaqy11c.js} +59 -59
  170. package/dist/chunks/{pty-61y22362.js → kv-np30ra1e.js} +9 -9
  171. package/dist/chunks/{pty-nr76rjj3.js → kv-nr76rjj3.js} +2 -2
  172. package/dist/chunks/{pty-y369bt6x.js → kv-nv3q1d9w.js} +5 -5
  173. package/dist/chunks/{pty-4pb49s5g.js → kv-nxat12yk.js} +4 -4
  174. package/dist/chunks/{pty-nzrjycs5.js → kv-nzrjycs5.js} +1 -1
  175. package/dist/chunks/{pty-ezzbbpt3.js → kv-p7ceka9t.js} +14 -14
  176. package/dist/chunks/{pty-6q0m15b3.js → kv-p8fr6x1v.js} +2 -2
  177. package/dist/chunks/{pty-8s0m95jw.js → kv-p99drwz0.js} +5 -5
  178. package/dist/chunks/{pty-zgsy1s8j.js → kv-pc68jvdy.js} +4 -4
  179. package/dist/chunks/{pty-3c3xz5w2.js → kv-ppx35r9t.js} +4 -4
  180. package/dist/chunks/{pty-pq4b4pqk.js → kv-pq4b4pqk.js} +2 -2
  181. package/dist/chunks/{pty-ggww5s4h.js → kv-pqn75jxa.js} +13 -13
  182. package/dist/chunks/{pty-th5k7hy4.js → kv-pydw6mfr.js} +3 -3
  183. package/dist/chunks/{pty-bc1jme2z.js → kv-q0pv8ccx.js} +2 -2
  184. package/dist/chunks/{pty-q9b4qnv8.js → kv-q9b4qnv8.js} +2 -2
  185. package/dist/chunks/{pty-9dnj3g8a.js → kv-qbhcf2ms.js} +10 -10
  186. package/dist/chunks/{pty-qe0d689s.js → kv-qe0d689s.js} +2 -2
  187. package/dist/chunks/{pty-63k0vevy.js → kv-qrvmr4r5.js} +12 -12
  188. package/dist/chunks/{pty-tepwy0cv.js → kv-qt2qv4ez.js} +3 -3
  189. package/dist/chunks/{pty-vsp0ywmz.js → kv-qzt690fz.js} +2 -2
  190. package/dist/chunks/{pty-r13w8t0w.js → kv-r13w8t0w.js} +2 -2
  191. package/dist/chunks/{pty-r3k9abhd.js → kv-r3k9abhd.js} +2 -2
  192. package/dist/chunks/{pty-75bh2x5p.js → kv-r5svksvn.js} +13 -13
  193. package/dist/chunks/{pty-1rwfe3w7.js → kv-r97ytgf1.js} +6 -6
  194. package/dist/chunks/{pty-rahat93a.js → kv-rahat93a.js} +1 -1
  195. package/dist/chunks/{pty-rameyvmv.js → kv-rameyvmv.js} +1 -1
  196. package/dist/chunks/{pty-rbnp2c85.js → kv-rbnp2c85.js} +3 -3
  197. package/dist/chunks/{pty-rfbm65k8.js → kv-rfbm65k8.js} +1 -1
  198. package/dist/chunks/{pty-wpb53h8k.js → kv-rm7md962.js} +10 -10
  199. package/dist/chunks/{pty-gzya93qj.js → kv-rv0cjn1z.js} +3 -3
  200. package/dist/chunks/{pty-s33fw6zm.js → kv-s33fw6zm.js} +1 -1
  201. package/dist/chunks/{pty-jpw0c2hb.js → kv-sas94s9a.js} +2 -2
  202. package/dist/chunks/{pty-se1aqaya.js → kv-se1aqaya.js} +3 -3
  203. package/dist/chunks/{pty-smpeg8c9.js → kv-smpeg8c9.js} +2 -2
  204. package/dist/chunks/{pty-sw84ckhj.js → kv-sw84ckhj.js} +1 -1
  205. package/dist/chunks/{pty-9xz132x0.js → kv-t0h4pkp4.js} +28 -28
  206. package/dist/chunks/{pty-t14kykx1.js → kv-t14kykx1.js} +1 -1
  207. package/dist/chunks/{pty-x31hnj33.js → kv-ta3fzjwk.js} +3 -3
  208. package/dist/chunks/{pty-tcptxgyq.js → kv-tcptxgyq.js} +1 -1
  209. package/dist/chunks/{pty-8hx58cse.js → kv-td0yzbe3.js} +7 -7
  210. package/dist/chunks/{pty-wsb1nxx2.js → kv-te3xfmcs.js} +22 -22
  211. package/dist/chunks/{pty-tgbb2ckq.js → kv-tgbb2ckq.js} +2 -2
  212. package/dist/chunks/{pty-thstd87d.js → kv-thstd87d.js} +1 -1
  213. package/dist/chunks/{pty-x5g53fnr.js → kv-txmc67eg.js} +8 -8
  214. package/dist/chunks/{pty-k3ng8j0p.js → kv-txnnyt3a.js} +3 -3
  215. package/dist/chunks/{pty-aa3706nc.js → kv-tyymnqm2.js} +12 -12
  216. package/dist/chunks/{pty-v2wshkax.js → kv-v2wshkax.js} +1 -1
  217. package/dist/chunks/{pty-f0mp5ybc.js → kv-v7q0vmsp.js} +7 -7
  218. package/dist/chunks/{pty-v80zsxnb.js → kv-v80zsxnb.js} +1 -1
  219. package/dist/chunks/{pty-v972xay6.js → kv-v972xay6.js} +1 -1
  220. package/dist/chunks/{pty-v9bfv94f.js → kv-v9bfv94f.js} +1 -1
  221. package/dist/chunks/{pty-vcwr2vpf.js → kv-vcwr2vpf.js} +1 -1
  222. package/dist/chunks/{pty-vqbmgfq1.js → kv-vqbmgfq1.js} +3 -3
  223. package/dist/chunks/{pty-vycjsnjm.js → kv-vycjsnjm.js} +2 -2
  224. package/dist/chunks/{pty-vz89hfgr.js → kv-vz89hfgr.js} +1 -1
  225. package/dist/chunks/{pty-3e611gqc.js → kv-w2dqsb3p.js} +7 -7
  226. package/dist/chunks/{pty-wbkt8qpj.js → kv-wbkt8qpj.js} +1 -1
  227. package/dist/chunks/{pty-njhebxnk.js → kv-wc64byt1.js} +1 -1
  228. package/dist/chunks/{pty-wd268jeg.js → kv-wd268jeg.js} +1 -1
  229. package/dist/chunks/{pty-whk0g8cz.js → kv-whk0g8cz.js} +4 -4
  230. package/dist/chunks/{pty-c0wpjb9x.js → kv-whqpbpex.js} +3 -3
  231. package/dist/chunks/{pty-wmxdh12w.js → kv-wmxdh12w.js} +1 -1
  232. package/dist/chunks/{pty-wps8gh8n.js → kv-wps8gh8n.js} +2 -2
  233. package/dist/chunks/{pty-72qw6s34.js → kv-x6t3f0mt.js} +7 -7
  234. package/dist/chunks/{pty-x89rah0x.js → kv-x89rah0x.js} +1 -1
  235. package/dist/chunks/{pty-vvw8wy47.js → kv-xaamjw0t.js} +4 -4
  236. package/dist/chunks/{pty-xczfw7dq.js → kv-xczfw7dq.js} +1 -1
  237. package/dist/chunks/{pty-xgv25zxy.js → kv-xgv25zxy.js} +1 -1
  238. package/dist/chunks/{pty-gb6y46qa.js → kv-xk62382b.js} +7 -7
  239. package/dist/chunks/{pty-2bh65m2v.js → kv-xv3kk1c8.js} +4 -4
  240. package/dist/chunks/{pty-xwftk1fd.js → kv-xwftk1fd.js} +2 -2
  241. package/dist/chunks/{pty-xxpvz42q.js → kv-xxpvz42q.js} +3 -3
  242. package/dist/chunks/{pty-8v9vyqap.js → kv-xyd30y3n.js} +7 -7
  243. package/dist/chunks/{pty-y0x38cee.js → kv-y0x38cee.js} +1 -1
  244. package/dist/chunks/{pty-y198y2ra.js → kv-y198y2ra.js} +1 -1
  245. package/dist/chunks/{pty-gry11svd.js → kv-y4zy7z84.js} +7 -7
  246. package/dist/chunks/{pty-y67x6rf6.js → kv-y67x6rf6.js} +1 -1
  247. package/dist/chunks/{pty-d5c7vh5e.js → kv-y8bhddg5.js} +5 -5
  248. package/dist/chunks/{pty-y980s7ka.js → kv-y980s7ka.js} +3 -3
  249. package/dist/chunks/{pty-ybhfpy64.js → kv-ybhfpy64.js} +2 -2
  250. package/dist/chunks/{pty-yc2vxtaa.js → kv-yc2vxtaa.js} +2 -2
  251. package/dist/chunks/{pty-3tmjw1xx.js → kv-ydp36znb.js} +2 -2
  252. package/dist/chunks/{pty-yf0knd5z.js → kv-yf0knd5z.js} +2 -2
  253. package/dist/chunks/{pty-ygy0xbqa.js → kv-ygy0xbqa.js} +3 -3
  254. package/dist/chunks/{pty-0b0bqs4b.js → kv-yj6j21rs.js} +4 -4
  255. package/dist/chunks/{pty-fd9akh10.js → kv-yk8p9vz7.js} +14 -14
  256. package/dist/chunks/{pty-mzh6z5a7.js → kv-z0cdzwb8.js} +5 -5
  257. package/dist/chunks/{pty-cb10vk7s.js → kv-z0nqfmpz.js} +11 -11
  258. package/dist/chunks/{pty-zbqqnp0n.js → kv-zbqqnp0n.js} +1 -1
  259. package/dist/chunks/{pty-zdkg1k91.js → kv-zdkg1k91.js} +1 -1
  260. package/dist/chunks/{pty-41e94bne.js → kv-znpzapdm.js} +17 -17
  261. package/dist/chunks/{pty-ztjk4rav.js → kv-ztjk4rav.js} +4 -4
  262. package/dist/chunks/{pty-0jpabrph.js → kv-ztxrn9cn.js} +11 -11
  263. package/dist/chunks/{pty-agqwgkz2.js → kv-ztz12k4m.js} +8 -8
  264. package/dist/chunks/{pty-zxcy6vhn.js → kv-zxcy6vhn.js} +1 -1
  265. package/dist/chunks/{pty-zxe9jjhn.js → kv-zxe9jjhn.js} +2 -2
  266. package/dist/codemode/catalog.js +2 -2
  267. package/dist/codemode/instructions.js +4 -4
  268. package/dist/codemode/tool.js +3 -3
  269. package/dist/command.js +70 -70
  270. package/dist/config/markdown.js +2 -2
  271. package/dist/config/normalize.js +20 -20
  272. package/dist/config/plugin/agent.js +135 -135
  273. package/dist/config/plugin/command.js +118 -118
  274. package/dist/config/plugin/compaction.js +170 -170
  275. package/dist/config/plugin/entry-observer.js +114 -114
  276. package/dist/config/plugin/formatter.js +119 -119
  277. package/dist/config/plugin/image.js +130 -130
  278. package/dist/config/plugin/instruction.js +90 -90
  279. package/dist/config/plugin/location-watcher.js +117 -117
  280. package/dist/config/plugin/mcp.js +127 -127
  281. package/dist/config/plugin/policy.js +116 -116
  282. package/dist/config/plugin/provider.js +115 -115
  283. package/dist/config/plugin/reference.js +119 -119
  284. package/dist/config/plugin/shell.js +118 -118
  285. package/dist/config/plugin/skill-file.js +108 -108
  286. package/dist/config/plugin/skill.js +138 -138
  287. package/dist/config/plugin/snapshot.js +117 -117
  288. package/dist/config/plugin/source.js +114 -114
  289. package/dist/config/plugin/tool-output.js +119 -119
  290. package/dist/config/plugin/websearch.js +115 -115
  291. package/dist/config/variable.js +4 -4
  292. package/dist/config.js +113 -113
  293. package/dist/credential/sql.js +3 -3
  294. package/dist/credential.js +71 -71
  295. package/dist/database/database.js +65 -65
  296. package/dist/database/drizzle/effect-sqlite/driver.js +13 -13
  297. package/dist/database/drizzle/effect-sqlite/index.js +13 -13
  298. package/dist/database/drizzle/effect-sqlite/session.js +12 -12
  299. package/dist/database/drizzle/index.js +14 -14
  300. package/dist/database/drizzle/internal/drizzle-utils.js +2 -2
  301. package/dist/database/drizzle/sqlite-core/effect/count.js +2 -2
  302. package/dist/database/drizzle/sqlite-core/effect/db.js +10 -10
  303. package/dist/database/drizzle/sqlite-core/effect/delete.js +3 -3
  304. package/dist/database/drizzle/sqlite-core/effect/index.js +20 -20
  305. package/dist/database/drizzle/sqlite-core/effect/insert.js +3 -3
  306. package/dist/database/drizzle/sqlite-core/effect/query.js +2 -2
  307. package/dist/database/drizzle/sqlite-core/effect/raw.js +2 -2
  308. package/dist/database/drizzle/sqlite-core/effect/select.js +3 -3
  309. package/dist/database/drizzle/sqlite-core/effect/session.js +11 -11
  310. package/dist/database/drizzle/sqlite-core/effect/update.js +3 -3
  311. package/dist/database/drizzle.js +15 -15
  312. package/dist/database/migration/20260127222353_familiar_lady_ursula.js +2 -2
  313. package/dist/database/migration/20260211171708_add_project_commands.js +2 -2
  314. package/dist/database/migration/20260213144116_wakeful_the_professor.js +2 -2
  315. package/dist/database/migration/20260225215848_workspace.js +2 -2
  316. package/dist/database/migration/20260227213759_add_session_workspace_id.js +2 -2
  317. package/dist/database/migration/20260228203230_blue_harpoon.js +2 -2
  318. package/dist/database/migration/20260303231226_add_workspace_fields.js +2 -2
  319. package/dist/database/migration/20260309230000_move_org_to_state.js +2 -2
  320. package/dist/database/migration/20260312043431_session_message_cursor.js +2 -2
  321. package/dist/database/migration/20260323234822_events.js +2 -2
  322. package/dist/database/migration/20260410174513_workspace-name.js +2 -2
  323. package/dist/database/migration/20260413175956_chief_energizer.js +2 -2
  324. package/dist/database/migration/20260423070820_add_icon_url_override.js +2 -2
  325. package/dist/database/migration/20260427172553_slow_nightmare.js +2 -2
  326. package/dist/database/migration/20260428004200_add_session_path.js +2 -2
  327. package/dist/database/migration/20260501142318_next_venus.js +2 -2
  328. package/dist/database/migration/20260504145000_add_sync_owner.js +2 -2
  329. package/dist/database/migration/20260507164347_add_workspace_time.js +2 -2
  330. package/dist/database/migration/20260510033149_session_usage.js +2 -2
  331. package/dist/database/migration/20260511000411_data_migration_state.js +2 -2
  332. package/dist/database/migration/20260511173437_session-metadata.js +2 -2
  333. package/dist/database/migration/20260601010001_normalize_storage_paths.js +2 -2
  334. package/dist/database/migration/20260601202201_amazing_prowler.js +2 -2
  335. package/dist/database/migration/20260602002951_lowly_union_jack.js +2 -2
  336. package/dist/database/migration/20260602182828_add_project_directories.js +2 -2
  337. package/dist/database/migration/20260603001617_session_message_projection_indexes.js +2 -2
  338. package/dist/database/migration/20260603040000_session_message_projection_order.js +2 -2
  339. package/dist/database/migration/20260603141458_session_input_inbox.js +2 -2
  340. package/dist/database/migration/20260603160727_jittery_ezekiel_stane.js +2 -2
  341. package/dist/database/migration/20260604172448_event_sourced_session_input.js +2 -2
  342. package/dist/database/migration/20260605003541_add_session_context_snapshot.js +2 -2
  343. package/dist/database/migration/20260605042240_add_context_epoch_agent.js +2 -2
  344. package/dist/database/migration/20260611035744_credential.js +2 -2
  345. package/dist/database/migration/20260611192811_lush_chimera.js +2 -2
  346. package/dist/database/migration/20260612174303_project_dir_strategy.js +2 -2
  347. package/dist/database/migration/20260622142730_simplify_session_context_epoch.js +2 -2
  348. package/dist/database/migration/20260622170816_reset_v2_session_state.js +2 -2
  349. package/dist/database/migration/20260622202450_simplify_session_input.js +2 -2
  350. package/dist/database/migration/20260804233008_loose_psylocke.js +2 -2
  351. package/dist/database/migration/20260805200742_import_legacy_credentials.js +2 -2
  352. package/dist/database/migration/20260808023530_workspace_domain.js +2 -2
  353. package/dist/database/migration/20260811161259_execution_claim_attempts.js +2 -2
  354. package/dist/database/migration/20260812181746_session_inbox.js +2 -2
  355. package/dist/database/migration/20260812213948_worktree.js +2 -2
  356. package/dist/database/migration/20260819222447_session_viewed_state.js +2 -2
  357. package/dist/database/migration/20260823191254_nullable_workspace_binding.js +2 -2
  358. package/dist/database/migration.gen.js +48 -48
  359. package/dist/database/migration.js +50 -50
  360. package/dist/database/path.js +3 -3
  361. package/dist/database/schema.gen.js +2 -2
  362. package/dist/database/schema.sql.js +2 -2
  363. package/dist/database/sqlite.bun.js +2 -2
  364. package/dist/database/sqlite.js +2 -2
  365. package/dist/database/sqlite.node.js +2 -2
  366. package/dist/database/sqlite.workerd.js +2 -2
  367. package/dist/database/v1-migration.bun.js +77 -77
  368. package/dist/database/v1-migration.js +2 -2
  369. package/dist/database/v1-migration.noop.js +1 -1
  370. package/dist/effect/app-node-builder.js +327 -327
  371. package/dist/effect/app-node-platform.js +3 -3
  372. package/dist/effect/keyed-mutex.js +2 -2
  373. package/dist/effect/websocket-constructor.js +2 -2
  374. package/dist/environment/driver.js +1 -1
  375. package/dist/environment/environment.js +91 -91
  376. package/dist/environment/exec-defaults.js +3 -3
  377. package/dist/environment/files.js +2 -2
  378. package/dist/environment/index.js +93 -93
  379. package/dist/environment/local.js +3 -3
  380. package/dist/environment/memory.js +3 -3
  381. package/dist/environment/unavailable.js +1 -1
  382. package/dist/event/sql.js +2 -2
  383. package/dist/event-logger.js +68 -68
  384. package/dist/file-mutation.js +92 -92
  385. package/dist/file-retention.js +2 -2
  386. package/dist/file.js +2 -2
  387. package/dist/filesystem/fff.bun.js +2 -2
  388. package/dist/filesystem/fff.js +2 -2
  389. package/dist/filesystem/fff.node.js +2 -2
  390. package/dist/filesystem/fff.workerd.js +2 -2
  391. package/dist/filesystem/ignore.js +1 -1
  392. package/dist/filesystem/location-watcher-policy.js +3 -3
  393. package/dist/filesystem/location-watcher.js +306 -306
  394. package/dist/filesystem/protected.js +2 -2
  395. package/dist/filesystem/search.js +96 -96
  396. package/dist/filesystem/watcher-binding.js +2 -2
  397. package/dist/filesystem/watcher.js +4 -4
  398. package/dist/filesystem.js +96 -96
  399. package/dist/form.js +69 -69
  400. package/dist/formatter/builtins.js +3 -3
  401. package/dist/formatter.js +85 -85
  402. package/dist/generate.js +84 -84
  403. package/dist/git.js +5 -5
  404. package/dist/github-copilot/chat/convert-to-openai-compatible-chat-messages.js +2 -2
  405. package/dist/github-copilot/chat/get-response-metadata.js +2 -2
  406. package/dist/github-copilot/chat/map-openai-compatible-finish-reason.js +2 -2
  407. package/dist/github-copilot/chat/openai-compatible-chat-language-model.js +8 -8
  408. package/dist/github-copilot/chat/openai-compatible-chat-options.js +2 -2
  409. package/dist/github-copilot/chat/openai-compatible-prepare-tools.js +2 -2
  410. package/dist/github-copilot/copilot-provider.js +20 -20
  411. package/dist/github-copilot/models.js +4 -4
  412. package/dist/github-copilot/openai-compatible-error.js +2 -2
  413. package/dist/github-copilot/responses/convert-to-openai-responses-input.js +2 -2
  414. package/dist/github-copilot/responses/map-openai-responses-finish-reason.js +2 -2
  415. package/dist/github-copilot/responses/openai-error.js +2 -2
  416. package/dist/github-copilot/responses/openai-responses-language-model.js +11 -11
  417. package/dist/github-copilot/responses/openai-responses-prepare-tools.js +7 -7
  418. package/dist/github-copilot/responses/tool/code-interpreter.js +2 -2
  419. package/dist/github-copilot/responses/tool/file-search.js +2 -2
  420. package/dist/github-copilot/responses/tool/image-generation.js +2 -2
  421. package/dist/github-copilot/responses/tool/web-search-preview.js +2 -2
  422. package/dist/github-copilot/responses/tool/web-search.js +2 -2
  423. package/dist/id/id.js +2 -2
  424. package/dist/image/photon-wasm.bun.js +1 -1
  425. package/dist/image/photon-wasm.node.js +1 -1
  426. package/dist/image/photon-wasm.workerd.js +1 -1
  427. package/dist/image/photon.js +98 -98
  428. package/dist/image.js +98 -98
  429. package/dist/instruction-discovery.js +72 -72
  430. package/dist/instructions/builtins.js +86 -86
  431. package/dist/instructions/index.js +2 -2
  432. package/dist/integration/connection.js +2 -2
  433. package/dist/integration.js +75 -75
  434. package/dist/job.js +72 -72
  435. package/dist/kv/sql.js +3 -3
  436. package/dist/kv.js +68 -68
  437. package/dist/location-activity.js +87 -87
  438. package/dist/location-mutation.js +84 -84
  439. package/dist/location-service-map.js +84 -84
  440. package/dist/location-services.js +327 -327
  441. package/dist/location.js +83 -83
  442. package/dist/mcp/client.js +96 -93
  443. package/dist/mcp/index.js +98 -98
  444. package/dist/mcp/instructions.js +128 -128
  445. package/dist/mcp/oauth.js +2 -2
  446. package/dist/mcp/stdio.js +92 -92
  447. package/dist/mime.js +2 -2
  448. package/dist/model-resolver.js +81 -81
  449. package/dist/model.js +3 -3
  450. package/dist/models-dev.js +75 -75
  451. package/dist/oauth/page.js +2 -2
  452. package/dist/permission/saved.js +84 -84
  453. package/dist/permission/sql.js +6 -6
  454. package/dist/permission.js +105 -105
  455. package/dist/persistent-pty/binary.bun.js +2 -2
  456. package/dist/persistent-pty/binary.node.js +1 -1
  457. package/dist/persistent-pty/binary.workerd.js +1 -1
  458. package/dist/persistent-pty/daemon.js +2 -2
  459. package/dist/persistent-pty/index.js +70 -70
  460. package/dist/persistent-pty/pty-binding.js +2 -2
  461. package/dist/persistent-pty.js +70 -70
  462. package/dist/plugin/agent.js +106 -106
  463. package/dist/plugin/command.js +99 -99
  464. package/dist/plugin/hooks.js +3 -3
  465. package/dist/plugin/host.js +170 -170
  466. package/dist/plugin/internal.js +300 -300
  467. package/dist/plugin/mcp-codemode-exclusion.js +2 -2
  468. package/dist/plugin/models-dev.js +76 -76
  469. package/dist/plugin/module.js +3 -3
  470. package/dist/plugin/plan.js +106 -106
  471. package/dist/plugin/promise.js +2 -2
  472. package/dist/plugin/provider/alibaba.js +3 -3
  473. package/dist/plugin/provider/amazon-bedrock.js +3 -3
  474. package/dist/plugin/provider/anthropic.js +3 -3
  475. package/dist/plugin/provider/azure.js +121 -121
  476. package/dist/plugin/provider/cerebras.js +3 -3
  477. package/dist/plugin/provider/cloudflare-ai-gateway.js +122 -122
  478. package/dist/plugin/provider/cloudflare-workers-ai.js +122 -122
  479. package/dist/plugin/provider/cohere.js +3 -3
  480. package/dist/plugin/provider/configured.js +119 -119
  481. package/dist/plugin/provider/dynamic.js +2 -2
  482. package/dist/plugin/provider/factory.js +2 -2
  483. package/dist/plugin/provider/gateway.js +3 -3
  484. package/dist/plugin/provider/github-copilot.js +82 -82
  485. package/dist/plugin/provider/gitlab.js +4 -4
  486. package/dist/plugin/provider/google-vertex.js +3 -3
  487. package/dist/plugin/provider/kilo.js +3 -3
  488. package/dist/plugin/provider/llmgateway.js +77 -77
  489. package/dist/plugin/provider/lmstudio.js +114 -114
  490. package/dist/plugin/provider/mistral.js +3 -3
  491. package/dist/plugin/provider/nvidia.js +3 -3
  492. package/dist/plugin/provider/ollama.js +114 -114
  493. package/dist/plugin/provider/openai-compatible.js +2 -2
  494. package/dist/plugin/provider/openai.js +79 -79
  495. package/dist/plugin/provider/opencode.js +93 -93
  496. package/dist/plugin/provider/openrouter.js +4 -4
  497. package/dist/plugin/provider/perplexity.js +3 -3
  498. package/dist/plugin/provider/sap-ai-core.js +3 -3
  499. package/dist/plugin/provider/snowflake-cortex.js +3 -3
  500. package/dist/plugin/provider/venice.js +3 -3
  501. package/dist/plugin/provider/vercel.js +3 -3
  502. package/dist/plugin/provider/vllm.js +114 -114
  503. package/dist/plugin/provider/xai.js +78 -78
  504. package/dist/plugin/provider/zenmux.js +3 -3
  505. package/dist/plugin/provider.js +157 -157
  506. package/dist/plugin/runtime.js +158 -158
  507. package/dist/plugin/sdk.js +69 -69
  508. package/dist/plugin/skill.js +136 -136
  509. package/dist/plugin/source-directory.js +2 -2
  510. package/dist/plugin/supervisor-service.js +2 -2
  511. package/dist/plugin/supervisor.js +305 -305
  512. package/dist/plugin/system-prompt.js +2 -2
  513. package/dist/plugin/variant.js +4 -4
  514. package/dist/plugin/vcs/git.js +85 -85
  515. package/dist/plugin/vcs/hg.js +85 -85
  516. package/dist/plugin/warming.js +115 -115
  517. package/dist/plugin/websearch/exa.js +4 -4
  518. package/dist/plugin/websearch/firecrawl.js +5 -5
  519. package/dist/plugin/websearch/index.js +9 -9
  520. package/dist/plugin/websearch/mcp.js +3 -3
  521. package/dist/plugin/websearch/parallel.js +5 -5
  522. package/dist/plugin/websearch/tavily.js +3 -3
  523. package/dist/plugin.js +171 -171
  524. package/dist/project/markers.js +74 -74
  525. package/dist/project/schema.js +3 -3
  526. package/dist/project/sql.js +5 -5
  527. package/dist/project.js +82 -82
  528. package/dist/provider.js +2 -2
  529. package/dist/pty/protocol.js +1 -1
  530. package/dist/pty/pty.bun.js +1 -1
  531. package/dist/pty/pty.node.js +1 -1
  532. package/dist/pty/pty.workerd.js +1 -1
  533. package/dist/pty/schema.js +2 -2
  534. package/dist/pty/ticket.js +70 -70
  535. package/dist/pty.js +89 -89
  536. package/dist/reference/instructions.js +77 -77
  537. package/dist/reference.js +75 -75
  538. package/dist/repository-cache.js +7 -7
  539. package/dist/repository.js +2 -2
  540. package/dist/ripgrep/binary.js +3 -3
  541. package/dist/ripgrep.js +94 -94
  542. package/dist/schema.js +2 -2
  543. package/dist/session/compaction.js +142 -142
  544. package/dist/session/context.js +312 -312
  545. package/dist/session/environment.js +3 -3
  546. package/dist/session/error.js +4 -4
  547. package/dist/session/event.js +2 -2
  548. package/dist/session/execution/restart.js +156 -156
  549. package/dist/session/execution.js +125 -125
  550. package/dist/session/generate-node.js +313 -313
  551. package/dist/session/generate.js +2 -2
  552. package/dist/session/history.js +77 -77
  553. package/dist/session/inbox.js +77 -77
  554. package/dist/session/info.js +92 -92
  555. package/dist/session/instruction-entry.js +73 -73
  556. package/dist/session/instruction-state.js +10 -10
  557. package/dist/session/instructions.js +101 -101
  558. package/dist/session/message-updater.js +4 -4
  559. package/dist/session/message.js +2 -2
  560. package/dist/session/model-request.js +138 -138
  561. package/dist/session/model-transport.js +5 -5
  562. package/dist/session/projector.js +90 -90
  563. package/dist/session/prompt-cache-diagnostics.js +2 -2
  564. package/dist/session/revert.js +90 -90
  565. package/dist/session/run-coordinator.js +2 -2
  566. package/dist/session/runner/index.js +84 -84
  567. package/dist/session/runner/llm.js +319 -319
  568. package/dist/session/runner/max-steps.js +2 -2
  569. package/dist/session/runner/model.js +83 -83
  570. package/dist/session/runner/publish-llm-event.js +4 -4
  571. package/dist/session/runner/retry.js +72 -72
  572. package/dist/session/runner/step.js +147 -147
  573. package/dist/session/runner/to-llm-message.js +2 -2
  574. package/dist/session/schema.js +2 -2
  575. package/dist/session/sql.js +6 -6
  576. package/dist/session/stats.js +71 -71
  577. package/dist/session/store.js +100 -100
  578. package/dist/session/system-prompt.js +2 -2
  579. package/dist/session/title.js +140 -140
  580. package/dist/session/to-session-error.js +116 -116
  581. package/dist/session/transfer.js +158 -158
  582. package/dist/session/usage.js +2 -2
  583. package/dist/session.js +156 -156
  584. package/dist/shell/parse.js +9 -6
  585. package/dist/shell/parser-wasm.bun.js +1 -1
  586. package/dist/shell/parser-wasm.node.js +1 -1
  587. package/dist/shell/parser-wasm.workerd.js +1 -1
  588. package/dist/shell/scan.js +1084 -365
  589. package/dist/shell/select.js +4 -4
  590. package/dist/shell.js +99 -99
  591. package/dist/skill/discovery.js +3 -3
  592. package/dist/skill/instructions.js +107 -107
  593. package/dist/skill.js +106 -106
  594. package/dist/snapshot.js +85 -85
  595. package/dist/state.js +2 -2
  596. package/dist/tool/html-markdown.js +2 -2
  597. package/dist/tool/http-body.js +2 -2
  598. package/dist/tool/mcp.js +127 -127
  599. package/dist/tool/plugin/edit.js +115 -115
  600. package/dist/tool/plugin/file-diff.js +2 -2
  601. package/dist/tool/plugin/glob.js +117 -117
  602. package/dist/tool/plugin/grep.js +117 -117
  603. package/dist/tool/plugin/patch.js +115 -115
  604. package/dist/tool/plugin/question.js +107 -107
  605. package/dist/tool/plugin/read.js +120 -120
  606. package/dist/tool/plugin/shell.js +186 -186
  607. package/dist/tool/plugin/skill.js +107 -107
  608. package/dist/tool/plugin/subagent.js +183 -183
  609. package/dist/tool/plugin/webfetch.js +108 -108
  610. package/dist/tool/plugin/websearch.js +110 -110
  611. package/dist/tool/plugin/write.js +115 -115
  612. package/dist/tool/read-filesystem.js +98 -98
  613. package/dist/tool/runtime.js +2 -2
  614. package/dist/tool-output.js +5 -5
  615. package/dist/tool.js +120 -120
  616. package/dist/types/shell/parse.d.ts +8 -6
  617. package/dist/types/shell/scan.d.ts +6 -3
  618. package/dist/util/array.js +1 -1
  619. package/dist/util/error.js +2 -2
  620. package/dist/util/identifier.js +1 -1
  621. package/dist/util/iife.js +2 -2
  622. package/dist/util/lazy.js +2 -2
  623. package/dist/util/process-lock-ffi.bun.js +1 -1
  624. package/dist/util/process-lock-ffi.node.js +1 -1
  625. package/dist/util/process-lock-ffi.workerd.js +1 -1
  626. package/dist/util/process-lock.js +1 -1
  627. package/dist/util/slug.js +2 -2
  628. package/dist/util/token.js +2 -2
  629. package/dist/util/which.js +2 -2
  630. package/dist/util/wildcard.js +2 -2
  631. package/dist/v1/config/agent.js +4 -4
  632. package/dist/v1/config/attachment.js +3 -3
  633. package/dist/v1/config/command.js +2 -2
  634. package/dist/v1/config/config.js +15 -15
  635. package/dist/v1/config/error.js +3 -3
  636. package/dist/v1/config/formatter.js +2 -2
  637. package/dist/v1/config/layout.js +2 -2
  638. package/dist/v1/config/lsp.js +2 -2
  639. package/dist/v1/config/mcp.js +3 -3
  640. package/dist/v1/config/migrate.js +19 -19
  641. package/dist/v1/config/permission.js +2 -2
  642. package/dist/v1/config/plugin.js +2 -2
  643. package/dist/v1/config/provider-options.js +2 -2
  644. package/dist/v1/config/provider.js +3 -3
  645. package/dist/v1/config/server.js +3 -3
  646. package/dist/v1/config/skills.js +2 -2
  647. package/dist/v1/permission.js +1 -1
  648. package/dist/vcs/patch.js +2 -2
  649. package/dist/vcs.js +86 -86
  650. package/dist/websearch.js +73 -73
  651. package/dist/wellknown/plugin.js +73 -73
  652. package/dist/wellknown.js +72 -72
  653. package/dist/workspace/driver.js +2 -2
  654. package/dist/workspace/sql.js +2 -2
  655. package/dist/workspace.js +69 -69
  656. package/dist/worktree/directory.js +3 -3
  657. package/dist/worktree/git.js +7 -7
  658. package/dist/worktree/sql.js +6 -6
  659. package/dist/worktree.js +87 -87
  660. package/package.json +8 -8
  661. package/dist/chunks/pty-nv9gjhyw.js +0 -712
  662. /package/dist/chunks/{pty-0cgt0xh2.js → kv-0cgt0xh2.js} +0 -0
  663. /package/dist/chunks/{pty-0f48qthw.js → kv-0f48qthw.js} +0 -0
  664. /package/dist/chunks/{pty-0zz82cjq.js → kv-0zz82cjq.js} +0 -0
  665. /package/dist/chunks/{pty-1fb7bmpf.js → kv-1fb7bmpf.js} +0 -0
  666. /package/dist/chunks/{pty-1wcz8fvj.js → kv-1wcz8fvj.js} +0 -0
  667. /package/dist/chunks/{pty-29n7vfk2.js → kv-29n7vfk2.js} +0 -0
  668. /package/dist/chunks/{pty-2qdx6zz3.js → kv-2qdx6zz3.js} +0 -0
  669. /package/dist/chunks/{pty-2xb0r1c6.js → kv-2xb0r1c6.js} +0 -0
  670. /package/dist/chunks/{pty-39ktntah.js → kv-39ktntah.js} +0 -0
  671. /package/dist/chunks/{pty-3g3rpp2x.js → kv-3g3rpp2x.js} +0 -0
  672. /package/dist/chunks/{pty-3q6gbwmd.js → kv-3q6gbwmd.js} +0 -0
  673. /package/dist/chunks/{pty-3w3ybtfd.js → kv-3w3ybtfd.js} +0 -0
  674. /package/dist/chunks/{pty-47ty4mvs.js → kv-47ty4mvs.js} +0 -0
  675. /package/dist/chunks/{pty-4b2tz2m9.js → kv-4b2tz2m9.js} +0 -0
  676. /package/dist/chunks/{pty-5a5ch9ts.js → kv-5a5ch9ts.js} +0 -0
  677. /package/dist/chunks/{pty-5va1yh78.js → kv-5va1yh78.js} +0 -0
  678. /package/dist/chunks/{pty-61ek4hj9.js → kv-61ek4hj9.js} +0 -0
  679. /package/dist/chunks/{pty-69qrqpw0.js → kv-69qrqpw0.js} +0 -0
  680. /package/dist/chunks/{pty-6zqxzw0a.js → kv-6zqxzw0a.js} +0 -0
  681. /package/dist/chunks/{pty-7n9qwqk4.js → kv-7n9qwqk4.js} +0 -0
  682. /package/dist/chunks/{pty-8nn8kqcn.js → kv-8nn8kqcn.js} +0 -0
  683. /package/dist/chunks/{pty-8rpfd2h6.js → kv-8rpfd2h6.js} +0 -0
  684. /package/dist/chunks/{pty-8sj3ajy5.js → kv-8sj3ajy5.js} +0 -0
  685. /package/dist/chunks/{pty-8w9tzfz1.js → kv-8w9tzfz1.js} +0 -0
  686. /package/dist/chunks/{pty-906y0b6d.js → kv-906y0b6d.js} +0 -0
  687. /package/dist/chunks/{pty-9dct5xhx.js → kv-9dct5xhx.js} +0 -0
  688. /package/dist/chunks/{pty-9sdtsapf.js → kv-9sdtsapf.js} +0 -0
  689. /package/dist/chunks/{pty-a02svayp.js → kv-a02svayp.js} +0 -0
  690. /package/dist/chunks/{pty-a83yvq99.js → kv-a83yvq99.js} +0 -0
  691. /package/dist/chunks/{pty-ayevdmef.js → kv-ayevdmef.js} +0 -0
  692. /package/dist/chunks/{pty-b02txbh8.js → kv-b02txbh8.js} +0 -0
  693. /package/dist/chunks/{pty-bbqs2y60.js → kv-bbqs2y60.js} +0 -0
  694. /package/dist/chunks/{pty-bjwj8hwv.js → kv-bjwj8hwv.js} +0 -0
  695. /package/dist/chunks/{pty-brsh5f65.js → kv-brsh5f65.js} +0 -0
  696. /package/dist/chunks/{pty-bxdhjb3y.js → kv-bxdhjb3y.js} +0 -0
  697. /package/dist/chunks/{pty-c77ad0vh.js → kv-c77ad0vh.js} +0 -0
  698. /package/dist/chunks/{pty-ck5pgha0.js → kv-ck5pgha0.js} +0 -0
  699. /package/dist/chunks/{pty-cm67rqy2.js → kv-cm67rqy2.js} +0 -0
  700. /package/dist/chunks/{pty-df3v2q6j.js → kv-df3v2q6j.js} +0 -0
  701. /package/dist/chunks/{pty-dhcq6c44.js → kv-dhcq6c44.js} +0 -0
  702. /package/dist/chunks/{pty-dht5baf0.js → kv-dht5baf0.js} +0 -0
  703. /package/dist/chunks/{pty-dkmkay92.js → kv-dkmkay92.js} +0 -0
  704. /package/dist/chunks/{pty-drean1vx.js → kv-drean1vx.js} +0 -0
  705. /package/dist/chunks/{pty-ehj9csmv.js → kv-ehj9csmv.js} +0 -0
  706. /package/dist/chunks/{pty-em6xpscd.js → kv-em6xpscd.js} +0 -0
  707. /package/dist/chunks/{pty-emmqknsm.js → kv-emmqknsm.js} +0 -0
  708. /package/dist/chunks/{pty-ezs3tagn.js → kv-ezs3tagn.js} +0 -0
  709. /package/dist/chunks/{pty-f14r7hfz.js → kv-f14r7hfz.js} +0 -0
  710. /package/dist/chunks/{pty-f4cp4g4a.js → kv-f4cp4g4a.js} +0 -0
  711. /package/dist/chunks/{pty-faypg4r1.js → kv-faypg4r1.js} +0 -0
  712. /package/dist/chunks/{pty-fgbfdq62.js → kv-fgbfdq62.js} +0 -0
  713. /package/dist/chunks/{pty-gd5xeqc2.js → kv-gd5xeqc2.js} +0 -0
  714. /package/dist/chunks/{pty-ghm4673n.js → kv-ghm4673n.js} +0 -0
  715. /package/dist/chunks/{pty-ghwjy7my.js → kv-ghwjy7my.js} +0 -0
  716. /package/dist/chunks/{pty-gqn2zsfg.js → kv-gqn2zsfg.js} +0 -0
  717. /package/dist/chunks/{pty-gy500k2r.js → kv-gy500k2r.js} +0 -0
  718. /package/dist/chunks/{pty-h846wrk2.js → kv-h846wrk2.js} +0 -0
  719. /package/dist/chunks/{pty-hzeg9cfr.js → kv-hzeg9cfr.js} +0 -0
  720. /package/dist/chunks/{pty-j07kk359.js → kv-j07kk359.js} +0 -0
  721. /package/dist/chunks/{pty-jve7t217.js → kv-jve7t217.js} +0 -0
  722. /package/dist/chunks/{pty-k3e42drn.js → kv-k3e42drn.js} +0 -0
  723. /package/dist/chunks/{pty-k8b45nas.js → kv-k8b45nas.js} +0 -0
  724. /package/dist/chunks/{pty-kcacmy5c.js → kv-kcacmy5c.js} +0 -0
  725. /package/dist/chunks/{pty-kpdbz7gn.js → kv-kpdbz7gn.js} +0 -0
  726. /package/dist/chunks/{pty-kxy11nzk.js → kv-kxy11nzk.js} +0 -0
  727. /package/dist/chunks/{pty-kyyqvx4s.js → kv-kyyqvx4s.js} +0 -0
  728. /package/dist/chunks/{pty-m8cbvarh.js → kv-m8cbvarh.js} +0 -0
  729. /package/dist/chunks/{pty-ma60vzgv.js → kv-ma60vzgv.js} +0 -0
  730. /package/dist/chunks/{pty-n3m50c2t.js → kv-n3m50c2t.js} +0 -0
  731. /package/dist/chunks/{pty-nkm1m8dz.js → kv-nkm1m8dz.js} +0 -0
  732. /package/dist/chunks/{pty-nsc0c3zb.js → kv-nsc0c3zb.js} +0 -0
  733. /package/dist/chunks/{pty-qaarhjrp.js → kv-qaarhjrp.js} +0 -0
  734. /package/dist/chunks/{pty-qc167nrn.js → kv-qc167nrn.js} +0 -0
  735. /package/dist/chunks/{pty-qp95y4jb.js → kv-qp95y4jb.js} +0 -0
  736. /package/dist/chunks/{pty-r8f4w671.js → kv-r8f4w671.js} +0 -0
  737. /package/dist/chunks/{pty-rdfev9jy.js → kv-rdfev9jy.js} +0 -0
  738. /package/dist/chunks/{pty-rvfvac9x.js → kv-rvfvac9x.js} +0 -0
  739. /package/dist/chunks/{pty-s7whb9gt.js → kv-s7whb9gt.js} +0 -0
  740. /package/dist/chunks/{pty-se76j685.js → kv-se76j685.js} +0 -0
  741. /package/dist/chunks/{pty-sem2g21k.js → kv-sem2g21k.js} +0 -0
  742. /package/dist/chunks/{pty-sp575ygv.js → kv-sp575ygv.js} +0 -0
  743. /package/dist/chunks/{pty-tmb1f636.js → kv-tmb1f636.js} +0 -0
  744. /package/dist/chunks/{pty-ttxf0gsy.js → kv-ttxf0gsy.js} +0 -0
  745. /package/dist/chunks/{pty-tvmhrvfj.js → kv-tvmhrvfj.js} +0 -0
  746. /package/dist/chunks/{pty-v2adqbbe.js → kv-v2adqbbe.js} +0 -0
  747. /package/dist/chunks/{pty-wj4sxzqa.js → kv-wj4sxzqa.js} +0 -0
  748. /package/dist/chunks/{pty-wwntjmk1.js → kv-wwntjmk1.js} +0 -0
  749. /package/dist/chunks/{pty-wyqjaaa5.js → kv-wyqjaaa5.js} +0 -0
  750. /package/dist/chunks/{pty-x4q807cx.js → kv-x4q807cx.js} +0 -0
  751. /package/dist/chunks/{pty-xt0068v8.js → kv-xt0068v8.js} +0 -0
  752. /package/dist/chunks/{pty-yrqrg4vp.js → kv-yrqrg4vp.js} +0 -0
  753. /package/dist/chunks/{pty-z47nswr2.js → kv-z47nswr2.js} +0 -0
  754. /package/dist/chunks/{pty-zsf8rs93.js → kv-zsf8rs93.js} +0 -0
@@ -1,92 +1,73 @@
1
1
  import {
2
2
  __export
3
- } from "../chunks/pty-rvfvac9x.js";
3
+ } from "../chunks/kv-rvfvac9x.js";
4
4
 
5
5
  // src/shell/scan.ts
6
6
  var exports_scan = {};
7
7
  __export(exports_scan, {
8
8
  scanPowerShell: () => scanPowerShell,
9
9
  scan: () => scan,
10
- ShellScan: () => exports_scan,
11
- Nested: () => Nested
10
+ ShellScan: () => exports_scan
12
11
  });
13
- var Nested = Symbol("ShellScan.Nested");
14
- var BASH_COMPOUND_KEYWORDS = new Set([
15
- "if",
16
- "then",
17
- "elif",
18
- "else",
19
- "fi",
20
- "for",
21
- "while",
22
- "until",
23
- "case",
24
- "select",
25
- "function",
26
- "do",
27
- "done",
28
- "coproc"
29
- ]);
30
- var POWERSHELL_LOCATIONS = new Set(["set-location", "cd", "chdir", "sl", "push-location", "pushd"]);
31
12
  var BASH_REDIRECTS = ["&>>", "&>", "<<<", "<<-", "<<", "<>", "<&", ">&", ">|", ">>", ">", "<"];
32
- var MAX_BASH_INPUT_LENGTH = 64 * 1024;
13
+ var BASH_DECLARATIONS = new Set(["declare", "typeset", "export", "readonly", "local", "unset", "unsetenv"]);
14
+ var MAX_INPUT_LENGTH = 64 * 1024;
33
15
  var MAX_SUBSTITUTION_DEPTH = 32;
34
16
  function scan(input) {
35
- return scanBash(input, 0);
17
+ return scanBash(input, 0, { remaining: MAX_INPUT_LENGTH * MAX_SUBSTITUTION_DEPTH });
36
18
  }
37
- function scanBash(input, depth) {
38
- if (input.length > MAX_BASH_INPUT_LENGTH)
19
+ function scanBash(input, depth, budget) {
20
+ budget.remaining -= input.length;
21
+ if (input.length > MAX_INPUT_LENGTH || budget.remaining < 0 || depth > MAX_SUBSTITUTION_DEPTH)
39
22
  return { kind: "opaque", reason: "invalid-structure" };
40
- const group = bashLeadingGroup(input);
41
- if (group) {
42
- if (depth >= MAX_SUBSTITUTION_DEPTH)
43
- return { kind: "opaque", reason: "invalid-structure" };
44
- const nested = scanBash(group.source, depth + 1);
45
- if (nested.kind === "opaque")
46
- return nested;
47
- const suffix = input.slice(group.end + 1).trim();
48
- if (!suffix)
49
- return nested;
50
- const separator = /^(?:&&|\|\||\|&|[;&|])/.exec(suffix)?.[0];
51
- const remaining = separator ? suffix.slice(separator.length).trim() : suffix;
52
- if (separator && !remaining)
53
- return nested;
54
- const prefixed = separator ? remaining : /^[<>]/.test(remaining) ? `: ${remaining}` : undefined;
55
- if (!prefixed)
56
- return { kind: "opaque", reason: "compound-command" };
57
- const rest = scanBash(prefixed, depth + 1);
58
- if (rest.kind === "opaque")
59
- return rest;
60
- return {
61
- kind: "scanned",
62
- commands: nested.commands.concat(rest.commands.filter((command) => command.words[0] !== ":"))
63
- };
64
- }
65
23
  const commands = [];
66
24
  const nestedCommands = [];
67
25
  const words = [];
26
+ const rawWords = [];
68
27
  const assignmentWords = [];
69
28
  let word = "";
70
29
  let wordStarted = false;
30
+ let wordStart = 0;
31
+ let wordEnd = 0;
32
+ let commandEnd = 0;
33
+ let resourceEnd;
34
+ let redirectWordCount;
71
35
  let assignmentWord = false;
72
36
  let assignmentHeadUnsafe = false;
73
37
  let segment = 0;
74
38
  let quote;
75
- let compound = false;
76
39
  let invalidRedirect = false;
77
40
  let invalidStructure = false;
78
41
  let separated = false;
79
- let comment;
80
- let heredoc = false;
81
42
  let redirectTarget = false;
82
43
  let hasRedirect = false;
83
- let terminalBackground = false;
44
+ let dangling = false;
45
+ let inList = false;
46
+ let compoundEnd = false;
47
+ const heredocs = [];
48
+ const structures = [];
49
+ const addSubstitutions = (substitution) => {
50
+ for (const source of substitution.substitutions ?? [substitution.source]) {
51
+ const result = scanBash(source, depth + 1, budget);
52
+ if (result.kind === "opaque")
53
+ return result;
54
+ nestedCommands.push(...result.commands);
55
+ }
56
+ };
57
+ const statement = () => {
58
+ const structure = structures.at(-1);
59
+ if (structure)
60
+ structure.count++;
61
+ };
62
+ const header = () => ["header", "pattern", "do"].includes(structures.at(-1)?.phase ?? "");
84
63
  const finishWord = () => {
85
64
  if (!wordStarted)
86
65
  return;
87
66
  if (!redirectTarget) {
88
67
  words.push(word);
68
+ rawWords.push(input.slice(wordStart, wordEnd));
89
69
  assignmentWords.push(assignmentWord);
70
+ commandEnd = wordEnd;
90
71
  }
91
72
  redirectTarget = false;
92
73
  word = "";
@@ -94,29 +75,185 @@ function scanBash(input, depth) {
94
75
  assignmentWord = false;
95
76
  assignmentHeadUnsafe = false;
96
77
  };
97
- const finishCommand = (end, boundary = false) => {
78
+ const finishCommand = (boundary = false) => {
98
79
  finishWord();
99
- const resource = input.slice(segment, end).trim();
80
+ if (redirectTarget)
81
+ invalidRedirect = true;
82
+ redirectTarget = false;
83
+ if (compoundEnd && words.length > 0)
84
+ invalidStructure = true;
85
+ const resource = input.slice(segment, resourceEnd ?? wordEnd).replace(/^[ \t\n]+|[ \t\n]+$/g, "");
100
86
  const name = assignmentWords.findIndex((assignment) => !assignment);
101
- if (name >= 0 && /[*?[]/.test(words[name]))
102
- compound = true;
103
- if (resource && name >= 0)
104
- commands.push({
105
- resource,
106
- words: words.slice(name)
107
- });
108
- else if (!(assignmentWords.length > 0 && assignmentWords.every(Boolean)) && (hasRedirect || boundary || separated))
87
+ if (name >= 0 && !words[name])
109
88
  invalidStructure = true;
89
+ if (rawWords[name] === "}")
90
+ invalidStructure = true;
91
+ if (resource && name >= 0 && !header()) {
92
+ const command = {
93
+ resource,
94
+ words: words.slice(name),
95
+ rawWords: rawWords.slice(name),
96
+ ...name === 0 && BASH_DECLARATIONS.has(rawWords[0]) && resource.startsWith(rawWords[0]) ? { declaration: true } : {},
97
+ ...redirectWordCount !== undefined && redirectWordCount < words.length ? { redirectWordCount: redirectWordCount - name } : {}
98
+ };
99
+ commands.push(command);
100
+ if (resourceEnd === undefined) {
101
+ for (const heredoc of heredocs) {
102
+ if (heredoc.command)
103
+ continue;
104
+ heredoc.command = command;
105
+ heredoc.start = segment;
106
+ }
107
+ }
108
+ } else if (!header() && !compoundEnd && (hasRedirect || boundary || separated)) {
109
+ const assignmentOnly = assignmentWords.length > 0 && assignmentWords.every(Boolean);
110
+ if (!assignmentOnly && !hasRedirect)
111
+ invalidStructure = true;
112
+ }
110
113
  commands.push(...nestedCommands.splice(0));
114
+ if (!header() && (words.length > 0 || hasRedirect))
115
+ statement();
111
116
  words.length = 0;
117
+ rawWords.length = 0;
112
118
  assignmentWords.length = 0;
113
119
  separated = true;
114
120
  hasRedirect = false;
121
+ resourceEnd = undefined;
122
+ redirectWordCount = undefined;
123
+ compoundEnd = false;
115
124
  };
116
125
  for (let index = 0;index < input.length; index++) {
117
126
  const char = input[index];
127
+ if (!wordStarted)
128
+ wordStart = index;
129
+ if (!quote && !wordStarted) {
130
+ const structure = structures.at(-1);
131
+ const token = /^[A-Za-z_][A-Za-z0-9_]*(?=[ \t\n;()<>]|$)/.exec(input.slice(index))?.[0];
132
+ if (structure?.kind === "case" && structure.phase === "header" && token === "in") {
133
+ finishCommand();
134
+ structure.phase = "pattern";
135
+ index += token.length - 1;
136
+ segment = index + 1;
137
+ continue;
138
+ }
139
+ if (structure?.phase === "pattern" && (char === "(" || char === "|"))
140
+ continue;
141
+ if (structure?.phase === "pattern" && char === ")") {
142
+ finishCommand();
143
+ structure.phase = "body";
144
+ structure.count = 0;
145
+ segment = index + 1;
146
+ continue;
147
+ }
148
+ if (!words.length && !hasRedirect && !compoundEnd) {
149
+ const definition = /^(?:function[ \t]+[A-Za-z_][A-Za-z0-9_]*(?:[ \t]*\([ \t]*\))?|[A-Za-z_][A-Za-z0-9_]*[ \t]*\([ \t]*\))[ \t\n]*(?=[{(])/.exec(input.slice(index));
150
+ if (definition && !header()) {
151
+ index += definition[0].length - 1;
152
+ segment = index + 1;
153
+ continue;
154
+ }
155
+ if (!header() && (token === "if" || token === "while" || token === "until" || token === "for" || token === "select" || token === "case")) {
156
+ if (depth + structures.length >= MAX_SUBSTITUTION_DEPTH)
157
+ return { kind: "opaque", reason: "compound-command" };
158
+ structures.push({
159
+ kind: token === "select" ? "for" : token,
160
+ phase: ["for", "select", "case"].includes(token) ? "header" : "condition",
161
+ count: 0
162
+ });
163
+ index += token.length - 1;
164
+ segment = index + 1;
165
+ inList = false;
166
+ continue;
167
+ }
168
+ if (token && ["then", "elif", "else", "fi", "do", "done", "esac"].includes(token) && (!header() || token === "do" && structure?.phase === "do" || token === "esac" && structure?.phase === "pattern")) {
169
+ if (!structure || dangling)
170
+ return { kind: "opaque", reason: "compound-command" };
171
+ if (token === "then") {
172
+ if (structure.kind !== "if" || structure.phase !== "condition" || !structure.count)
173
+ return { kind: "opaque", reason: "compound-command" };
174
+ structure.phase = "body";
175
+ } else if (token === "elif" || token === "else") {
176
+ if (structure.kind !== "if" || structure.phase !== "body" || !structure.count || structure.sawElse)
177
+ return { kind: "opaque", reason: "compound-command" };
178
+ structure.phase = token === "elif" ? "condition" : "body";
179
+ structure.sawElse = token === "else";
180
+ } else if (token === "do") {
181
+ if (!["for", "while", "until"].includes(structure.kind) || !["condition", "do"].includes(structure.phase) || structure.kind !== "for" && !structure.count)
182
+ return { kind: "opaque", reason: "compound-command" };
183
+ structure.phase = "body";
184
+ } else {
185
+ if (token === "fi" && (structure.kind !== "if" || structure.phase !== "body" || !structure.count) || token === "done" && (!["for", "while", "until"].includes(structure.kind) || structure.phase !== "body" || !structure.count) || token === "esac" && (structure.kind !== "case" || structure.phase === "header"))
186
+ return { kind: "opaque", reason: "compound-command" };
187
+ structures.pop();
188
+ statement();
189
+ compoundEnd = true;
190
+ dangling = false;
191
+ }
192
+ structure.count = 0;
193
+ index += token.length - 1;
194
+ segment = index + 1;
195
+ inList = false;
196
+ continue;
197
+ }
198
+ if (!header() && (char === "!" && /[ \t\n]/.test(input[index + 1] ?? "") || token === "coproc" && /^coproc[ \t]+(?:[A-Za-z_][A-Za-z0-9_]*[ \t]+)?(?:[{(]|(?:if|while|until|for|case)\b)/.test(input.slice(index)) || token === "time" && /^time[ \t]+(?:-p[ \t]+)?(?:[{(]|(?:if|while|until|for|case)\b)/.test(input.slice(index)))) {
199
+ index += token ? token.length - 1 : 0;
200
+ if (token === "time")
201
+ index += /^[ \t]+-p\b/.exec(input.slice(index + 1))?.[0].length ?? 0;
202
+ if (token === "coproc")
203
+ index += /^[ \t]+[A-Za-z_][A-Za-z0-9_]*[ \t]+(?=[{(]|(?:if|while|until|for|case)\b)/.exec(input.slice(index + 1))?.[0].length ?? 0;
204
+ segment = index + 1;
205
+ continue;
206
+ }
207
+ }
208
+ if ((!words.length && !hasRedirect && !header() || structure?.kind === "for" && structure.phase === "header") && input.startsWith("((", index)) {
209
+ const expression = bashExpansion(input, index, depth, "arithmetic");
210
+ if (!expression)
211
+ return { kind: "opaque", reason: "invalid-structure" };
212
+ const failure = addSubstitutions(expression);
213
+ if (failure)
214
+ return failure;
215
+ commands.push(...nestedCommands.splice(0));
216
+ statement();
217
+ compoundEnd = !header();
218
+ dangling = false;
219
+ index = expression.end;
220
+ segment = index + 1;
221
+ continue;
222
+ }
223
+ if (!words.length && !hasRedirect && !header() && (char === "(" || char === "{" && /[ \t\n]/.test(input[index + 1] ?? ""))) {
224
+ const group = bashDelimited(input, index, depth);
225
+ if (!group || !group.source.trim())
226
+ return { kind: "opaque", reason: "invalid-structure" };
227
+ const result = scanBash(group.source, depth + 1, budget);
228
+ if (result.kind === "opaque")
229
+ return result;
230
+ commands.push(...result.commands);
231
+ statement();
232
+ compoundEnd = true;
233
+ dangling = false;
234
+ index = group.end;
235
+ segment = index + 1;
236
+ continue;
237
+ }
238
+ if (!words.length && !hasRedirect && input.startsWith("[[", index)) {
239
+ const expression = bashExpansion(input, index, depth, "test");
240
+ if (!expression)
241
+ return { kind: "opaque", reason: "invalid-structure" };
242
+ const failure = addSubstitutions(expression);
243
+ if (failure)
244
+ return failure;
245
+ commands.push(...nestedCommands.splice(0));
246
+ statement();
247
+ compoundEnd = true;
248
+ dangling = false;
249
+ index = expression.end;
250
+ segment = index + 1;
251
+ continue;
252
+ }
253
+ }
118
254
  if (quote === "single") {
119
255
  wordStarted = true;
256
+ wordEnd = index + 1;
120
257
  if (char === "'")
121
258
  quote = undefined;
122
259
  else
@@ -136,28 +273,44 @@ function scanBash(input, depth) {
136
273
  word += next2;
137
274
  } else
138
275
  word += char;
139
- } else if (char === "$" && input[index + 1] === "(" || char === "`") {
140
- const substitution = bashSubstitution(input, index);
276
+ } else if (char === "$" && "({[".includes(input[index + 1] ?? "\x00") || char === "`") {
277
+ const substitution = bashExpansion(input, index, depth, undefined, true);
141
278
  if (!substitution || depth >= MAX_SUBSTITUTION_DEPTH)
142
279
  return { kind: "opaque", reason: "command-substitution" };
143
- const result = scanBash(substitution.source, depth + 1);
144
- if (result.kind === "opaque")
145
- return result;
146
- nestedCommands.push(...result.commands.map(markNested));
280
+ const failure = addSubstitutions(substitution);
281
+ if (failure)
282
+ return failure;
147
283
  word += input.slice(index, substitution.end + 1);
148
284
  index = substitution.end;
149
- } else {
150
- if (char === "$" && /^\$\{[^}:@]+@P\}/.test(input.slice(index)))
151
- return { kind: "opaque", reason: "dynamic-execution" };
152
- if (char === "$" && /^\$\{\([^)]*e[^)]*\)/.test(input.slice(index)))
153
- return { kind: "opaque", reason: "dynamic-execution" };
285
+ } else
154
286
  word += char;
155
- }
287
+ wordEnd = index + 1;
288
+ continue;
289
+ }
290
+ if (char === "$" && input[index + 1] === "'") {
291
+ const literal = bashAnsiQuote(input, index + 1);
292
+ if (!literal)
293
+ return { kind: "opaque", reason: "unterminated-quote" };
294
+ wordStarted = true;
295
+ if (!assignmentWord)
296
+ assignmentHeadUnsafe = true;
297
+ word += literal.value;
298
+ index = literal.end;
299
+ wordEnd = index + 1;
300
+ continue;
301
+ }
302
+ if (char === "$" && input[index + 1] === '"') {
303
+ quote = "double";
304
+ wordStarted = true;
305
+ if (!assignmentWord)
306
+ assignmentHeadUnsafe = true;
307
+ wordEnd = ++index + 1;
156
308
  continue;
157
309
  }
158
310
  if (char === "'") {
159
311
  quote = "single";
160
312
  wordStarted = true;
313
+ wordEnd = index + 1;
161
314
  if (!assignmentWord)
162
315
  assignmentHeadUnsafe = true;
163
316
  continue;
@@ -165,6 +318,7 @@ function scanBash(input, depth) {
165
318
  if (char === '"') {
166
319
  quote = "double";
167
320
  wordStarted = true;
321
+ wordEnd = index + 1;
168
322
  if (!assignmentWord)
169
323
  assignmentHeadUnsafe = true;
170
324
  continue;
@@ -172,60 +326,56 @@ function scanBash(input, depth) {
172
326
  if (char === "\\") {
173
327
  if (index + 1 >= input.length)
174
328
  return { kind: "opaque", reason: "unterminated-escape" };
175
- wordStarted = true;
176
329
  if (input[index + 1] === `
177
330
  `)
178
331
  index++;
179
332
  else {
333
+ wordStarted = true;
180
334
  if (!assignmentWord)
181
335
  assignmentHeadUnsafe = true;
182
336
  word += input[++index];
337
+ wordEnd = index + 1;
183
338
  }
184
339
  continue;
185
340
  }
186
- if (char === "$" && input[index + 1] === "(" || char === "`") {
187
- const substitution = bashSubstitution(input, index);
341
+ if (char === "$" && "({[".includes(input[index + 1] ?? "\x00") || char === "`" || char === "[" && /^[A-Za-z_][A-Za-z0-9_]*$/.test(word) && /^\[[\s\S]*?\]\+?=/.test(input.slice(index)) || char === "(" && (assignmentWord || /[?*+@!]$/.test(word))) {
342
+ const substitution = char === "(" ? bashExpansion(input, index, depth, assignmentWord ? "array" : "pattern") : char === "[" ? bashExpansion(input, index, depth, "subscript") : bashExpansion(input, index, depth);
188
343
  if (!substitution || depth >= MAX_SUBSTITUTION_DEPTH)
189
344
  return { kind: "opaque", reason: "command-substitution" };
190
- const result = scanBash(substitution.source, depth + 1);
191
- if (result.kind === "opaque")
192
- return result;
193
- nestedCommands.push(...result.commands.map(markNested));
345
+ const failure = addSubstitutions(substitution);
346
+ if (failure)
347
+ return failure;
194
348
  wordStarted = true;
195
349
  word += input.slice(index, substitution.end + 1);
196
350
  index = substitution.end;
351
+ wordEnd = index + 1;
197
352
  continue;
198
353
  }
199
- if ((char === "<" || char === ">") && input[index + 1] === "(") {
200
- const substitution = bashParenthesized(input, index + 1);
354
+ if ((char === "<" || char === ">" || char === "=" && !wordStarted) && input[index + 1] === "(") {
355
+ const substitution = bashDelimited(input, index + 1, depth);
201
356
  if (!substitution || depth >= MAX_SUBSTITUTION_DEPTH)
202
357
  return { kind: "opaque", reason: "command-substitution" };
203
- const result = scanBash(substitution.source, depth + 1);
204
- if (result.kind === "opaque")
205
- return result;
206
- nestedCommands.push(...result.commands.map(markNested));
358
+ const failure = addSubstitutions(substitution);
359
+ if (failure)
360
+ return failure;
207
361
  wordStarted = true;
208
362
  word += input.slice(index, substitution.end + 1);
209
363
  index = substitution.end;
364
+ wordEnd = index + 1;
210
365
  continue;
211
366
  }
212
- if (char === "$" && input[index + 1] === "{" && /^\$\{[^}:@]+@P\}/.test(input.slice(index)))
213
- return { kind: "opaque", reason: "dynamic-execution" };
214
- if (char === "$" && /^\$\{\([^)]*e[^)]*\)/.test(input.slice(index)))
215
- return { kind: "opaque", reason: "dynamic-execution" };
216
- if (char === "$" && input[index + 1] === "[")
217
- return { kind: "opaque", reason: "dynamic-execution" };
218
- if (char === "<" && input[index + 1] === "<")
219
- heredoc = true;
220
367
  if (char === "#" && !wordStarted) {
221
- finishCommand(index);
222
- comment = index;
223
368
  const newline = input.indexOf(`
224
369
  `, index);
370
+ if (words.length > 0 || hasRedirect) {
371
+ finishCommand();
372
+ dangling = false;
373
+ inList = false;
374
+ }
225
375
  if (newline === -1)
226
376
  break;
227
- index = newline;
228
- segment = newline + 1;
377
+ index = newline - 1;
378
+ segment = newline;
229
379
  continue;
230
380
  }
231
381
  const redirect = "<>&".includes(char) ? BASH_REDIRECTS.find((candidate) => input.startsWith(candidate, index)) : undefined;
@@ -233,19 +383,43 @@ function scanBash(input, depth) {
233
383
  hasRedirect = true;
234
384
  if (redirectTarget)
235
385
  invalidRedirect = true;
236
- if (wordStarted && /^\d+$/.test(word)) {
386
+ if (wordStarted && !assignmentHeadUnsafe && /^(?:\d+|\{[A-Za-z_][A-Za-z0-9_]*\})$/.test(word)) {
387
+ if (wordEnd < index)
388
+ commandEnd = wordEnd;
237
389
  word = "";
238
390
  wordStarted = false;
239
391
  } else
240
392
  finishWord();
393
+ if (redirectWordCount === undefined && assignmentWords.some((assignment) => !assignment)) {
394
+ redirectWordCount = words.length;
395
+ if (inList)
396
+ resourceEnd = commandEnd;
397
+ }
398
+ if (redirect === "<<" || redirect === "<<-") {
399
+ const delimiter = bashHeredocDelimiter(input, index);
400
+ if (!delimiter)
401
+ return { kind: "opaque", reason: "invalid-redirect" };
402
+ heredocs.push(delimiter);
403
+ wordEnd = delimiter.end + 1;
404
+ index = delimiter.end;
405
+ redirectTarget = false;
406
+ continue;
407
+ }
241
408
  redirectTarget = true;
242
409
  index += redirect.length - 1;
243
410
  continue;
244
411
  }
245
- if ("()".includes(char) || char === "!" && !wordStarted)
246
- compound = true;
247
- if (/\s/.test(char) && char !== `
248
- `) {
412
+ if (structures.at(-1)?.phase === "pattern" && (char === ")" || char === "|")) {
413
+ finishWord();
414
+ index--;
415
+ continue;
416
+ }
417
+ if ("()".includes(char))
418
+ return { kind: "opaque", reason: "compound-command" };
419
+ if (/\s/.test(char) && !`
420
+ `.includes(char))
421
+ return { kind: "opaque", reason: "invalid-structure" };
422
+ if (char === " " || char === "\t") {
249
423
  finishWord();
250
424
  continue;
251
425
  }
@@ -253,315 +427,578 @@ function scanBash(input, depth) {
253
427
  const separator = char === "&" && next === "&" || char === "|" && (next === "|" || next === "&") ? char + next : char === ";" || char === "|" || char === "&" || char === `
254
428
  ` ? char : undefined;
255
429
  if (separator) {
256
- finishCommand(index, true);
257
- if (redirectTarget)
258
- invalidRedirect = true;
259
- terminalBackground = separator === "&" || separator === ";" || separator === `
430
+ const structure = structures.at(-1);
431
+ if (char === ";" && structure?.kind === "case" && structure.phase === "body" && (next === ";" || next === "&")) {
432
+ if (wordStarted || words.length || hasRedirect || compoundEnd)
433
+ finishCommand();
434
+ structure.phase = "pattern";
435
+ index += input.startsWith(";;&", index) ? 2 : 1;
436
+ segment = index + 1;
437
+ inList = false;
438
+ continue;
439
+ }
440
+ if (separator === `
441
+ ` && !wordStarted && words.length === 0 && !hasRedirect && !compoundEnd) {
442
+ if (heredocs.length) {
443
+ for (const heredoc of heredocs.splice(0)) {
444
+ const body = bashHeredoc(input, index + 1, heredoc);
445
+ if (!body)
446
+ return { kind: "opaque", reason: "heredoc" };
447
+ if (heredoc.command)
448
+ heredoc.command.resource = input.slice(heredoc.start, body.end).trim();
449
+ if (!heredoc.quoted) {
450
+ const expansion = bashExpansion(body.source, 0, depth, "heredoc");
451
+ if (!expansion)
452
+ return { kind: "opaque", reason: "command-substitution" };
453
+ const failure = addSubstitutions(expansion);
454
+ if (failure)
455
+ return failure;
456
+ commands.push(...nestedCommands.splice(0));
457
+ }
458
+ index = body.end;
459
+ }
460
+ }
461
+ segment = index + 1;
462
+ continue;
463
+ }
464
+ finishCommand(true);
465
+ if (structure?.kind === "for" && structure.phase === "header")
466
+ structure.phase = "do";
467
+ dangling = separator !== "&" && separator !== ";" && separator !== `
260
468
  `;
469
+ inList = dangling;
470
+ if (separator === `
471
+ ` && heredocs.length) {
472
+ index--;
473
+ continue;
474
+ }
261
475
  index += separator.length - 1;
262
476
  segment = index + 1;
263
477
  continue;
264
478
  }
265
- terminalBackground = false;
266
479
  wordStarted = true;
267
- if (char === "=" && !assignmentHeadUnsafe && /^[A-Za-z_][A-Za-z0-9_]*\+?$/.test(word))
480
+ if (char === "=" && !assignmentHeadUnsafe && /^[A-Za-z_][A-Za-z0-9_]*(?:\[.*\])?\+?$/.test(word))
268
481
  assignmentWord = true;
269
482
  word += char;
483
+ wordEnd = index + 1;
270
484
  }
271
485
  if (quote)
272
486
  return { kind: "opaque", reason: "unterminated-quote" };
273
- if (heredoc)
487
+ if (heredocs.length)
274
488
  return { kind: "opaque", reason: "heredoc" };
275
- if (!terminalBackground && (comment === undefined || input.includes(`
276
- `, comment)))
277
- finishCommand(input.length);
278
- if (redirectTarget)
279
- invalidRedirect = true;
280
- if (separated && !terminalBackground && comment === undefined && !input.slice(segment).trim())
489
+ if (wordStarted || words.length > 0 || hasRedirect) {
490
+ finishCommand();
491
+ dangling = false;
492
+ }
493
+ if (dangling)
281
494
  invalidStructure = true;
282
495
  if (invalidStructure)
283
496
  return { kind: "opaque", reason: "invalid-structure" };
284
497
  if (invalidRedirect)
285
498
  return { kind: "opaque", reason: "invalid-redirect" };
286
- const conditional = bashConditionalCommands(commands);
287
- if (conditional)
288
- commands.splice(0, commands.length, ...conditional);
289
- if (compound || commands.some((command) => BASH_COMPOUND_KEYWORDS.has(command.words[0] ?? "")))
499
+ if (structures.length)
290
500
  return { kind: "opaque", reason: "compound-command" };
291
- if (commands.some((command) => /[$`]/.test(command.words[0] ?? "")))
292
- return { kind: "opaque", reason: "dynamic-command-name" };
293
- if (commands.some((command) => command.words[0]?.startsWith("=")))
294
- return { kind: "opaque", reason: "dynamic-command-name" };
295
501
  return { kind: "scanned", commands };
296
502
  }
297
- function bashConditionalCommands(commands) {
298
- if (commands[0]?.words[0] !== "if" || commands.at(-1)?.words[0] !== "fi")
503
+ function bashDelimited(input, start, depth) {
504
+ if (depth >= MAX_SUBSTITUTION_DEPTH)
299
505
  return;
300
- const keywords = new Set(["if", "then", "elif", "else", "fi"]);
301
- if (commands.some((command) => BASH_COMPOUND_KEYWORDS.has(command.words[0] ?? "") && !keywords.has(command.words[0])))
302
- return;
303
- const normalized = [];
304
- let phase = "condition";
305
- let hasCommand = false;
306
- let sawElse = false;
307
- for (const [index, command] of commands.entries()) {
308
- const keyword = command.words[0];
309
- if (!keywords.has(keyword ?? "")) {
310
- normalized.push(command);
311
- hasCommand = true;
312
- continue;
313
- }
314
- const offset = command.resource.indexOf(keyword) + keyword.length;
315
- const inline = command.words.length > 1 ? { resource: command.resource.slice(offset).trim(), words: command.words.slice(1) } : undefined;
316
- if (index === 0) {
317
- if (inline)
318
- normalized.push(inline);
319
- hasCommand = Boolean(inline);
320
- continue;
321
- }
322
- if (keyword === "then") {
323
- if (phase !== "condition" || !hasCommand)
324
- return;
325
- phase = "body";
326
- hasCommand = Boolean(inline);
506
+ const close = input[start] === "{" ? "}" : ")";
507
+ const cases = [];
508
+ const heredocs = [];
509
+ let commandStart = true;
510
+ for (let index = start + 1;index < input.length; index++) {
511
+ const char = input[index];
512
+ if (char === "\\") {
513
+ if (input[index + 1] !== `
514
+ `)
515
+ commandStart = false;
516
+ index++;
517
+ continue;
327
518
  }
328
- if (keyword === "elif") {
329
- if (phase !== "body" || !hasCommand || sawElse)
519
+ if (char === "'" || char === '"' || char === "`" || char === "$" && `({['"`.includes(input[index + 1] ?? "\x00")) {
520
+ commandStart = false;
521
+ if (char === "'" || input.startsWith("$'", index)) {
522
+ const end = char === "'" ? input.indexOf("'", index + 1) : bashAnsiQuote(input, index + 1)?.end;
523
+ if (end === undefined || end < 0)
524
+ return;
525
+ index = end;
526
+ continue;
527
+ }
528
+ const nested = char === '"' || input.startsWith('$"', index) ? bashExpansion(input, index + (char === "$" ? 1 : 0), depth + 1, "double") : bashExpansion(input, index, depth + 1);
529
+ if (!nested)
330
530
  return;
331
- phase = "condition";
332
- hasCommand = Boolean(inline);
531
+ index = nested.end;
532
+ continue;
333
533
  }
334
- if (keyword === "else") {
335
- if (phase !== "body" || !hasCommand || sawElse)
534
+ const boundary = index === start + 1 || /[ \t\n;|&(){}]/.test(input[index - 1]);
535
+ if (char === "#" && boundary) {
536
+ const newline = input.indexOf(`
537
+ `, index);
538
+ if (newline < 0)
336
539
  return;
337
- phase = "else";
338
- sawElse = true;
339
- hasCommand = Boolean(inline);
540
+ index = newline - 1;
541
+ continue;
340
542
  }
341
- if (keyword === "fi") {
342
- if (index !== commands.length - 1 || phase === "condition" || !hasCommand || inline)
543
+ if (input.startsWith("<<<", index)) {
544
+ index += 2;
545
+ continue;
546
+ }
547
+ if (input.startsWith("<<", index)) {
548
+ const delimiter = bashHeredocDelimiter(input, index);
549
+ if (!delimiter)
343
550
  return;
551
+ heredocs.push(delimiter);
552
+ index = delimiter.end;
344
553
  continue;
345
554
  }
346
- if (inline)
347
- normalized.push(inline);
348
- }
349
- return normalized;
350
- }
351
- function bashLeadingGroup(input) {
352
- const start = input.search(/\S/);
353
- if (start < 0)
354
- return;
355
- if (input[start] === "{") {
356
- const group = bashBraced(input, start);
357
- if (!group)
358
- return;
359
- const source = group.source.trim();
360
- if (!source.endsWith(";"))
361
- return;
362
- return { source: source.slice(0, -1), end: group.end };
363
- }
364
- if (input[start] !== "(")
365
- return;
366
- return bashParenthesized(input, start);
367
- }
368
- function bashBraced(input, start) {
369
- let quote;
370
- let level = 1;
371
- for (let index = start + 1;index < input.length; index++) {
372
- const char = input[index];
373
- if (quote === "single") {
374
- if (char === "'")
375
- quote = undefined;
555
+ if (char === `
556
+ ` && heredocs.length) {
557
+ for (const heredoc of heredocs.splice(0)) {
558
+ const body = bashHeredoc(input, index + 1, heredoc);
559
+ if (!body)
560
+ return;
561
+ index = body.end;
562
+ }
563
+ commandStart = true;
376
564
  continue;
377
565
  }
378
- if (char === "\\") {
379
- index++;
566
+ const token = boundary ? /^[A-Za-z_][A-Za-z0-9_]*(?=[ \t\n;()<>]|$)/.exec(input.slice(index))?.[0] : undefined;
567
+ if (token === "case" && commandStart)
568
+ cases.push("header");
569
+ if (token === "in" && cases.at(-1) === "header")
570
+ cases[cases.length - 1] = "pattern";
571
+ if (token === "esac" && (commandStart || cases.at(-1) === "pattern"))
572
+ cases.pop();
573
+ if (token) {
574
+ commandStart = commandStart && ["if", "while", "until", "then", "elif", "else", "do"].includes(token);
575
+ index += token.length - 1;
380
576
  continue;
381
577
  }
382
- if (char === "'") {
383
- quote = "single";
578
+ if (cases.length && char === ";" && /[;&]/.test(input[index + 1] ?? ""))
579
+ cases[cases.length - 1] = "pattern";
580
+ if (cases.at(-1) === "pattern" && char === "(")
581
+ continue;
582
+ if (cases.at(-1) === "pattern" && char === ")") {
583
+ cases[cases.length - 1] = "body";
584
+ commandStart = true;
384
585
  continue;
385
586
  }
386
- if (char === '"') {
387
- quote = quote === "double" ? undefined : "double";
587
+ if (input.startsWith("((", index)) {
588
+ const nested = bashExpansion(input, index, depth + 1, "arithmetic");
589
+ if (!nested)
590
+ return;
591
+ index = nested.end;
592
+ commandStart = false;
388
593
  continue;
389
594
  }
390
- if (char === "{" && quote !== "double")
391
- level++;
392
- if (char !== "}" || quote === "double" || --level)
595
+ if (char === "(" || char === "{" && boundary && /[ \t\n]/.test(input[index + 1] ?? "")) {
596
+ const nested = bashDelimited(input, index, depth + 1);
597
+ if (!nested)
598
+ return;
599
+ index = nested.end;
600
+ commandStart = false;
393
601
  continue;
394
- return { source: input.slice(start + 1, index), end: index };
602
+ }
603
+ if (char === close && (close === ")" || boundary))
604
+ return { source: input.slice(start + 1, index), end: index };
605
+ if (/[\n;&|]/.test(char))
606
+ commandStart = true;
607
+ else if (!/[ \t]/.test(char))
608
+ commandStart = false;
395
609
  }
396
610
  }
397
- function bashParenthesized(input, start) {
398
- let quote;
399
- let level = 1;
400
- for (let index = start + 1;index < input.length; index++) {
611
+ function bashExpansion(input, start, depth, mode, quoted = false) {
612
+ if (depth >= MAX_SUBSTITUTION_DEPTH)
613
+ return;
614
+ if (!mode && input[start] === "`") {
615
+ let source = "";
616
+ for (let index = start + 1;index < input.length; index++) {
617
+ if (input[index] === "`")
618
+ return { source, end: index };
619
+ if (input[index] === "\\" && "$`\\\n".includes(input[index + 1] ?? "\x00")) {
620
+ if (input[++index] !== `
621
+ `)
622
+ source += input[index];
623
+ continue;
624
+ }
625
+ source += input[index];
626
+ }
627
+ return;
628
+ }
629
+ if (!mode && input.startsWith("$(", start) && !input.startsWith("$((", start))
630
+ return bashDelimited(input, start + 1, depth);
631
+ if (!mode && /^\$\{[ \t\n|]/.test(input.slice(start))) {
632
+ const nested = bashDelimited(input, start + 1, depth);
633
+ if (!nested)
634
+ return;
635
+ return { ...nested, source: nested.source.startsWith("|") ? nested.source.slice(1) : nested.source };
636
+ }
637
+ const kind = mode ?? (input[start + 1] === "{" ? "parameter" : input[start + 1] === "[" ? "subscript" : "arithmetic");
638
+ const arithmetic = ["arithmetic", "arithmetic-group", "subscript"].includes(kind);
639
+ const offset = mode ? kind === "heredoc" ? 0 : kind === "arithmetic" || kind === "test" ? 2 : 1 : kind === "arithmetic" ? 3 : 2;
640
+ const close = kind === "heredoc" ? undefined : kind === "double" ? '"' : kind === "parameter" ? "}" : kind === "subscript" ? "]" : kind === "test" ? "]]" : kind === "arithmetic" ? "))" : ")";
641
+ const substitutions = [];
642
+ for (let index = start + offset;index < input.length; index++) {
401
643
  const char = input[index];
402
- if (quote === "single") {
403
- if (char === "'")
404
- quote = undefined;
644
+ if (close && input.startsWith(close, index))
645
+ return { source: input.slice(start + offset, index), end: index + close.length - 1, substitutions };
646
+ if (char === "\\") {
647
+ if (kind !== "heredoc" && kind !== "double" || '$`\\\n"'.includes(input[index + 1] ?? "\x00"))
648
+ index++;
405
649
  continue;
406
650
  }
407
- if (char === "\\") {
408
- index++;
651
+ if ((char === "'" || input.startsWith("$'", index)) && kind !== "double" && kind !== "heredoc" && !arithmetic && !(kind === "parameter" && quoted)) {
652
+ const end = char === "'" ? input.indexOf("'", index + 1) : bashAnsiQuote(input, index + 1)?.end;
653
+ if (end === undefined || end < 0)
654
+ return;
655
+ index = end;
409
656
  continue;
410
657
  }
411
- if (char === "'") {
412
- quote = "single";
658
+ if (char === '"' && kind !== "heredoc") {
659
+ const nested = bashExpansion(input, index, depth + 1, "double");
660
+ if (!nested)
661
+ return;
662
+ substitutions.push(...nested.substitutions);
663
+ index = nested.end;
413
664
  continue;
414
665
  }
415
- if (char === '"') {
416
- quote = quote === "double" ? undefined : "double";
666
+ if (char === "`" || char === "$" && "({[".includes(input[index + 1] ?? "\x00")) {
667
+ const nested = bashExpansion(input, index, depth + 1, undefined, kind === "double" || quoted);
668
+ if (!nested)
669
+ return;
670
+ substitutions.push(...nested.substitutions ?? [nested.source]);
671
+ index = nested.end;
417
672
  continue;
418
673
  }
419
- if (char === "(" && quote !== "double")
420
- level++;
421
- if (char !== ")" || quote === "double" || --level)
674
+ if (kind === "array" && "<>=".includes(char) && input[index + 1] === "(") {
675
+ const nested = bashDelimited(input, index + 1, depth + 1);
676
+ if (!nested)
677
+ return;
678
+ substitutions.push(nested.source);
679
+ index = nested.end;
680
+ continue;
681
+ }
682
+ if ((arithmetic || kind === "array" || kind === "pattern") && (char === "(" || char === "[") || kind === "parameter" && char === "[" && /^[!#]?[A-Za-z_][A-Za-z0-9_]*$/.test(input.slice(start + offset, index))) {
683
+ const nested = bashExpansion(input, index, depth + 1, char === "[" ? "subscript" : arithmetic ? "arithmetic-group" : kind);
684
+ if (!nested)
685
+ return;
686
+ substitutions.push(...nested.substitutions);
687
+ index = nested.end;
422
688
  continue;
423
- return { source: input.slice(start + 1, index), end: index };
689
+ }
690
+ if (!mode && kind === "arithmetic" && char === ";")
691
+ return;
424
692
  }
693
+ if (kind === "heredoc")
694
+ return { source: input.slice(start), end: input.length - 1, substitutions };
425
695
  }
426
- function bashSubstitution(input, start) {
427
- if (input[start] === "`") {
428
- for (let index = start + 1;index < input.length; index++) {
429
- if (input[index] === "\\")
430
- index++;
431
- else if (input[index] === "`")
432
- return { source: input.slice(start + 1, index).replaceAll("\\`", "`"), end: index };
696
+ function bashAnsiQuote(input, start) {
697
+ let value = "";
698
+ for (let index = start + 1;index < input.length; index++) {
699
+ if (input[index] === "'")
700
+ return { value, end: index };
701
+ if (input[index] !== "\\") {
702
+ value += input[index];
703
+ continue;
704
+ }
705
+ const escaped = input[++index];
706
+ const simple = {
707
+ a: "\x07",
708
+ b: "\b",
709
+ e: "\x1B",
710
+ E: "\x1B",
711
+ f: "\f",
712
+ n: `
713
+ `,
714
+ r: "\r",
715
+ t: "\t",
716
+ v: "\v",
717
+ "\\": "\\",
718
+ "'": "'",
719
+ '"': '"',
720
+ "?": "?"
721
+ };
722
+ if (escaped in simple)
723
+ value += simple[escaped];
724
+ else if (escaped === "c" && index + 1 < input.length)
725
+ value += String.fromCharCode(input[++index].toUpperCase().charCodeAt(0) & 31);
726
+ else {
727
+ const digits = escaped === "x" ? /^[\da-fA-F]{1,2}/.exec(input.slice(index + 1))?.[0] : escaped === "u" ? /^[\da-fA-F]{1,4}/.exec(input.slice(index + 1))?.[0] : escaped === "U" ? /^[\da-fA-F]{1,8}/.exec(input.slice(index + 1))?.[0] : /[0-7]/.test(escaped ?? "") ? /^[0-7]{1,3}/.exec(input.slice(index))?.[0] : undefined;
728
+ if (!digits)
729
+ value += `\\${escaped}`;
730
+ else {
731
+ const octal = /[0-7]/.test(escaped);
732
+ const point = parseInt(digits, octal ? 8 : 16);
733
+ value += point <= 1114111 ? String.fromCodePoint(point) : "";
734
+ index += digits.length - (octal ? 1 : 0);
735
+ }
433
736
  }
434
- return;
435
737
  }
436
- if (input.slice(start, start + 3) === "$((")
437
- return;
738
+ }
739
+ function bashHeredocDelimiter(input, start) {
740
+ const tabs = input[start + 2] === "-";
741
+ let delimiter = "";
742
+ let quoted = false;
438
743
  let quote;
439
- let level = 1;
440
- for (let index = start + 2;index < input.length; index++) {
744
+ let end = start;
745
+ let started = false;
746
+ for (let index = start + (tabs ? 3 : 2);index < input.length; index++) {
441
747
  const char = input[index];
442
- if (quote === "single") {
443
- if (char === "'")
444
- quote = undefined;
748
+ if (!started && /[ \t]/.test(char))
445
749
  continue;
446
- }
447
- if (char === "\\") {
448
- index++;
750
+ if (!started && char === "#")
751
+ return;
752
+ if (!quote && /[ \t\n;&|()<>]/.test(char))
753
+ return started ? { delimiter, quoted, tabs, end } : undefined;
754
+ if (!quote && input.startsWith("$'", index)) {
755
+ const literal = bashAnsiQuote(input, index + 1);
756
+ if (!literal)
757
+ return;
758
+ delimiter += literal.value;
759
+ quoted = true;
760
+ started = true;
761
+ index = literal.end;
762
+ end = index;
449
763
  continue;
450
764
  }
451
- if (char === "'") {
452
- quote = "single";
765
+ if (!quote && input.startsWith('$"', index)) {
766
+ quote = '"';
767
+ quoted = true;
768
+ started = true;
769
+ end = ++index;
453
770
  continue;
454
771
  }
455
- if (quote !== "double" && char === "#" && (index === start + 2 || /[\s;&|()]/.test(input[index - 1] ?? "")))
456
- return;
457
- if (char === '"') {
458
- quote = quote === "double" ? undefined : "double";
772
+ if (char === quote) {
773
+ quote = undefined;
774
+ end = index;
459
775
  continue;
460
776
  }
461
- if (char === "`" && quote !== "double") {
462
- const nested = bashSubstitution(input, index);
463
- if (!nested)
777
+ if (char === "\\" && quote !== "'") {
778
+ const next = input[index + 1];
779
+ if (next === undefined)
464
780
  return;
465
- index = nested.end;
466
- continue;
467
- }
468
- if (quote === "double") {
469
- if (char === "$" && input[index + 1] === "(") {
470
- level++;
781
+ if (next === `
782
+ `) {
471
783
  index++;
472
- } else if (char === ")" && level > 1)
473
- level--;
784
+ continue;
785
+ }
786
+ if (!quote || '$`"\\'.includes(next)) {
787
+ quoted = true;
788
+ started = true;
789
+ delimiter += input[++index];
790
+ end = index;
791
+ continue;
792
+ }
793
+ }
794
+ if (!quote && (char === "'" || char === '"')) {
795
+ quote = char;
796
+ quoted = true;
797
+ started = true;
798
+ end = index;
474
799
  continue;
475
800
  }
476
- if (char === "(")
477
- level++;
478
- if (char !== ")" || --level)
801
+ delimiter += char;
802
+ started = true;
803
+ end = index;
804
+ }
805
+ if (started && !quote)
806
+ return { delimiter, quoted, tabs, end };
807
+ }
808
+ function bashHeredoc(input, start, delimiter) {
809
+ const bodyStart = start;
810
+ let lineStart = start;
811
+ let line = "";
812
+ for (let index = start;index <= input.length; index++) {
813
+ if (index < input.length && input[index] !== `
814
+ `)
479
815
  continue;
480
- return { source: input.slice(start + 2, index), end: index };
816
+ const text = input.slice(start, index);
817
+ line += delimiter.tabs ? text.replace(/^\t+/, "") : text;
818
+ if (!delimiter.quoted && /(?<!\\)(?:\\\\)*\\$/.test(line) && index < input.length) {
819
+ line = line.slice(0, -1);
820
+ start = index + 1;
821
+ continue;
822
+ }
823
+ if (line === delimiter.delimiter)
824
+ return { source: input.slice(bodyStart, lineStart), end: index };
825
+ line = "";
826
+ start = index + 1;
827
+ lineStart = start;
481
828
  }
482
829
  }
483
830
  function scanPowerShell(input) {
484
- return scanPowerShellNested(input, 0);
831
+ return scanPowerShellNested(input, 0, { remaining: MAX_INPUT_LENGTH * MAX_SUBSTITUTION_DEPTH });
485
832
  }
486
- function scanPowerShellNested(input, depth) {
487
- if (input.length > MAX_BASH_INPUT_LENGTH || depth >= MAX_SUBSTITUTION_DEPTH)
833
+ function scanPowerShellNested(input, depth, budget, hash = false) {
834
+ budget.remaining -= input.length;
835
+ if (input.length > MAX_INPUT_LENGTH || depth >= MAX_SUBSTITUTION_DEPTH || budget.remaining < 0)
836
+ return { kind: "opaque", reason: "invalid-structure" };
837
+ if (/[\0\u0085\u2013-\u2015\u2018-\u201e\ufeff]/.test(input))
488
838
  return { kind: "opaque", reason: "invalid-structure" };
489
839
  const commands = [];
490
840
  const nestedCommands = [];
491
841
  const words = [];
842
+ const rawWords = [];
843
+ const wordEnds = [];
492
844
  let segment = 0;
493
845
  let word = "";
494
846
  let started = false;
847
+ let wordStart = 0;
495
848
  let quote;
496
- let dynamic = false;
849
+ let standalone = false;
850
+ let expression = hash;
851
+ let compound = false;
852
+ let stopParsing = false;
853
+ let commandEnd = 0;
854
+ let statementHead = true;
497
855
  let invalid = false;
498
856
  let redirectTarget = false;
499
857
  let comment = false;
500
- let separated = false;
501
858
  let dangling = false;
502
- const finishWord = () => {
859
+ let invocation = false;
860
+ const finishWord = (end) => {
503
861
  if (!started)
504
862
  return;
505
- if (!redirectTarget)
863
+ if (word === "--%" && words.length > 0 && !expression && !/['"]/.test(input[wordStart]))
864
+ stopParsing = true;
865
+ if (!redirectTarget) {
866
+ if (!words.length && !invocation && !expression)
867
+ segment = wordStart;
506
868
  words.push(word);
869
+ rawWords.push(input.slice(wordStart, end));
870
+ wordEnds.push(end);
871
+ dangling = false;
872
+ }
873
+ commandEnd = end;
507
874
  redirectTarget = false;
508
875
  word = "";
509
876
  started = false;
510
877
  };
511
- const finishCommand = (end, boundary = false) => {
512
- finishWord();
513
- const resource = input.slice(segment, end).trim();
514
- if (resource)
515
- commands.push({ resource, words: [...words] });
516
- else if (boundary && separated)
878
+ const finishCommand = (end, required = false) => {
879
+ finishWord(end);
880
+ const start = segment + input.slice(segment, commandEnd).search(/\S|$/);
881
+ const resource = input.slice(start, commandEnd).trimEnd();
882
+ if (words.length && !expression)
883
+ commands.push({
884
+ resource,
885
+ words: [...words],
886
+ rawWords: [...rawWords],
887
+ wordEnds: wordEnds.map((end2) => end2 - start),
888
+ ...statementHead && !invocation ? { statementHead: true } : {}
889
+ });
890
+ else if (!expression && invocation || required && !words.length && !nestedCommands.length)
891
+ invalid = true;
892
+ if (redirectTarget)
517
893
  invalid = true;
518
894
  commands.push(...nestedCommands.splice(0));
519
895
  words.length = 0;
520
- separated ||= Boolean(resource);
896
+ rawWords.length = 0;
897
+ wordEnds.length = 0;
898
+ redirectTarget = false;
899
+ invocation = false;
900
+ expression = hash;
901
+ compound = false;
902
+ stopParsing = false;
521
903
  };
522
904
  for (let index = 0;index < input.length; index++) {
523
905
  const char = input[index];
524
- if (quote) {
906
+ if (!started)
907
+ wordStart = index;
908
+ if (stopParsing) {
909
+ const stop = powerShellStopParsing(input, index);
910
+ const text = input.slice(index, stop).trim();
911
+ if (text) {
912
+ wordStart = index + input.slice(index, stop).search(/\S/);
913
+ word = text;
914
+ started = true;
915
+ finishWord(wordStart + text.length);
916
+ }
917
+ stopParsing = false;
918
+ index = stop - 1;
919
+ continue;
920
+ }
921
+ if (quote === "single") {
525
922
  started = true;
526
- if (quote === "single" && char === "'" && input[index + 1] === "'") {
923
+ if (char === "'" && input[index + 1] === "'") {
527
924
  word += "'";
528
925
  index++;
529
- } else if (quote === "single" && char === "'" || quote === "double" && char === '"')
926
+ } else if (char === "'") {
530
927
  quote = undefined;
531
- else if (char === "`" && index + 1 < input.length)
532
- word += input[++index];
533
- else {
534
- if (quote === "double" && char === "$" && input[index + 1] === "(")
535
- dynamic = true;
928
+ if (standalone)
929
+ finishWord(index + 1);
930
+ } else
931
+ word += char;
932
+ continue;
933
+ }
934
+ if (quote === "double") {
935
+ if (char === '"' && input[index + 1] === '"') {
936
+ word += '"';
937
+ index++;
938
+ } else if (char === '"') {
939
+ quote = undefined;
940
+ if (standalone)
941
+ finishWord(index + 1);
942
+ } else if (char === "`") {
943
+ const escape = powerShellEscape(input, index);
944
+ if (!escape)
945
+ return { kind: "opaque", reason: "unterminated-escape" };
946
+ word += escape.value;
947
+ index = escape.end;
948
+ } else if (char === "$" && input[index + 1] === "(") {
949
+ const block = powerShellBlock(input, index + 1, depth);
950
+ if (!block)
951
+ return { kind: "opaque", reason: "invalid-structure" };
952
+ const result = scanPowerShellNested(block.source, depth + 1, budget);
953
+ if (result.kind === "opaque")
954
+ return result;
955
+ nestedCommands.push(...result.commands);
956
+ word += input.slice(index, block.end + 1);
957
+ index = block.end;
958
+ } else
536
959
  word += char;
537
- }
538
960
  continue;
539
961
  }
540
962
  if (char === "'" || char === '"') {
963
+ if (!started && words.length === 0 && !invocation)
964
+ expression = true;
541
965
  quote = char === "'" ? "single" : "double";
966
+ standalone = !started;
542
967
  started = true;
543
968
  continue;
544
969
  }
545
- if (char === "`" && index + 1 < input.length) {
546
- if (input[index + 1] === "\r" || input[index + 1] === `
547
- `)
548
- return { kind: "opaque", reason: "invalid-structure" };
549
- if (";&|".includes(input[index + 1]))
550
- return { kind: "opaque", reason: "invalid-structure" };
551
- if (words.length === 0)
552
- dynamic = true;
970
+ if (char === "`") {
971
+ const escape = powerShellEscape(input, index);
972
+ if (!escape)
973
+ return { kind: "opaque", reason: "unterminated-escape" };
974
+ if (started || /\S/.test(escape.value)) {
975
+ started = true;
976
+ word += escape.value;
977
+ }
978
+ index = escape.end;
979
+ continue;
980
+ }
981
+ if (!started && words.length > 0 && !expression && /^--%(?=$|[\s;|&(){}])/.test(input.slice(index))) {
982
+ word = "--%";
553
983
  started = true;
554
- word += input[++index];
984
+ finishWord(index + 3);
985
+ stopParsing = true;
986
+ index += 2;
555
987
  continue;
556
988
  }
557
- if (char === "`")
558
- return { kind: "opaque", reason: "unterminated-escape" };
559
- if (char === "<" && input[index + 1] === "#")
560
- return { kind: "opaque", reason: "dynamic-execution" };
561
- if (char === "#" && !started) {
562
- if (/^#requires\b/i.test(input.slice(index)))
563
- return { kind: "opaque", reason: "dynamic-execution" };
564
- finishCommand(index);
989
+ if (char === "<" && input[index + 1] === "#" && !started) {
990
+ const end = powerShellComment(input, index);
991
+ if (end === undefined)
992
+ return { kind: "opaque", reason: "invalid-structure" };
993
+ if (!words.length && !invocation)
994
+ segment = end + 1;
995
+ index = end;
996
+ continue;
997
+ }
998
+ if (char === "#" && (!started || expression)) {
999
+ if (words.length || started || invocation)
1000
+ finishCommand(index);
1001
+ statementHead = !dangling;
565
1002
  comment = true;
566
1003
  const endings = [input.indexOf(`
567
1004
  `, index), input.indexOf("\r", index)].filter((ending) => ending >= 0);
@@ -571,40 +1008,130 @@ function scanPowerShellNested(input, depth) {
571
1008
  comment = false;
572
1009
  index = input[newline] === "\r" && input[newline + 1] === `
573
1010
  ` ? newline + 1 : newline;
574
- segment = newline + 1;
1011
+ segment = index + 1;
575
1012
  continue;
576
1013
  }
577
- const redirect = char === ">" || !started && (char === "*" || /\d/.test(char)) ? powerShellRedirect(input, index) : undefined;
1014
+ const redirect = !started && (char === ">" || char === "*" || /\d/.test(char)) ? powerShellRedirect(input, index) : undefined;
1015
+ if (redirect === false)
1016
+ return { kind: "opaque", reason: "invalid-redirect" };
578
1017
  if (redirect) {
579
- finishWord();
1018
+ if (redirectTarget)
1019
+ return { kind: "opaque", reason: "invalid-redirect" };
1020
+ if (words.length === 0)
1021
+ return { kind: "opaque", reason: "invalid-redirect" };
580
1022
  redirectTarget = !redirect.includes("&");
581
1023
  index += redirect.length - 1;
1024
+ commandEnd = index + 1;
1025
+ continue;
1026
+ }
1027
+ if (!started && !words.length && !invocation && !expression && /[A-Za-z]/.test(char)) {
1028
+ const keyword = /^[A-Za-z]+(?=$|[\s({])/.exec(input.slice(index))?.[0]?.toLowerCase();
1029
+ if (keyword && /^(?:if|elseif|else|for|while|do|until|switch|function|filter|try|catch|finally|begin|process|end|clean|param|trap|class|enum|data|dynamicparam|using)$/.test(keyword)) {
1030
+ expression = true;
1031
+ compound = true;
1032
+ index += keyword.length - 1;
1033
+ continue;
1034
+ }
1035
+ if (keyword === "foreach" && /^foreach\s*\(/i.test(input.slice(index))) {
1036
+ expression = true;
1037
+ compound = true;
1038
+ index += keyword.length - 1;
1039
+ continue;
1040
+ }
1041
+ if (keyword && /^(?:return|throw|exit|break|continue)$/.test(keyword)) {
1042
+ index += keyword.length - 1;
1043
+ segment = index + 1;
1044
+ continue;
1045
+ }
1046
+ }
1047
+ if (expression && !compound && (char === "=" || /[-+*/%]/.test(char) && input[index + 1] === "=")) {
1048
+ finishWord(index);
1049
+ words.length = 0;
1050
+ rawWords.length = 0;
1051
+ wordEnds.length = 0;
1052
+ expression = false;
1053
+ if (char !== "=")
1054
+ index++;
1055
+ segment = index + 1;
1056
+ continue;
1057
+ }
1058
+ if (expression && !started && /^in\b/i.test(input.slice(index))) {
1059
+ words.length = 0;
1060
+ rawWords.length = 0;
1061
+ wordEnds.length = 0;
1062
+ expression = false;
1063
+ index++;
1064
+ segment = index + 1;
582
1065
  continue;
583
1066
  }
584
- if (char === "{" && !started) {
585
- const block = powerShellBlock(input, index);
1067
+ if (char === "@" && /['"]/.test(input[index + 1] ?? "")) {
1068
+ const literal = powerShellHereString(input, index);
1069
+ if (!literal)
1070
+ return { kind: "opaque", reason: "unterminated-quote" };
1071
+ if (!words.length && !invocation)
1072
+ expression = true;
1073
+ if (input[index + 1] === '"') {
1074
+ const result = powerShellExpansions(literal.source, depth + 1, budget);
1075
+ if (result.kind === "opaque")
1076
+ return result;
1077
+ nestedCommands.push(...result.commands);
1078
+ }
1079
+ word = literal.source;
1080
+ started = true;
1081
+ index = literal.end;
1082
+ finishWord(index + 1);
1083
+ continue;
1084
+ }
1085
+ if (char === "$" && input[index + 1] === "{") {
1086
+ const end = input.indexOf("}", index + 2);
1087
+ if (end < 0)
1088
+ return { kind: "opaque", reason: "invalid-structure" };
1089
+ if (!started && !words.length && !invocation)
1090
+ expression = true;
1091
+ word += input.slice(index, end + 1);
1092
+ started = true;
1093
+ index = end;
1094
+ continue;
1095
+ }
1096
+ const opener = (char === "$" || char === "@") && input[index + 1] === "(" ? index + 1 : char === "@" && input[index + 1] === "{" ? index + 1 : char === "(" || char === "{" || char === "[" && (expression || !started) ? index : undefined;
1097
+ if (opener !== undefined) {
1098
+ if (started && (char === "{" || char === "(")) {
1099
+ finishWord(index);
1100
+ wordStart = index;
1101
+ }
1102
+ if (!started && !words.length && !invocation)
1103
+ expression = true;
1104
+ const block = powerShellBlock(input, opener, depth);
586
1105
  if (!block)
587
1106
  return { kind: "opaque", reason: "invalid-structure" };
588
- const result = scanPowerShellNested(block.source, depth + 1);
1107
+ const result = scanPowerShellNested(block.source, depth + 1, budget, input[opener] === "[" || char === "@" && input[opener] === "{");
589
1108
  if (result.kind === "opaque")
590
1109
  return result;
591
- nestedCommands.push(...result.commands.map(markNested));
1110
+ nestedCommands.push(...result.commands);
592
1111
  started = true;
593
1112
  word += input.slice(index, block.end + 1);
594
1113
  index = block.end;
1114
+ if (input[opener] === "{" || char === "(")
1115
+ finishWord(index + 1);
1116
+ if (compound && input[opener] === "{") {
1117
+ finishCommand(index + 1);
1118
+ segment = index + 1;
1119
+ }
595
1120
  continue;
596
1121
  }
597
- if (char === "}")
1122
+ if (char === "}" || char === ")")
598
1123
  return { kind: "opaque", reason: "invalid-structure" };
599
- if (char === "&" && !started && words.length === 0)
600
- continue;
601
- if (char === "." && !started && words.length === 0 && (/\s/.test(input[index + 1] ?? "") || !input[index + 1]))
1124
+ if (!started && words.length === 0 && (char === "&" && input[index + 1] !== "&" || char === "." && (/\s/.test(input[index + 1] ?? "") || !input[index + 1]))) {
1125
+ if (invocation)
1126
+ return { kind: "opaque", reason: "invalid-structure" };
1127
+ invocation = true;
602
1128
  continue;
603
- if ("@()".includes(char))
604
- dynamic = true;
1129
+ }
1130
+ if (!started && !words.length && !invocation && powerShellExpression(input.slice(index)))
1131
+ expression = true;
605
1132
  if (/\s/.test(char) && char !== `
606
1133
  ` && char !== "\r") {
607
- finishWord();
1134
+ finishWord(index);
608
1135
  continue;
609
1136
  }
610
1137
  const next = input[index + 1];
@@ -612,14 +1139,22 @@ function scanPowerShellNested(input, depth) {
612
1139
  ` ? char + next : char === "&" && next === "&" || char === "|" && next === "|" ? char + next : char === ";" || char === "|" || char === "&" || char === `
613
1140
  ` || char === "\r" ? char : undefined;
614
1141
  if (separator) {
615
- finishCommand(index, true);
616
- if (redirectTarget)
617
- invalid = true;
1142
+ if ((separator === `
1143
+ ` || separator === "\r" || separator === `\r
1144
+ `) && !started && !words.length && !invocation) {
1145
+ index += separator.length - 1;
1146
+ segment = index + 1;
1147
+ continue;
1148
+ }
1149
+ finishCommand(index, dangling || ![";", `
1150
+ `, "\r", `\r
1151
+ `].includes(separator));
618
1152
  dangling = ![";", "&", `
619
1153
  `, "\r", `\r
620
1154
  `].includes(separator);
1155
+ statementHead = !dangling;
621
1156
  index += separator.length - 1;
622
- segment = separator === "&" ? index : index + 1;
1157
+ segment = index + 1;
623
1158
  continue;
624
1159
  }
625
1160
  started = true;
@@ -632,76 +1167,263 @@ function scanPowerShellNested(input, depth) {
632
1167
  finishCommand(input.length);
633
1168
  if (redirectTarget || invalid || dangling)
634
1169
  return { kind: "opaque", reason: "invalid-structure" };
635
- const reason = dynamic ? "dynamic-execution" : commands.reduce((result, command) => result ?? powerShellOpaqueReason(command), undefined);
636
- if (reason)
637
- return { kind: "opaque", reason };
1170
+ if (commands.some((command) => !command.words[0]))
1171
+ return { kind: "opaque", reason: "dynamic-command-name" };
638
1172
  return { kind: "scanned", commands };
639
1173
  }
640
- function powerShellBlock(input, start) {
1174
+ function powerShellBlock(input, start, depth) {
1175
+ if (depth >= MAX_SUBSTITUTION_DEPTH)
1176
+ return;
641
1177
  let quote;
642
- let level = 1;
1178
+ let standalone = false;
1179
+ let started = false;
1180
+ let head = true;
1181
+ let expression = false;
1182
+ let token = "";
1183
+ const close = input[start] === "(" ? ")" : input[start] === "[" ? "]" : "}";
643
1184
  for (let index = start + 1;index < input.length; index++) {
644
1185
  const char = input[index];
645
1186
  if (quote === "single") {
646
- if (char === "'" && input[index + 1] === "'")
1187
+ if (char === "'" && input[index + 1] === "'") {
1188
+ token += "'";
1189
+ index++;
1190
+ } else if (char === "'") {
1191
+ quote = undefined;
1192
+ started = !standalone;
1193
+ if (standalone)
1194
+ token = "";
1195
+ } else
1196
+ token += char;
1197
+ continue;
1198
+ }
1199
+ if (quote === "double") {
1200
+ if (char === "`") {
1201
+ const escape = powerShellEscape(input, index);
1202
+ if (!escape)
1203
+ return;
1204
+ token += escape.value;
1205
+ index = escape.end;
1206
+ } else if (char === '"' && input[index + 1] === '"') {
1207
+ token += '"';
647
1208
  index++;
648
- else if (char === "'")
1209
+ } else if (char === '"') {
649
1210
  quote = undefined;
1211
+ started = !standalone;
1212
+ if (standalone)
1213
+ token = "";
1214
+ } else if (char === "$" && input[index + 1] === "(") {
1215
+ const nested = powerShellBlock(input, index + 1, depth + 1);
1216
+ if (!nested)
1217
+ return;
1218
+ index = nested.end;
1219
+ } else
1220
+ token += char;
650
1221
  continue;
651
1222
  }
652
1223
  if (char === "`") {
653
- index++;
1224
+ const escape = powerShellEscape(input, index);
1225
+ if (!escape)
1226
+ return;
1227
+ if (started || /\S/.test(escape.value)) {
1228
+ started = true;
1229
+ token += escape.value;
1230
+ }
1231
+ index = escape.end;
654
1232
  continue;
655
1233
  }
656
- if (char === "#" && quote !== "double") {
657
- const newline = input.indexOf(`
658
- `, index);
1234
+ if (char === "<" && input[index + 1] === "#" && !started) {
1235
+ const end = powerShellComment(input, index);
1236
+ if (end === undefined)
1237
+ return;
1238
+ index = end;
1239
+ continue;
1240
+ }
1241
+ if (char === "#" && (!started || expression)) {
1242
+ const endings = [input.indexOf(`
1243
+ `, index), input.indexOf("\r", index)].filter((ending) => ending >= 0);
1244
+ const newline = endings.length > 0 ? Math.min(...endings) : -1;
659
1245
  if (newline < 0)
660
1246
  return;
661
1247
  index = newline;
1248
+ started = false;
1249
+ head = true;
1250
+ expression = false;
1251
+ token = "";
1252
+ continue;
1253
+ }
1254
+ if (char === "@" && /['"]/.test(input[index + 1] ?? "")) {
1255
+ const literal = powerShellHereString(input, index);
1256
+ if (!literal)
1257
+ return;
1258
+ index = literal.end;
1259
+ started = false;
1260
+ head = false;
1261
+ continue;
1262
+ }
1263
+ if (head && !started && (char === "&" && input[index + 1] !== "&" || char === "." && /\s/.test(input[index + 1] ?? ""))) {
1264
+ head = false;
662
1265
  continue;
663
1266
  }
664
- if (char === "<" && input[index + 1] === "#" && quote !== "double") {
665
- const end = input.indexOf("#>", index + 2);
1267
+ if (expression && (char === "=" || !started && /^in\b/i.test(input.slice(index)))) {
1268
+ if (char !== "=")
1269
+ index++;
1270
+ expression = false;
1271
+ head = true;
1272
+ started = false;
1273
+ token = "";
1274
+ continue;
1275
+ }
1276
+ if (char === "'" || char === '"') {
1277
+ quote = char === "'" ? "single" : "double";
1278
+ standalone = !started;
1279
+ if (head && !started)
1280
+ expression = true;
1281
+ started = true;
1282
+ continue;
1283
+ }
1284
+ const redirect = !started && (char === ">" || char === "*" || /\d/.test(char)) ? powerShellRedirect(input, index) : undefined;
1285
+ if (redirect === false)
1286
+ return;
1287
+ if (redirect) {
1288
+ index += redirect.length - 1;
1289
+ token = "";
1290
+ continue;
1291
+ }
1292
+ if (char === "$" && input[index + 1] === "{") {
1293
+ const end = input.indexOf("}", index + 2);
666
1294
  if (end < 0)
667
1295
  return;
668
- index = end + 1;
1296
+ if (head && !started)
1297
+ expression = true;
1298
+ index = end;
1299
+ started = true;
669
1300
  continue;
670
1301
  }
671
- if (char === "'") {
672
- quote = "single";
1302
+ if (!started && !head && !expression && /^--%(?=$|[\s;|&(){}])/.test(input.slice(index))) {
1303
+ index = powerShellStopParsing(input, index + 3) - 1;
673
1304
  continue;
674
1305
  }
675
- if (char === '"') {
676
- quote = quote === "double" ? undefined : "double";
1306
+ if (char === close)
1307
+ return { source: input.slice(start + 1, index), end: index };
1308
+ if (char === "(" || char === "{" || char === "[" && (!started || expression)) {
1309
+ if (head && !started)
1310
+ expression = true;
1311
+ const nested = powerShellBlock(input, index, depth + 1);
1312
+ if (!nested)
1313
+ return;
1314
+ index = nested.end;
1315
+ started = false;
1316
+ head = false;
1317
+ token = "";
677
1318
  continue;
678
1319
  }
679
- if (char === "{" && quote !== "double")
680
- level++;
681
- if (char !== "}" || quote === "double" || --level)
1320
+ if (/[\s;&|]/.test(char)) {
1321
+ if (token === "--%" && !expression) {
1322
+ index = powerShellStopParsing(input, index) - 1;
1323
+ token = "";
1324
+ continue;
1325
+ }
1326
+ if (/[;&|\r\n]/.test(char)) {
1327
+ head = true;
1328
+ expression = false;
1329
+ } else if (started)
1330
+ head = false;
1331
+ started = false;
1332
+ token = "";
682
1333
  continue;
683
- return { source: input.slice(start + 1, index), end: index };
1334
+ }
1335
+ if (head && !started && powerShellExpression(input.slice(index)))
1336
+ expression = true;
1337
+ started = true;
1338
+ token += char;
684
1339
  }
685
1340
  }
686
- function shellCommandName(word) {
687
- const value = (word ?? "").toLowerCase();
688
- return value.slice(Math.max(value.lastIndexOf("/"), value.lastIndexOf("\\")) + 1);
1341
+ var POWERSHELL_ESCAPES = {
1342
+ "0": "\x00",
1343
+ a: "\x07",
1344
+ b: "\b",
1345
+ e: "\x1B",
1346
+ f: "\f",
1347
+ n: `
1348
+ `,
1349
+ r: "\r",
1350
+ t: "\t",
1351
+ v: "\v"
1352
+ };
1353
+ function powerShellEscape(input, start) {
1354
+ const char = input[start + 1];
1355
+ if (char === undefined)
1356
+ return;
1357
+ if (char === "\r" || char === `
1358
+ `)
1359
+ return {
1360
+ value: char === "\r" && input[start + 2] === `
1361
+ ` ? `\r
1362
+ ` : char,
1363
+ end: start + (char === "\r" && input[start + 2] === `
1364
+ ` ? 2 : 1)
1365
+ };
1366
+ if (char === "u" && input[start + 2] === "{") {
1367
+ const code = /^u\{([0-9a-f]{1,6})\}/i.exec(input.slice(start + 1));
1368
+ if (!code || Number.parseInt(code[1], 16) > 1114111)
1369
+ return;
1370
+ return { value: String.fromCodePoint(Number.parseInt(code[1], 16)), end: start + code[0].length };
1371
+ }
1372
+ return { value: POWERSHELL_ESCAPES[char] ?? char, end: start + 1 };
1373
+ }
1374
+ function powerShellExpression(input) {
1375
+ return /^(?:[$!,+]|[+-]?\d+(?:\.\d*)?(?:[eE][+-]?\d+)?(?:[dDlLnNuU]|[kKmMgGtTpP][bB])?(?![\w'"`])|0[xX][\da-fA-F]+\b|0[bB][01]+\b|\.[0-9]|-(?:not|bnot|join|split)\b)/i.test(input);
1376
+ }
1377
+ function powerShellStopParsing(input, start) {
1378
+ let quoted = false;
1379
+ for (let index = start;index < input.length; index++) {
1380
+ if (input[index] === '"')
1381
+ quoted = !quoted;
1382
+ if (input[index] === "\r" || input[index] === `
1383
+ ` || input[index] === "|" && !quoted)
1384
+ return index;
1385
+ }
1386
+ return input.length;
689
1387
  }
690
- function powerShellOpaqueReason(command) {
691
- const head = command.words[0] ?? "";
692
- if (head.includes("\\") && !/^[A-Za-z]:\\/.test(head) && !/^[A-Za-z_][A-Za-z0-9_.-]*\\[A-Za-z_][A-Za-z0-9_.-]*$/.test(head) || head.includes("$") || head.includes("@"))
693
- return "dynamic-execution";
694
- const name = shellCommandName(head);
695
- if (["return", "throw", "exit", "break", "continue"].includes(name) && command.words.length > 1)
696
- return "dynamic-execution";
697
- if (!POWERSHELL_LOCATIONS.has(name))
1388
+ function powerShellComment(input, start) {
1389
+ const end = input.indexOf("#>", start + 2);
1390
+ return end < 0 ? undefined : end + 1;
1391
+ }
1392
+ function powerShellHereString(input, start) {
1393
+ const header = /^@['"][ \t]*(?:\r\n|\r|\n)/.exec(input.slice(start));
1394
+ if (!header)
698
1395
  return;
699
- if (command.words.some((word, index) => index > 0 && (word.includes("(") || word.includes("$") && !knownPowerShellDirectory(word) || /^[A-Za-z]+:/.test(word) && !/^[A-Za-z]:[\\/]/.test(word))))
700
- return "dynamic-directory";
1396
+ const body = start + header[0].length;
1397
+ for (let index = body;index < input.length; index++) {
1398
+ if (index !== body && input[index - 1] !== "\r" && input[index - 1] !== `
1399
+ `)
1400
+ continue;
1401
+ if (input[index] !== input[start + 1] || input[index + 1] !== "@")
1402
+ continue;
1403
+ const end = index > body && input[index - 1] === `
1404
+ ` && input[index - 2] === "\r" ? index - 2 : index > body ? index - 1 : index;
1405
+ return { source: input.slice(body, end), end: index + 1 };
1406
+ }
701
1407
  }
702
- function knownPowerShellDirectory(word) {
703
- const variable = /^(?:\$(?:PWD|HOME|PSHOME)|\$env:[A-Za-z_][A-Za-z0-9_]*|\$\{env:[^}]+\})(?:[\\/]|$)/i.exec(word);
704
- return Boolean(variable) && !word.slice(variable?.[0].length).includes("$");
1408
+ function powerShellExpansions(input, depth, budget) {
1409
+ const commands = [];
1410
+ for (let index = 0;index < input.length; index++) {
1411
+ if (input[index] === "`") {
1412
+ index++;
1413
+ continue;
1414
+ }
1415
+ if (!input.startsWith("$(", index))
1416
+ continue;
1417
+ const block = powerShellBlock(input, index + 1, depth);
1418
+ if (!block)
1419
+ return { kind: "opaque", reason: "invalid-structure" };
1420
+ const result = scanPowerShellNested(block.source, depth + 1, budget);
1421
+ if (result.kind === "opaque")
1422
+ return result;
1423
+ commands.push(...result.commands);
1424
+ index = block.end;
1425
+ }
1426
+ return { kind: "scanned", commands };
705
1427
  }
706
1428
  function powerShellRedirect(input, index) {
707
1429
  let cursor = index;
@@ -720,14 +1442,11 @@ function powerShellRedirect(input, index) {
720
1442
  while (/\d/.test(input[cursor] ?? ""))
721
1443
  cursor++;
722
1444
  }
723
- return input.slice(index, cursor);
724
- }
725
- function markNested(command) {
726
- return Object.defineProperty({ ...command }, Nested, { value: true });
1445
+ const redirect = input.slice(index, cursor);
1446
+ return /^(?:(?:[1-6]|\*)?>>?|[2-6*]>&1)$/.test(redirect) ? redirect : false;
727
1447
  }
728
1448
  export {
729
1449
  scanPowerShell,
730
1450
  scan,
731
- exports_scan as ShellScan,
732
- Nested
1451
+ exports_scan as ShellScan
733
1452
  };