code-squad-cli 1.2.7 → 1.2.10

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 (316) hide show
  1. package/dist/flip/constants/filters.d.ts +2 -0
  2. package/dist/flip/constants/filters.js +30 -0
  3. package/dist/flip/events/SSEManager.d.ts +10 -0
  4. package/dist/flip/events/SSEManager.js +28 -0
  5. package/dist/flip/events/types.d.ts +11 -0
  6. package/dist/flip/events/types.js +1 -0
  7. package/dist/flip/index.js +2 -2
  8. package/dist/flip/output/autopaste.js +15 -3
  9. package/dist/flip/output/clipboard.js +56 -2
  10. package/dist/flip/routes/events.d.ts +3 -0
  11. package/dist/flip/routes/events.js +25 -0
  12. package/dist/flip/routes/files.d.ts +6 -1
  13. package/dist/flip/routes/files.js +21 -33
  14. package/dist/flip/routes/static.js +8 -2
  15. package/dist/flip/routes/submit.js +14 -7
  16. package/dist/flip/server/Server.d.ts +1 -1
  17. package/dist/flip/server/Server.js +24 -2
  18. package/dist/flip/watcher/FileWatcher.d.ts +29 -0
  19. package/dist/flip/watcher/FileWatcher.js +128 -0
  20. package/dist/flip-ui/dist/assets/index-B2PjDe6F.js +217 -0
  21. package/dist/flip-ui/dist/assets/index-DYY1gRRa.css +1 -0
  22. package/dist/flip-ui/dist/index.html +2 -2
  23. package/dist/index.js +345 -80
  24. package/package.json +3 -2
  25. package/dist/flip-ui/dist/assets/abap-BdImnpbu.js +0 -1
  26. package/dist/flip-ui/dist/assets/actionscript-3-CfeIJUat.js +0 -1
  27. package/dist/flip-ui/dist/assets/ada-bCR0ucgS.js +0 -1
  28. package/dist/flip-ui/dist/assets/andromeeda-C-Jbm3Hp.js +0 -1
  29. package/dist/flip-ui/dist/assets/angular-html-CU67Zn6k.js +0 -1
  30. package/dist/flip-ui/dist/assets/angular-ts-BwZT4LLn.js +0 -1
  31. package/dist/flip-ui/dist/assets/apache-Pmp26Uib.js +0 -1
  32. package/dist/flip-ui/dist/assets/apex-D8_7TLub.js +0 -1
  33. package/dist/flip-ui/dist/assets/apl-dKokRX4l.js +0 -1
  34. package/dist/flip-ui/dist/assets/applescript-Co6uUVPk.js +0 -1
  35. package/dist/flip-ui/dist/assets/ara-BRHolxvo.js +0 -1
  36. package/dist/flip-ui/dist/assets/asciidoc-Dv7Oe6Be.js +0 -1
  37. package/dist/flip-ui/dist/assets/asm-D_Q5rh1f.js +0 -1
  38. package/dist/flip-ui/dist/assets/astro-CbQHKStN.js +0 -1
  39. package/dist/flip-ui/dist/assets/aurora-x-D-2ljcwZ.js +0 -1
  40. package/dist/flip-ui/dist/assets/awk-DMzUqQB5.js +0 -1
  41. package/dist/flip-ui/dist/assets/ayu-dark-CmMr59Fi.js +0 -1
  42. package/dist/flip-ui/dist/assets/ballerina-BFfxhgS-.js +0 -1
  43. package/dist/flip-ui/dist/assets/bat-BkioyH1T.js +0 -1
  44. package/dist/flip-ui/dist/assets/beancount-k_qm7-4y.js +0 -1
  45. package/dist/flip-ui/dist/assets/berry-uYugtg8r.js +0 -1
  46. package/dist/flip-ui/dist/assets/bibtex-CHM0blh-.js +0 -1
  47. package/dist/flip-ui/dist/assets/bicep-Bmn6On1c.js +0 -1
  48. package/dist/flip-ui/dist/assets/blade-D4QpJJKB.js +0 -1
  49. package/dist/flip-ui/dist/assets/bsl-BO_Y6i37.js +0 -1
  50. package/dist/flip-ui/dist/assets/c-BIGW1oBm.js +0 -1
  51. package/dist/flip-ui/dist/assets/c3-VCDPK7BO.js +0 -1
  52. package/dist/flip-ui/dist/assets/cadence-Bv_4Rxtq.js +0 -1
  53. package/dist/flip-ui/dist/assets/cairo-KRGpt6FW.js +0 -1
  54. package/dist/flip-ui/dist/assets/catppuccin-frappe-DFWUc33u.js +0 -1
  55. package/dist/flip-ui/dist/assets/catppuccin-latte-C9dUb6Cb.js +0 -1
  56. package/dist/flip-ui/dist/assets/catppuccin-macchiato-DQyhUUbL.js +0 -1
  57. package/dist/flip-ui/dist/assets/catppuccin-mocha-D87Tk5Gz.js +0 -1
  58. package/dist/flip-ui/dist/assets/clarity-D53aC0YG.js +0 -1
  59. package/dist/flip-ui/dist/assets/clojure-P80f7IUj.js +0 -1
  60. package/dist/flip-ui/dist/assets/cmake-D1j8_8rp.js +0 -1
  61. package/dist/flip-ui/dist/assets/cobol-nwyudZeR.js +0 -1
  62. package/dist/flip-ui/dist/assets/codeowners-Bp6g37R7.js +0 -1
  63. package/dist/flip-ui/dist/assets/codeql-DsOJ9woJ.js +0 -1
  64. package/dist/flip-ui/dist/assets/coffee-Ch7k5sss.js +0 -1
  65. package/dist/flip-ui/dist/assets/common-lisp-Cg-RD9OK.js +0 -1
  66. package/dist/flip-ui/dist/assets/coq-DkFqJrB1.js +0 -1
  67. package/dist/flip-ui/dist/assets/cpp-CofmeUqb.js +0 -1
  68. package/dist/flip-ui/dist/assets/crystal-tKQVLTB8.js +0 -1
  69. package/dist/flip-ui/dist/assets/csharp-K5feNrxe.js +0 -1
  70. package/dist/flip-ui/dist/assets/css-DPfMkruS.js +0 -1
  71. package/dist/flip-ui/dist/assets/csv-fuZLfV_i.js +0 -1
  72. package/dist/flip-ui/dist/assets/cue-D82EKSYY.js +0 -1
  73. package/dist/flip-ui/dist/assets/cypher-COkxafJQ.js +0 -1
  74. package/dist/flip-ui/dist/assets/d-85-TOEBH.js +0 -1
  75. package/dist/flip-ui/dist/assets/dark-plus-C3mMm8J8.js +0 -1
  76. package/dist/flip-ui/dist/assets/dart-CF10PKvl.js +0 -1
  77. package/dist/flip-ui/dist/assets/dax-CEL-wOlO.js +0 -1
  78. package/dist/flip-ui/dist/assets/desktop-BmXAJ9_W.js +0 -1
  79. package/dist/flip-ui/dist/assets/diff-D97Zzqfu.js +0 -1
  80. package/dist/flip-ui/dist/assets/docker-BcOcwvcX.js +0 -1
  81. package/dist/flip-ui/dist/assets/dotenv-Da5cRb03.js +0 -1
  82. package/dist/flip-ui/dist/assets/dracula-BzJJZx-M.js +0 -1
  83. package/dist/flip-ui/dist/assets/dracula-soft-BXkSAIEj.js +0 -1
  84. package/dist/flip-ui/dist/assets/dream-maker-BtqSS_iP.js +0 -1
  85. package/dist/flip-ui/dist/assets/edge-BkV0erSs.js +0 -1
  86. package/dist/flip-ui/dist/assets/elixir-CDX3lj18.js +0 -1
  87. package/dist/flip-ui/dist/assets/elm-DbKCFpqz.js +0 -1
  88. package/dist/flip-ui/dist/assets/emacs-lisp-C9XAeP06.js +0 -1
  89. package/dist/flip-ui/dist/assets/erb-BOJIQeun.js +0 -1
  90. package/dist/flip-ui/dist/assets/erlang-DsQrWhSR.js +0 -1
  91. package/dist/flip-ui/dist/assets/everforest-dark-BgDCqdQA.js +0 -1
  92. package/dist/flip-ui/dist/assets/everforest-light-C8M2exoo.js +0 -1
  93. package/dist/flip-ui/dist/assets/fennel-BYunw83y.js +0 -1
  94. package/dist/flip-ui/dist/assets/fish-BvzEVeQv.js +0 -1
  95. package/dist/flip-ui/dist/assets/fluent-C4IJs8-o.js +0 -1
  96. package/dist/flip-ui/dist/assets/fortran-fixed-form-CkoXwp7k.js +0 -1
  97. package/dist/flip-ui/dist/assets/fortran-free-form-BxgE0vQu.js +0 -1
  98. package/dist/flip-ui/dist/assets/fsharp-CXgrBDvD.js +0 -1
  99. package/dist/flip-ui/dist/assets/gdresource-B7Tvp0Sc.js +0 -1
  100. package/dist/flip-ui/dist/assets/gdscript-DTMYz4Jt.js +0 -1
  101. package/dist/flip-ui/dist/assets/gdshader-DkwncUOv.js +0 -1
  102. package/dist/flip-ui/dist/assets/genie-D0YGMca9.js +0 -1
  103. package/dist/flip-ui/dist/assets/gherkin-DyxjwDmM.js +0 -1
  104. package/dist/flip-ui/dist/assets/git-commit-F4YmCXRG.js +0 -1
  105. package/dist/flip-ui/dist/assets/git-rebase-r7XF79zn.js +0 -1
  106. package/dist/flip-ui/dist/assets/github-dark-DHJKELXO.js +0 -1
  107. package/dist/flip-ui/dist/assets/github-dark-default-Cuk6v7N8.js +0 -1
  108. package/dist/flip-ui/dist/assets/github-dark-dimmed-DH5Ifo-i.js +0 -1
  109. package/dist/flip-ui/dist/assets/github-dark-high-contrast-E3gJ1_iC.js +0 -1
  110. package/dist/flip-ui/dist/assets/github-light-DAi9KRSo.js +0 -1
  111. package/dist/flip-ui/dist/assets/github-light-default-D7oLnXFd.js +0 -1
  112. package/dist/flip-ui/dist/assets/github-light-high-contrast-BfjtVDDH.js +0 -1
  113. package/dist/flip-ui/dist/assets/gleam-BspZqrRM.js +0 -1
  114. package/dist/flip-ui/dist/assets/glimmer-js-Rg0-pVw9.js +0 -1
  115. package/dist/flip-ui/dist/assets/glimmer-ts-U6CK756n.js +0 -1
  116. package/dist/flip-ui/dist/assets/glsl-DplSGwfg.js +0 -1
  117. package/dist/flip-ui/dist/assets/gn-n2N0HUVH.js +0 -1
  118. package/dist/flip-ui/dist/assets/gnuplot-DdkO51Og.js +0 -1
  119. package/dist/flip-ui/dist/assets/go-Dn2_MT6a.js +0 -1
  120. package/dist/flip-ui/dist/assets/graphql-ChdNCCLP.js +0 -1
  121. package/dist/flip-ui/dist/assets/groovy-gcz8RCvz.js +0 -1
  122. package/dist/flip-ui/dist/assets/gruvbox-dark-hard-CFHQjOhq.js +0 -1
  123. package/dist/flip-ui/dist/assets/gruvbox-dark-medium-GsRaNv29.js +0 -1
  124. package/dist/flip-ui/dist/assets/gruvbox-dark-soft-CVdnzihN.js +0 -1
  125. package/dist/flip-ui/dist/assets/gruvbox-light-hard-CH1njM8p.js +0 -1
  126. package/dist/flip-ui/dist/assets/gruvbox-light-medium-DRw_LuNl.js +0 -1
  127. package/dist/flip-ui/dist/assets/gruvbox-light-soft-hJgmCMqR.js +0 -1
  128. package/dist/flip-ui/dist/assets/hack-CaT9iCJl.js +0 -1
  129. package/dist/flip-ui/dist/assets/haml-B8DHNrY2.js +0 -1
  130. package/dist/flip-ui/dist/assets/handlebars-BL8al0AC.js +0 -1
  131. package/dist/flip-ui/dist/assets/haskell-Df6bDoY_.js +0 -1
  132. package/dist/flip-ui/dist/assets/haxe-CzTSHFRz.js +0 -1
  133. package/dist/flip-ui/dist/assets/hcl-BWvSN4gD.js +0 -1
  134. package/dist/flip-ui/dist/assets/hjson-D5-asLiD.js +0 -1
  135. package/dist/flip-ui/dist/assets/hlsl-D3lLCCz7.js +0 -1
  136. package/dist/flip-ui/dist/assets/houston-DnULxvSX.js +0 -1
  137. package/dist/flip-ui/dist/assets/html-GMplVEZG.js +0 -1
  138. package/dist/flip-ui/dist/assets/html-derivative-BFtXZ54Q.js +0 -1
  139. package/dist/flip-ui/dist/assets/http-jrhK8wxY.js +0 -1
  140. package/dist/flip-ui/dist/assets/hurl-irOxFIW8.js +0 -1
  141. package/dist/flip-ui/dist/assets/hxml-Bvhsp5Yf.js +0 -1
  142. package/dist/flip-ui/dist/assets/hy-DFXneXwc.js +0 -1
  143. package/dist/flip-ui/dist/assets/imba-DGztddWO.js +0 -1
  144. package/dist/flip-ui/dist/assets/index-BYcwO1DZ.js +0 -154
  145. package/dist/flip-ui/dist/assets/index-iFjjtGMT.css +0 -1
  146. package/dist/flip-ui/dist/assets/ini-BEwlwnbL.js +0 -1
  147. package/dist/flip-ui/dist/assets/java-CylS5w8V.js +0 -1
  148. package/dist/flip-ui/dist/assets/javascript-wDzz0qaB.js +0 -1
  149. package/dist/flip-ui/dist/assets/jinja-4LBKfQ-Z.js +0 -1
  150. package/dist/flip-ui/dist/assets/jison-wvAkD_A8.js +0 -1
  151. package/dist/flip-ui/dist/assets/json-Cp-IABpG.js +0 -1
  152. package/dist/flip-ui/dist/assets/json5-C9tS-k6U.js +0 -1
  153. package/dist/flip-ui/dist/assets/jsonc-Des-eS-w.js +0 -1
  154. package/dist/flip-ui/dist/assets/jsonl-DcaNXYhu.js +0 -1
  155. package/dist/flip-ui/dist/assets/jsonnet-DFQXde-d.js +0 -1
  156. package/dist/flip-ui/dist/assets/jssm-C2t-YnRu.js +0 -1
  157. package/dist/flip-ui/dist/assets/jsx-g9-lgVsj.js +0 -1
  158. package/dist/flip-ui/dist/assets/julia-CxzCAyBv.js +0 -1
  159. package/dist/flip-ui/dist/assets/kanagawa-dragon-CkXjmgJE.js +0 -1
  160. package/dist/flip-ui/dist/assets/kanagawa-lotus-CfQXZHmo.js +0 -1
  161. package/dist/flip-ui/dist/assets/kanagawa-wave-DWedfzmr.js +0 -1
  162. package/dist/flip-ui/dist/assets/kdl-DV7GczEv.js +0 -1
  163. package/dist/flip-ui/dist/assets/kotlin-BdnUsdx6.js +0 -1
  164. package/dist/flip-ui/dist/assets/kusto-DZf3V79B.js +0 -1
  165. package/dist/flip-ui/dist/assets/laserwave-DUszq2jm.js +0 -1
  166. package/dist/flip-ui/dist/assets/latex-B4uzh10-.js +0 -1
  167. package/dist/flip-ui/dist/assets/lean-BZvkOJ9d.js +0 -1
  168. package/dist/flip-ui/dist/assets/less-B1dDrJ26.js +0 -1
  169. package/dist/flip-ui/dist/assets/light-plus-B7mTdjB0.js +0 -1
  170. package/dist/flip-ui/dist/assets/liquid-DYVedYrR.js +0 -1
  171. package/dist/flip-ui/dist/assets/llvm-BtvRca6l.js +0 -1
  172. package/dist/flip-ui/dist/assets/log-2UxHyX5q.js +0 -1
  173. package/dist/flip-ui/dist/assets/logo-BtOb2qkB.js +0 -1
  174. package/dist/flip-ui/dist/assets/lua-BbnMAYS6.js +0 -1
  175. package/dist/flip-ui/dist/assets/luau-C-HG3fhB.js +0 -1
  176. package/dist/flip-ui/dist/assets/make-CHLpvVh8.js +0 -1
  177. package/dist/flip-ui/dist/assets/markdown-Cvjx9yec.js +0 -1
  178. package/dist/flip-ui/dist/assets/marko-DZsq8hO1.js +0 -1
  179. package/dist/flip-ui/dist/assets/material-theme-D5KoaKCx.js +0 -1
  180. package/dist/flip-ui/dist/assets/material-theme-darker-BfHTSMKl.js +0 -1
  181. package/dist/flip-ui/dist/assets/material-theme-lighter-B0m2ddpp.js +0 -1
  182. package/dist/flip-ui/dist/assets/material-theme-ocean-CyktbL80.js +0 -1
  183. package/dist/flip-ui/dist/assets/material-theme-palenight-Csfq5Kiy.js +0 -1
  184. package/dist/flip-ui/dist/assets/matlab-D7o27uSR.js +0 -1
  185. package/dist/flip-ui/dist/assets/mdc-DUICxH0z.js +0 -1
  186. package/dist/flip-ui/dist/assets/mdx-Cmh6b_Ma.js +0 -1
  187. package/dist/flip-ui/dist/assets/mermaid-mWjccvbQ.js +0 -1
  188. package/dist/flip-ui/dist/assets/min-dark-CafNBF8u.js +0 -1
  189. package/dist/flip-ui/dist/assets/min-light-CTRr51gU.js +0 -1
  190. package/dist/flip-ui/dist/assets/mipsasm-CKIfxQSi.js +0 -1
  191. package/dist/flip-ui/dist/assets/mojo-B93PlW-d.js +0 -1
  192. package/dist/flip-ui/dist/assets/monokai-D4h5O-jR.js +0 -1
  193. package/dist/flip-ui/dist/assets/moonbit-Ba13S78F.js +0 -1
  194. package/dist/flip-ui/dist/assets/move-Bu9oaDYs.js +0 -1
  195. package/dist/flip-ui/dist/assets/narrat-DRg8JJMk.js +0 -1
  196. package/dist/flip-ui/dist/assets/nextflow-BrzmwbiE.js +0 -1
  197. package/dist/flip-ui/dist/assets/nginx-DknmC5AR.js +0 -1
  198. package/dist/flip-ui/dist/assets/night-owl-C39BiMTA.js +0 -1
  199. package/dist/flip-ui/dist/assets/nim-CVrawwO9.js +0 -1
  200. package/dist/flip-ui/dist/assets/nix-CwoSXNpI.js +0 -1
  201. package/dist/flip-ui/dist/assets/nord-Ddv68eIx.js +0 -1
  202. package/dist/flip-ui/dist/assets/nushell-C-sUppwS.js +0 -1
  203. package/dist/flip-ui/dist/assets/objective-c-DXmwc3jG.js +0 -1
  204. package/dist/flip-ui/dist/assets/objective-cpp-CLxacb5B.js +0 -1
  205. package/dist/flip-ui/dist/assets/ocaml-C0hk2d4L.js +0 -1
  206. package/dist/flip-ui/dist/assets/one-dark-pro-DVMEJ2y_.js +0 -1
  207. package/dist/flip-ui/dist/assets/one-light-PoHY5YXO.js +0 -1
  208. package/dist/flip-ui/dist/assets/openscad-C4EeE6gA.js +0 -1
  209. package/dist/flip-ui/dist/assets/pascal-D93ZcfNL.js +0 -1
  210. package/dist/flip-ui/dist/assets/perl-C0TMdlhV.js +0 -1
  211. package/dist/flip-ui/dist/assets/php-CDn_0X-4.js +0 -1
  212. package/dist/flip-ui/dist/assets/pkl-u5AG7uiY.js +0 -1
  213. package/dist/flip-ui/dist/assets/plastic-3e1v2bzS.js +0 -1
  214. package/dist/flip-ui/dist/assets/plsql-ChMvpjG-.js +0 -1
  215. package/dist/flip-ui/dist/assets/po-BTJTHyun.js +0 -1
  216. package/dist/flip-ui/dist/assets/poimandres-CS3Unz2-.js +0 -1
  217. package/dist/flip-ui/dist/assets/polar-C0HS_06l.js +0 -1
  218. package/dist/flip-ui/dist/assets/postcss-CXtECtnM.js +0 -1
  219. package/dist/flip-ui/dist/assets/powerquery-CEu0bR-o.js +0 -1
  220. package/dist/flip-ui/dist/assets/powershell-Dpen1YoG.js +0 -1
  221. package/dist/flip-ui/dist/assets/prisma-Dd19v3D-.js +0 -1
  222. package/dist/flip-ui/dist/assets/prolog-CbFg5uaA.js +0 -1
  223. package/dist/flip-ui/dist/assets/proto-C7zT0LnQ.js +0 -1
  224. package/dist/flip-ui/dist/assets/pug-CGlum2m_.js +0 -1
  225. package/dist/flip-ui/dist/assets/puppet-BMWR74SV.js +0 -1
  226. package/dist/flip-ui/dist/assets/purescript-CklMAg4u.js +0 -1
  227. package/dist/flip-ui/dist/assets/python-B6aJPvgy.js +0 -1
  228. package/dist/flip-ui/dist/assets/qml-3beO22l8.js +0 -1
  229. package/dist/flip-ui/dist/assets/qmldir-C8lEn-DE.js +0 -1
  230. package/dist/flip-ui/dist/assets/qss-IeuSbFQv.js +0 -1
  231. package/dist/flip-ui/dist/assets/r-Dspwwk_N.js +0 -1
  232. package/dist/flip-ui/dist/assets/racket-BqYA7rlc.js +0 -1
  233. package/dist/flip-ui/dist/assets/raku-DXvB9xmW.js +0 -1
  234. package/dist/flip-ui/dist/assets/razor-C1TweQQi.js +0 -1
  235. package/dist/flip-ui/dist/assets/red-bN70gL4F.js +0 -1
  236. package/dist/flip-ui/dist/assets/reg-C-SQnVFl.js +0 -1
  237. package/dist/flip-ui/dist/assets/regexp-CDVJQ6XC.js +0 -1
  238. package/dist/flip-ui/dist/assets/rel-C3B-1QV4.js +0 -1
  239. package/dist/flip-ui/dist/assets/riscv-BM1_JUlF.js +0 -1
  240. package/dist/flip-ui/dist/assets/rose-pine-dawn-DHQR4-dF.js +0 -1
  241. package/dist/flip-ui/dist/assets/rose-pine-moon-D4_iv3hh.js +0 -1
  242. package/dist/flip-ui/dist/assets/rose-pine-qdsjHGoJ.js +0 -1
  243. package/dist/flip-ui/dist/assets/rosmsg-BJDFO7_C.js +0 -1
  244. package/dist/flip-ui/dist/assets/rst-B0xPkSld.js +0 -1
  245. package/dist/flip-ui/dist/assets/ruby-BvKwtOVI.js +0 -1
  246. package/dist/flip-ui/dist/assets/rust-B1yitclQ.js +0 -1
  247. package/dist/flip-ui/dist/assets/sas-cz2c8ADy.js +0 -1
  248. package/dist/flip-ui/dist/assets/sass-Cj5Yp3dK.js +0 -1
  249. package/dist/flip-ui/dist/assets/scala-C151Ov-r.js +0 -1
  250. package/dist/flip-ui/dist/assets/scheme-C98Dy4si.js +0 -1
  251. package/dist/flip-ui/dist/assets/scss-OYdSNvt2.js +0 -1
  252. package/dist/flip-ui/dist/assets/sdbl-DVxCFoDh.js +0 -1
  253. package/dist/flip-ui/dist/assets/shaderlab-Dg9Lc6iA.js +0 -1
  254. package/dist/flip-ui/dist/assets/shellscript-Yzrsuije.js +0 -1
  255. package/dist/flip-ui/dist/assets/shellsession-BADoaaVG.js +0 -1
  256. package/dist/flip-ui/dist/assets/slack-dark-BthQWCQV.js +0 -1
  257. package/dist/flip-ui/dist/assets/slack-ochin-DqwNpetd.js +0 -1
  258. package/dist/flip-ui/dist/assets/smalltalk-BERRCDM3.js +0 -1
  259. package/dist/flip-ui/dist/assets/snazzy-light-Bw305WKR.js +0 -1
  260. package/dist/flip-ui/dist/assets/solarized-dark-DXbdFlpD.js +0 -1
  261. package/dist/flip-ui/dist/assets/solarized-light-L9t79GZl.js +0 -1
  262. package/dist/flip-ui/dist/assets/solidity-rGO070M0.js +0 -1
  263. package/dist/flip-ui/dist/assets/soy-Brmx7dQM.js +0 -1
  264. package/dist/flip-ui/dist/assets/sparql-rVzFXLq3.js +0 -1
  265. package/dist/flip-ui/dist/assets/splunk-BtCnVYZw.js +0 -1
  266. package/dist/flip-ui/dist/assets/sql-BLtJtn59.js +0 -1
  267. package/dist/flip-ui/dist/assets/ssh-config-_ykCGR6B.js +0 -1
  268. package/dist/flip-ui/dist/assets/stata-BH5u7GGu.js +0 -1
  269. package/dist/flip-ui/dist/assets/stylus-BEDo0Tqx.js +0 -1
  270. package/dist/flip-ui/dist/assets/svelte-zxCyuUbr.js +0 -1
  271. package/dist/flip-ui/dist/assets/swift-Dg5xB15N.js +0 -1
  272. package/dist/flip-ui/dist/assets/synthwave-84-CbfX1IO0.js +0 -1
  273. package/dist/flip-ui/dist/assets/system-verilog-CnnmHF94.js +0 -1
  274. package/dist/flip-ui/dist/assets/systemd-4A_iFExJ.js +0 -1
  275. package/dist/flip-ui/dist/assets/talonscript-CkByrt1z.js +0 -1
  276. package/dist/flip-ui/dist/assets/tasl-QIJgUcNo.js +0 -1
  277. package/dist/flip-ui/dist/assets/tcl-dwOrl1Do.js +0 -1
  278. package/dist/flip-ui/dist/assets/templ-W15q3VgB.js +0 -1
  279. package/dist/flip-ui/dist/assets/terraform-BETggiCN.js +0 -1
  280. package/dist/flip-ui/dist/assets/tex-CvyZ59Mk.js +0 -1
  281. package/dist/flip-ui/dist/assets/tokyo-night-hegEt444.js +0 -1
  282. package/dist/flip-ui/dist/assets/toml-vGWfd6FD.js +0 -1
  283. package/dist/flip-ui/dist/assets/ts-tags-zn1MmPIZ.js +0 -1
  284. package/dist/flip-ui/dist/assets/tsv-B_m7g4N7.js +0 -1
  285. package/dist/flip-ui/dist/assets/tsx-COt5Ahok.js +0 -1
  286. package/dist/flip-ui/dist/assets/turtle-BsS91CYL.js +0 -1
  287. package/dist/flip-ui/dist/assets/twig-CO9l9SDP.js +0 -1
  288. package/dist/flip-ui/dist/assets/typescript-BPQ3VLAy.js +0 -1
  289. package/dist/flip-ui/dist/assets/typespec-BGHnOYBU.js +0 -1
  290. package/dist/flip-ui/dist/assets/typst-DHCkPAjA.js +0 -1
  291. package/dist/flip-ui/dist/assets/v-BcVCzyr7.js +0 -1
  292. package/dist/flip-ui/dist/assets/vala-CsfeWuGM.js +0 -1
  293. package/dist/flip-ui/dist/assets/vb-D17OF-Vu.js +0 -1
  294. package/dist/flip-ui/dist/assets/verilog-BQ8w6xss.js +0 -1
  295. package/dist/flip-ui/dist/assets/vesper-DU1UobuO.js +0 -1
  296. package/dist/flip-ui/dist/assets/vhdl-CeAyd5Ju.js +0 -1
  297. package/dist/flip-ui/dist/assets/viml-CJc9bBzg.js +0 -1
  298. package/dist/flip-ui/dist/assets/vitesse-black-Bkuqu6BP.js +0 -1
  299. package/dist/flip-ui/dist/assets/vitesse-dark-D0r3Knsf.js +0 -1
  300. package/dist/flip-ui/dist/assets/vitesse-light-CVO1_9PV.js +0 -1
  301. package/dist/flip-ui/dist/assets/vue-DN_0RTcg.js +0 -1
  302. package/dist/flip-ui/dist/assets/vue-html-AaS7Mt5G.js +0 -1
  303. package/dist/flip-ui/dist/assets/vue-vine-CQOfvN7w.js +0 -1
  304. package/dist/flip-ui/dist/assets/vyper-CDx5xZoG.js +0 -1
  305. package/dist/flip-ui/dist/assets/wasm-CG6Dc4jp.js +0 -1
  306. package/dist/flip-ui/dist/assets/wasm-MzD3tlZU.js +0 -1
  307. package/dist/flip-ui/dist/assets/wenyan-BV7otONQ.js +0 -1
  308. package/dist/flip-ui/dist/assets/wgsl-Dx-B1_4e.js +0 -1
  309. package/dist/flip-ui/dist/assets/wikitext-BhOHFoWU.js +0 -1
  310. package/dist/flip-ui/dist/assets/wit-5i3qLPDT.js +0 -1
  311. package/dist/flip-ui/dist/assets/wolfram-lXgVvXCa.js +0 -1
  312. package/dist/flip-ui/dist/assets/xml-sdJ4AIDG.js +0 -1
  313. package/dist/flip-ui/dist/assets/xsl-CtQFsRM5.js +0 -1
  314. package/dist/flip-ui/dist/assets/yaml-Buea-lGh.js +0 -1
  315. package/dist/flip-ui/dist/assets/zenscript-DVFEvuxE.js +0 -1
  316. package/dist/flip-ui/dist/assets/zig-VOosw3JB.js +0 -1
@@ -0,0 +1,2 @@
1
+ export declare const FILTERED_PATTERNS: Set<string>;
2
+ export declare function isFiltered(name: string): boolean;
@@ -0,0 +1,30 @@
1
+ // Patterns to filter for performance (O(1) lookup with Set)
2
+ // These are system directories that users don't directly edit
3
+ export const FILTERED_PATTERNS = new Set([
4
+ // Package managers
5
+ 'node_modules',
6
+ 'vendor',
7
+ '.pnpm-store',
8
+ // VCS internal
9
+ '.git',
10
+ '.svn',
11
+ '.hg',
12
+ // OS metadata
13
+ '.DS_Store',
14
+ 'Thumbs.db',
15
+ // Build output
16
+ 'dist',
17
+ 'build',
18
+ 'out',
19
+ // Cache directories
20
+ '.cache',
21
+ '.next',
22
+ '.nuxt',
23
+ 'coverage',
24
+ '__pycache__',
25
+ '.pytest_cache',
26
+ 'target',
27
+ ]);
28
+ export function isFiltered(name) {
29
+ return FILTERED_PATTERNS.has(name);
30
+ }
@@ -0,0 +1,10 @@
1
+ import { Response } from 'express';
2
+ import { SyncEvent } from './types.js';
3
+ export declare class SSEManager {
4
+ private clients;
5
+ addClient(res: Response): void;
6
+ removeClient(res: Response): void;
7
+ broadcast(event: SyncEvent): void;
8
+ closeAll(): void;
9
+ get clientCount(): number;
10
+ }
@@ -0,0 +1,28 @@
1
+ export class SSEManager {
2
+ clients = new Set();
3
+ addClient(res) {
4
+ this.clients.add(res);
5
+ res.on('close', () => {
6
+ this.clients.delete(res);
7
+ });
8
+ }
9
+ removeClient(res) {
10
+ this.clients.delete(res);
11
+ }
12
+ broadcast(event) {
13
+ const data = JSON.stringify(event);
14
+ const message = `data: ${data}\n\n`;
15
+ this.clients.forEach(client => {
16
+ client.write(message);
17
+ });
18
+ }
19
+ closeAll() {
20
+ this.clients.forEach(client => {
21
+ client.end();
22
+ });
23
+ this.clients.clear();
24
+ }
25
+ get clientCount() {
26
+ return this.clients.size;
27
+ }
28
+ }
@@ -0,0 +1,11 @@
1
+ export type FilesChangeEvent = {
2
+ type: 'files-changed';
3
+ };
4
+ export type FileContentEvent = {
5
+ type: 'file-changed';
6
+ path: string;
7
+ };
8
+ export type GitChangeEvent = {
9
+ type: 'git-changed';
10
+ };
11
+ export type SyncEvent = FilesChangeEvent | FileContentEvent | GitChangeEvent;
@@ -0,0 +1 @@
1
+ export {};
@@ -5,7 +5,7 @@ import fs from 'fs';
5
5
  import os from 'os';
6
6
  import { execSync } from 'child_process';
7
7
  import { confirm } from '@inquirer/prompts';
8
- import clipboardy from 'clipboardy';
8
+ import { copyToClipboard } from './output/clipboard.js';
9
9
  const DEFAULT_PORT = 51234;
10
10
  function formatTime() {
11
11
  const now = new Date();
@@ -226,7 +226,7 @@ osascript ${applescriptPath} > /dev/null 2>&1
226
226
  console.log('└─────────────────────────────────────────────────┘');
227
227
  console.log('');
228
228
  // Copy path to clipboard
229
- await clipboardy.write(shPath);
229
+ await copyToClipboard(shPath);
230
230
  console.log(`✓ Copied to clipboard: ${shPath}`);
231
231
  console.log('');
232
232
  await confirm({
@@ -1,4 +1,4 @@
1
- import { execSync } from 'child_process';
1
+ import { spawn } from 'child_process';
2
2
  import fs from 'fs';
3
3
  import path from 'path';
4
4
  import os from 'os';
@@ -70,9 +70,21 @@ async function pasteToOriginalSession(sessionId) {
70
70
  `;
71
71
  }
72
72
  try {
73
- execSync(`osascript -e '${script.replace(/'/g, "'\"'\"'")}'`, {
74
- stdio: 'pipe',
73
+ // Write script to temp file and execute via detached process
74
+ const tmpScript = path.join(os.tmpdir(), `flip-paste-${Date.now()}.scpt`);
75
+ fs.writeFileSync(tmpScript, script);
76
+ const child = spawn('osascript', [tmpScript], {
77
+ detached: true,
78
+ stdio: 'ignore',
75
79
  });
80
+ child.unref();
81
+ // Schedule cleanup
82
+ setTimeout(() => {
83
+ try {
84
+ fs.unlinkSync(tmpScript);
85
+ }
86
+ catch { }
87
+ }, 5000);
76
88
  }
77
89
  catch (e) {
78
90
  console.error('Failed to paste to iTerm:', e);
@@ -1,7 +1,61 @@
1
- import clipboardy from 'clipboardy';
1
+ import { spawn } from 'child_process';
2
+ import fs from 'fs';
3
+ import path from 'path';
4
+ import os from 'os';
2
5
  /**
3
6
  * Copy text to system clipboard
4
7
  */
5
8
  export async function copyToClipboard(text) {
6
- await clipboardy.write(text);
9
+ if (process.platform === 'darwin') {
10
+ // Write to temp file first, then use pbcopy via shell
11
+ const tmpFile = path.join(os.tmpdir(), `flip-clipboard-${Date.now()}.txt`);
12
+ try {
13
+ fs.writeFileSync(tmpFile, text);
14
+ // Use a detached process to avoid EBADF
15
+ const child = spawn('sh', ['-c', `cat "${tmpFile}" | pbcopy && rm "${tmpFile}"`], {
16
+ detached: true,
17
+ stdio: 'ignore',
18
+ });
19
+ child.unref();
20
+ }
21
+ catch (e) {
22
+ // Fallback: just leave the file for manual copy
23
+ console.log(`Output saved to: ${tmpFile}`);
24
+ throw e;
25
+ }
26
+ }
27
+ else if (process.platform === 'linux') {
28
+ const tmpFile = path.join(os.tmpdir(), `flip-clipboard-${Date.now()}.txt`);
29
+ fs.writeFileSync(tmpFile, text);
30
+ try {
31
+ const child = spawn('sh', ['-c', `cat "${tmpFile}" | xclip -selection clipboard && rm "${tmpFile}"`], {
32
+ detached: true,
33
+ stdio: 'ignore',
34
+ });
35
+ child.unref();
36
+ }
37
+ catch {
38
+ try {
39
+ const child = spawn('sh', ['-c', `cat "${tmpFile}" | xsel --clipboard --input && rm "${tmpFile}"`], {
40
+ detached: true,
41
+ stdio: 'ignore',
42
+ });
43
+ child.unref();
44
+ }
45
+ catch (e) {
46
+ // Final fallback if both xclip and xsel fail
47
+ console.log(`Output saved to: ${tmpFile}`);
48
+ throw e;
49
+ }
50
+ }
51
+ }
52
+ else if (process.platform === 'win32') {
53
+ const tmpFile = path.join(os.tmpdir(), `flip-clipboard-${Date.now()}.txt`);
54
+ fs.writeFileSync(tmpFile, text);
55
+ const child = spawn('cmd', ['/c', `type "${tmpFile}" | clip && del "${tmpFile}"`], {
56
+ detached: true,
57
+ stdio: 'ignore',
58
+ });
59
+ child.unref();
60
+ }
7
61
  }
@@ -0,0 +1,3 @@
1
+ import type { Router as IRouter } from 'express';
2
+ import { SSEManager } from '../events/SSEManager.js';
3
+ export declare function createEventsRouter(sseManager: SSEManager): IRouter;
@@ -0,0 +1,25 @@
1
+ import { Router } from 'express';
2
+ export function createEventsRouter(sseManager) {
3
+ const router = Router();
4
+ // GET /api/events - SSE endpoint for real-time updates
5
+ router.get('/', (req, res) => {
6
+ // Set SSE headers
7
+ res.setHeader('Content-Type', 'text/event-stream');
8
+ res.setHeader('Cache-Control', 'no-cache');
9
+ res.setHeader('Connection', 'keep-alive');
10
+ res.setHeader('X-Accel-Buffering', 'no'); // Disable nginx buffering
11
+ // Send initial connection message
12
+ res.write('data: {"type":"connected"}\n\n');
13
+ // Register client
14
+ sseManager.addClient(res);
15
+ // Keep connection alive with heartbeat
16
+ const heartbeat = setInterval(() => {
17
+ res.write(':heartbeat\n\n');
18
+ }, 30000);
19
+ // Cleanup on close (removeClient is handled by SSEManager)
20
+ req.on('close', () => {
21
+ clearInterval(heartbeat);
22
+ });
23
+ });
24
+ return router;
25
+ }
@@ -10,9 +10,14 @@ export interface FilesResponse {
10
10
  root: string;
11
11
  tree: FileNode[];
12
12
  }
13
+ export interface FileWithMtime {
14
+ path: string;
15
+ mtime: number;
16
+ }
13
17
  export interface FlatFilesResponse {
14
- files: string[];
18
+ files: FileWithMtime[];
15
19
  filteredDirs: string[];
20
+ recentFile: string | null;
16
21
  }
17
22
  declare const router: IRouter;
18
23
  export { router as filesRouter };
@@ -1,36 +1,7 @@
1
1
  import { Router } from 'express';
2
2
  import fs from 'fs';
3
3
  import path from 'path';
4
- // Patterns to filter for performance (O(1) lookup with Set)
5
- // These are system directories that users don't directly edit
6
- const FILTERED_PATTERNS = new Set([
7
- // Package managers
8
- 'node_modules',
9
- 'vendor',
10
- '.pnpm-store',
11
- // VCS internal
12
- '.git',
13
- '.svn',
14
- '.hg',
15
- // OS metadata
16
- '.DS_Store',
17
- 'Thumbs.db',
18
- // Build output
19
- 'dist',
20
- 'build',
21
- 'out',
22
- // Cache directories
23
- '.cache',
24
- '.next',
25
- '.nuxt',
26
- 'coverage',
27
- '__pycache__',
28
- '.pytest_cache',
29
- 'target',
30
- ]);
31
- function isFiltered(name) {
32
- return FILTERED_PATTERNS.has(name);
33
- }
4
+ import { isFiltered } from '../constants/filters.js';
34
5
  const router = Router();
35
6
  function buildFileTree(rootPath, currentPath, maxDepth, depth = 0) {
36
7
  if (depth > maxDepth)
@@ -78,7 +49,16 @@ function collectFlatFiles(rootPath, currentPath, maxDepth, depth = 0, result = {
78
49
  continue; // Don't traverse filtered directories
79
50
  }
80
51
  if (entry.isFile()) {
81
- result.files.push(relativePath);
52
+ try {
53
+ const stat = fs.statSync(fullPath);
54
+ result.files.push({
55
+ path: relativePath,
56
+ mtime: stat.mtimeMs,
57
+ });
58
+ }
59
+ catch {
60
+ // Skip files that can't be stat'd
61
+ }
82
62
  }
83
63
  else if (entry.isDirectory()) {
84
64
  collectFlatFiles(rootPath, fullPath, maxDepth, depth + 1, result);
@@ -96,15 +76,23 @@ router.get('/', (req, res) => {
96
76
  };
97
77
  res.json(response);
98
78
  });
99
- // GET /api/files/flat - Get flat list of all files
79
+ // GET /api/files/flat - Get flat list of all files with mtime
100
80
  router.get('/flat', (req, res) => {
101
81
  const state = req.app.locals.state;
102
82
  const result = collectFlatFiles(state.cwd, state.cwd, 10);
103
- result.files.sort();
83
+ // Sort files by path for consistent display
84
+ result.files.sort((a, b) => a.path.localeCompare(b.path));
104
85
  result.filteredDirs.sort();
86
+ // Find the most recently modified file
87
+ let recentFile = null;
88
+ if (result.files.length > 0) {
89
+ const mostRecent = result.files.reduce((prev, curr) => curr.mtime > prev.mtime ? curr : prev);
90
+ recentFile = mostRecent.path;
91
+ }
105
92
  const response = {
106
93
  files: result.files,
107
94
  filteredDirs: result.filteredDirs,
95
+ recentFile,
108
96
  };
109
97
  res.json(response);
110
98
  });
@@ -8,8 +8,14 @@ export function createStaticRouter() {
8
8
  // Get __dirname equivalent in ESM
9
9
  const __filename = fileURLToPath(import.meta.url);
10
10
  const __dirname = path.dirname(__filename);
11
- // Path to the built web-ui (relative to dist/ after bundling)
12
- const distPath = path.resolve(__dirname, 'flip-ui/dist');
11
+ // First, check for the bundled path. This is more robust than checking the filename.
12
+ // - Bundled: dist/flip-ui/dist
13
+ let distPath = path.resolve(__dirname, 'flip-ui/dist');
14
+ // If the bundled path doesn't exist, fall back to the unbundled (development) path.
15
+ // - Unbundled: packages/cli/flip-ui/dist
16
+ if (!fs.existsSync(distPath)) {
17
+ distPath = path.resolve(__dirname, '../../../flip-ui/dist');
18
+ }
13
19
  // Check if dist exists (for development vs production)
14
20
  if (fs.existsSync(distPath)) {
15
21
  // Serve static files
@@ -18,19 +18,26 @@ router.post('/', async (req, res) => {
18
18
  }));
19
19
  // Format the output
20
20
  const formatted = formatComments(comments);
21
- // Copy to clipboard
21
+ // Copy to clipboard and schedule paste only if copy succeeds
22
+ let clipboardSuccess = false;
22
23
  try {
23
24
  await copyToClipboard(formatted);
25
+ clipboardSuccess = true;
24
26
  }
25
27
  catch (e) {
26
28
  console.error('Failed to copy to clipboard:', e);
29
+ console.log('\n--- Output (copy manually) ---');
30
+ console.log(formatted);
31
+ console.log('--- End of output ---\n');
27
32
  }
28
- // Schedule paste (will execute after server shuts down)
29
- try {
30
- await schedulePaste(body.session_id);
31
- }
32
- catch (e) {
33
- console.error('Failed to schedule paste:', e);
33
+ // Schedule paste only if clipboard copy succeeded
34
+ if (clipboardSuccess) {
35
+ try {
36
+ await schedulePaste(body.session_id);
37
+ }
38
+ catch (e) {
39
+ console.error('Failed to schedule paste:', e);
40
+ }
34
41
  }
35
42
  // Send response before shutdown
36
43
  res.json({ status: 'ok' });
@@ -1,6 +1,6 @@
1
1
  export interface AppState {
2
2
  cwd: string;
3
- resolve: ((output: string | null) => void) | null;
3
+ resolve: ((output: string | null) => void | Promise<void>) | null;
4
4
  }
5
5
  export declare class Server {
6
6
  private cwd;
@@ -8,6 +8,9 @@ import { gitRouter } from '../routes/git.js';
8
8
  import { submitRouter } from '../routes/submit.js';
9
9
  import { cancelRouter } from '../routes/cancel.js';
10
10
  import { createStaticRouter } from '../routes/static.js';
11
+ import { createEventsRouter } from '../routes/events.js';
12
+ import { FileWatcher } from '../watcher/FileWatcher.js';
13
+ import { SSEManager } from '../events/SSEManager.js';
11
14
  export class Server {
12
15
  cwd;
13
16
  port;
@@ -27,18 +30,37 @@ export class Server {
27
30
  app.use(express.json());
28
31
  // Store state in app locals
29
32
  app.locals.state = state;
33
+ // Initialize SSE manager and file watcher
34
+ const sseManager = new SSEManager();
35
+ const fileWatcher = new FileWatcher({ cwd: this.cwd });
36
+ // Set up watcher event handlers
37
+ fileWatcher.onFilesChanged(() => {
38
+ sseManager.broadcast({ type: 'files-changed' });
39
+ });
40
+ fileWatcher.onFileChanged((path) => {
41
+ sseManager.broadcast({ type: 'file-changed', path });
42
+ });
43
+ fileWatcher.onGitChanged(() => {
44
+ sseManager.broadcast({ type: 'git-changed' });
45
+ });
46
+ // Start watching
47
+ fileWatcher.start();
30
48
  // API routes
31
49
  app.use('/api/files', filesRouter);
32
50
  app.use('/api/file', fileRouter);
33
51
  app.use('/api/git', gitRouter);
34
52
  app.use('/api/submit', submitRouter);
35
53
  app.use('/api/cancel', cancelRouter);
54
+ app.use('/api/events', createEventsRouter(sseManager));
36
55
  // Static files (fallback to web-ui dist)
37
56
  app.use(createStaticRouter());
38
57
  const server = http.createServer(app);
39
58
  // Set up the shutdown mechanism
40
- state.resolve = (output) => {
41
- server.close();
59
+ state.resolve = async (output) => {
60
+ // Cleanup watcher and SSE connections
61
+ await fileWatcher.stop();
62
+ sseManager.closeAll();
63
+ await new Promise(res => server.close(() => res()));
42
64
  resolve(output);
43
65
  };
44
66
  server.listen(this.port, '127.0.0.1', () => {
@@ -0,0 +1,29 @@
1
+ export interface FileWatcherOptions {
2
+ cwd: string;
3
+ debounceMs?: number;
4
+ }
5
+ type EventCallback = () => void;
6
+ type FileEventCallback = (filePath: string) => void;
7
+ export declare class FileWatcher {
8
+ private watcher;
9
+ private cwd;
10
+ private debounceMs;
11
+ private filesChangedCallbacks;
12
+ private fileChangedCallbacks;
13
+ private gitChangedCallbacks;
14
+ private filesDebounceTimer;
15
+ private gitDebounceTimer;
16
+ private fileDebounceTimers;
17
+ constructor(options: FileWatcherOptions);
18
+ start(): void;
19
+ stop(): Promise<void>;
20
+ onFilesChanged(callback: EventCallback): void;
21
+ onFileChanged(callback: FileEventCallback): void;
22
+ onGitChanged(callback: EventCallback): void;
23
+ private handleFileEvent;
24
+ private handleDirEvent;
25
+ private emitFilesChanged;
26
+ private emitFileChanged;
27
+ private emitGitChanged;
28
+ }
29
+ export {};
@@ -0,0 +1,128 @@
1
+ import chokidar from 'chokidar';
2
+ import * as path from 'path';
3
+ import { FILTERED_PATTERNS } from '../constants/filters.js';
4
+ export class FileWatcher {
5
+ watcher = null;
6
+ cwd;
7
+ debounceMs;
8
+ filesChangedCallbacks = [];
9
+ fileChangedCallbacks = [];
10
+ gitChangedCallbacks = [];
11
+ filesDebounceTimer = null;
12
+ gitDebounceTimer = null;
13
+ fileDebounceTimers = new Map();
14
+ constructor(options) {
15
+ this.cwd = options.cwd;
16
+ this.debounceMs = options.debounceMs ?? 300;
17
+ }
18
+ start() {
19
+ const ignoredPatterns = Array.from(FILTERED_PATTERNS).map(pattern => {
20
+ // .git은 감시하되 내부 변경은 git-changed 이벤트로 처리
21
+ if (pattern === '.git') {
22
+ return undefined;
23
+ }
24
+ return `**/${pattern}/**`;
25
+ }).filter(Boolean);
26
+ this.watcher = chokidar.watch(this.cwd, {
27
+ ignored: ignoredPatterns,
28
+ persistent: true,
29
+ ignoreInitial: true,
30
+ awaitWriteFinish: {
31
+ stabilityThreshold: 100,
32
+ pollInterval: 50,
33
+ },
34
+ });
35
+ this.watcher
36
+ .on('add', (filePath) => this.handleFileEvent(filePath, 'add'))
37
+ .on('unlink', (filePath) => this.handleFileEvent(filePath, 'unlink'))
38
+ .on('change', (filePath) => this.handleFileEvent(filePath, 'change'))
39
+ .on('addDir', (filePath) => this.handleDirEvent(filePath, 'addDir'))
40
+ .on('unlinkDir', (filePath) => this.handleDirEvent(filePath, 'unlinkDir'))
41
+ .on('error', (error) => console.error('Watcher error:', error));
42
+ }
43
+ async stop() {
44
+ if (this.filesDebounceTimer) {
45
+ clearTimeout(this.filesDebounceTimer);
46
+ }
47
+ if (this.gitDebounceTimer) {
48
+ clearTimeout(this.gitDebounceTimer);
49
+ }
50
+ Array.from(this.fileDebounceTimers.values()).forEach(timer => {
51
+ clearTimeout(timer);
52
+ });
53
+ this.fileDebounceTimers.clear();
54
+ if (this.watcher) {
55
+ await this.watcher.close();
56
+ this.watcher = null;
57
+ }
58
+ }
59
+ onFilesChanged(callback) {
60
+ this.filesChangedCallbacks.push(callback);
61
+ }
62
+ onFileChanged(callback) {
63
+ this.fileChangedCallbacks.push(callback);
64
+ }
65
+ onGitChanged(callback) {
66
+ this.gitChangedCallbacks.push(callback);
67
+ }
68
+ handleFileEvent(filePath, event) {
69
+ const relativePath = path.relative(this.cwd, filePath);
70
+ // .git 내부 변경은 git-changed 이벤트
71
+ if (relativePath.startsWith('.git')) {
72
+ this.emitGitChanged();
73
+ return;
74
+ }
75
+ // 파일 추가/삭제는 트리 변경
76
+ if (event === 'add' || event === 'unlink') {
77
+ this.emitFilesChanged();
78
+ }
79
+ // 파일 내용 변경
80
+ if (event === 'change' || event === 'add') {
81
+ this.emitFileChanged(relativePath);
82
+ }
83
+ // 모든 파일 변경은 잠재적으로 git 상태에 영향
84
+ this.emitGitChanged();
85
+ }
86
+ handleDirEvent(dirPath, event) {
87
+ const relativePath = path.relative(this.cwd, dirPath);
88
+ // .git 내부는 무시
89
+ if (relativePath.startsWith('.git')) {
90
+ return;
91
+ }
92
+ // 디렉토리 변경은 트리 변경
93
+ this.emitFilesChanged();
94
+ }
95
+ emitFilesChanged() {
96
+ if (this.filesDebounceTimer) {
97
+ clearTimeout(this.filesDebounceTimer);
98
+ }
99
+ this.filesDebounceTimer = setTimeout(() => {
100
+ for (const callback of this.filesChangedCallbacks) {
101
+ callback();
102
+ }
103
+ }, this.debounceMs);
104
+ }
105
+ emitFileChanged(relativePath) {
106
+ const existingTimer = this.fileDebounceTimers.get(relativePath);
107
+ if (existingTimer) {
108
+ clearTimeout(existingTimer);
109
+ }
110
+ const timer = setTimeout(() => {
111
+ this.fileDebounceTimers.delete(relativePath);
112
+ for (const callback of this.fileChangedCallbacks) {
113
+ callback(relativePath);
114
+ }
115
+ }, this.debounceMs);
116
+ this.fileDebounceTimers.set(relativePath, timer);
117
+ }
118
+ emitGitChanged() {
119
+ if (this.gitDebounceTimer) {
120
+ clearTimeout(this.gitDebounceTimer);
121
+ }
122
+ this.gitDebounceTimer = setTimeout(() => {
123
+ for (const callback of this.gitChangedCallbacks) {
124
+ callback();
125
+ }
126
+ }, this.debounceMs);
127
+ }
128
+ }