@sunshinelife83/hearth 1.0.0

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 (436) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +323 -0
  3. package/bin/hearth-agentd.js +4 -0
  4. package/bin/hearth.js +4 -0
  5. package/bin/run-entrypoint.js +20 -0
  6. package/dist/agent-tools.js +738 -0
  7. package/dist/app-version.js +16 -0
  8. package/dist/apply-patch.js +402 -0
  9. package/dist/artifact-error.js +8 -0
  10. package/dist/artifact-tools.js +377 -0
  11. package/dist/cli-workspace.js +36 -0
  12. package/dist/cli.js +1086 -0
  13. package/dist/config-migration.js +82 -0
  14. package/dist/config-schema.js +136 -0
  15. package/dist/config.js +115 -0
  16. package/dist/context/context-tools.js +150 -0
  17. package/dist/context/repo-map.js +102 -0
  18. package/dist/dashboard/app.js +226 -0
  19. package/dist/dashboard/index.html +45 -0
  20. package/dist/dashboard/landing.html +57 -0
  21. package/dist/dashboard/styles.css +23 -0
  22. package/dist/dashboard.js +271 -0
  23. package/dist/db/client.js +29 -0
  24. package/dist/db/migrations.js +262 -0
  25. package/dist/db/schema.js +85 -0
  26. package/dist/device-tokens.js +61 -0
  27. package/dist/git-worktrees.js +134 -0
  28. package/dist/git.js +41 -0
  29. package/dist/incoming-artifacts.js +378 -0
  30. package/dist/local-agent-acp.js +768 -0
  31. package/dist/local-agent-adapters.js +20 -0
  32. package/dist/local-agent-availability.js +92 -0
  33. package/dist/local-agent-catalog.js +51 -0
  34. package/dist/local-agent-claude.js +334 -0
  35. package/dist/local-agent-client.js +519 -0
  36. package/dist/local-agent-codex.js +532 -0
  37. package/dist/local-agent-config.js +34 -0
  38. package/dist/local-agent-daemon-lifecycle.js +195 -0
  39. package/dist/local-agent-daemon-main.js +86 -0
  40. package/dist/local-agent-daemon-protocol.js +302 -0
  41. package/dist/local-agent-daemon.js +407 -0
  42. package/dist/local-agent-errors.js +378 -0
  43. package/dist/local-agent-grok.js +202 -0
  44. package/dist/local-agent-manager.js +715 -0
  45. package/dist/local-agent-opencode.js +463 -0
  46. package/dist/local-agent-path.js +24 -0
  47. package/dist/local-agent-pi-sandbox.js +472 -0
  48. package/dist/local-agent-pi.js +298 -0
  49. package/dist/local-agent-presentation.js +104 -0
  50. package/dist/local-agent-profiles.js +127 -0
  51. package/dist/local-agent-runtime-pool.js +481 -0
  52. package/dist/local-agent-runtime.js +1 -0
  53. package/dist/local-agent-store.js +193 -0
  54. package/dist/local-agent-targets.js +97 -0
  55. package/dist/logger.js +97 -0
  56. package/dist/machine-id.js +35 -0
  57. package/dist/mcp-modern-server.js +65 -0
  58. package/dist/oauth-provider.js +331 -0
  59. package/dist/oauth-store.js +144 -0
  60. package/dist/onboarding.js +35 -0
  61. package/dist/orchestration/brief.js +70 -0
  62. package/dist/orchestration/lanes.js +145 -0
  63. package/dist/orchestration/result.js +46 -0
  64. package/dist/orchestration/scope.js +61 -0
  65. package/dist/pi-tools.js +58 -0
  66. package/dist/policy/command-policy.js +104 -0
  67. package/dist/policy/env-allowlist.js +96 -0
  68. package/dist/policy/sandbox.js +68 -0
  69. package/dist/policy/workspace-profiles.js +47 -0
  70. package/dist/process-journal.js +116 -0
  71. package/dist/process-platform.js +49 -0
  72. package/dist/process-sessions.js +388 -0
  73. package/dist/rate-limit.js +77 -0
  74. package/dist/request-meta.js +9 -0
  75. package/dist/review-checkpoints.js +349 -0
  76. package/dist/roots.js +37 -0
  77. package/dist/server-shutdown.js +12 -0
  78. package/dist/server.js +980 -0
  79. package/dist/skills.js +84 -0
  80. package/dist/snapshot-manager.js +123 -0
  81. package/dist/stdio-server.js +80 -0
  82. package/dist/task-store.js +203 -0
  83. package/dist/task-tools.js +455 -0
  84. package/dist/tool-surfaces/claude.js +220 -0
  85. package/dist/tool-surfaces/codex.js +255 -0
  86. package/dist/tool-surfaces/index.js +15 -0
  87. package/dist/tool-surfaces/shared.js +228 -0
  88. package/dist/tool-surfaces/types.js +27 -0
  89. package/dist/ui/.vite/manifest.json +2544 -0
  90. package/dist/ui/assets/abap-CLvhMVsD.js +1 -0
  91. package/dist/ui/assets/actionscript-3--17pq3dv.js +1 -0
  92. package/dist/ui/assets/ada-C5qYipkI.js +1 -0
  93. package/dist/ui/assets/andromeeda-vGVdxbeo.js +1 -0
  94. package/dist/ui/assets/angular-html-DrbO3_Xe.js +1 -0
  95. package/dist/ui/assets/angular-ts-CmTVzHJx.js +1 -0
  96. package/dist/ui/assets/apache-U0d_L8uA.js +1 -0
  97. package/dist/ui/assets/apex-CGTLDQj6.js +1 -0
  98. package/dist/ui/assets/apl-BOpCpqXf.js +1 -0
  99. package/dist/ui/assets/applescript-CCn79oCD.js +1 -0
  100. package/dist/ui/assets/ara-4CJ0cIlV.js +1 -0
  101. package/dist/ui/assets/asciidoc-DE70LPWp.js +1 -0
  102. package/dist/ui/assets/asm-Cmm7eHzH.js +1 -0
  103. package/dist/ui/assets/astro-CxPeBwei.js +1 -0
  104. package/dist/ui/assets/aurora-x-CDeNXAV0.js +1 -0
  105. package/dist/ui/assets/awk-BWXHIvNe.js +1 -0
  106. package/dist/ui/assets/ayu-dark-DluEY0Gj.js +1 -0
  107. package/dist/ui/assets/ayu-light-C3h-C4tm.js +1 -0
  108. package/dist/ui/assets/ayu-mirage-Bqwy1Gya.js +1 -0
  109. package/dist/ui/assets/ballerina-B7ZEbQpA.js +1 -0
  110. package/dist/ui/assets/bat-Bo4NYOV-.js +1 -0
  111. package/dist/ui/assets/beancount-D-usSTwE.js +1 -0
  112. package/dist/ui/assets/berry-DKpUyyne.js +1 -0
  113. package/dist/ui/assets/bibtex-Ci_nEsc7.js +1 -0
  114. package/dist/ui/assets/bicep-CUHmPFLl.js +1 -0
  115. package/dist/ui/assets/bird2-C2hNVINV.js +1 -0
  116. package/dist/ui/assets/blade-DtsAAG4P.js +1 -0
  117. package/dist/ui/assets/bsl-BkkzgIyY.js +1 -0
  118. package/dist/ui/assets/c-D9hLjNUM.js +1 -0
  119. package/dist/ui/assets/c3-CnJL0r0V.js +1 -0
  120. package/dist/ui/assets/cadence-CQ2zXKGN.js +1 -0
  121. package/dist/ui/assets/cairo-DLTphjLi.js +1 -0
  122. package/dist/ui/assets/catppuccin-frappe-3VR1Za6u.js +1 -0
  123. package/dist/ui/assets/catppuccin-latte-DwIHMF0Q.js +1 -0
  124. package/dist/ui/assets/catppuccin-macchiato-DYnBP6_5.js +1 -0
  125. package/dist/ui/assets/catppuccin-mocha-DYhrFGRu.js +1 -0
  126. package/dist/ui/assets/clarity-SemFz856.js +1 -0
  127. package/dist/ui/assets/clojure-DqKBuwfJ.js +1 -0
  128. package/dist/ui/assets/cmake-Bj61d0ZC.js +1 -0
  129. package/dist/ui/assets/cobol-C1SWlvZm.js +1 -0
  130. package/dist/ui/assets/codeowners-C8r90Shi.js +1 -0
  131. package/dist/ui/assets/codeql-oeQT6MSM.js +1 -0
  132. package/dist/ui/assets/coffee-B71R3v2U.js +1 -0
  133. package/dist/ui/assets/common-lisp-Cv5bFMCO.js +1 -0
  134. package/dist/ui/assets/coq-BrsZFFmf.js +1 -0
  135. package/dist/ui/assets/cpp--5a4c3v4.js +1 -0
  136. package/dist/ui/assets/crystal-AtqWYtE0.js +1 -0
  137. package/dist/ui/assets/csharp-Ct8U2NOr.js +1 -0
  138. package/dist/ui/assets/css-CbqKSHI-.js +1 -0
  139. package/dist/ui/assets/csv-Dx-8-gkx.js +1 -0
  140. package/dist/ui/assets/cue-CE9AQfxI.js +1 -0
  141. package/dist/ui/assets/cypher-ClKdZ_lG.js +1 -0
  142. package/dist/ui/assets/d-qD-0Kul2.js +1 -0
  143. package/dist/ui/assets/dark-plus-Cs2F2srj.js +1 -0
  144. package/dist/ui/assets/dart-DkHntEIa.js +1 -0
  145. package/dist/ui/assets/dax-BkyTk9wS.js +1 -0
  146. package/dist/ui/assets/desktop-Dlh5hvp9.js +1 -0
  147. package/dist/ui/assets/diff-woXpYk--.js +1 -0
  148. package/dist/ui/assets/docker-IyjqRm3v.js +1 -0
  149. package/dist/ui/assets/dotenv-_5a1GRtc.js +1 -0
  150. package/dist/ui/assets/dracula-BHWKrbxM.js +1 -0
  151. package/dist/ui/assets/dracula-soft-5eyTD99u.js +1 -0
  152. package/dist/ui/assets/dream-maker-DW3nJb8Q.js +1 -0
  153. package/dist/ui/assets/edge-BPwY_RrJ.js +1 -0
  154. package/dist/ui/assets/elixir-DVH2yLJf.js +1 -0
  155. package/dist/ui/assets/elm-BrleA6gS.js +1 -0
  156. package/dist/ui/assets/emacs-lisp-C9PiwqqW.js +1 -0
  157. package/dist/ui/assets/erb-2SHiYe30.js +1 -0
  158. package/dist/ui/assets/erlang-Cphh6RMH.js +1 -0
  159. package/dist/ui/assets/everforest-dark-sB-x3p7T.js +1 -0
  160. package/dist/ui/assets/everforest-light-Df2xbC6M.js +1 -0
  161. package/dist/ui/assets/fennel-DQxkIbk2.js +1 -0
  162. package/dist/ui/assets/fish-BJitypiv.js +1 -0
  163. package/dist/ui/assets/fluent-C03EYrpw.js +1 -0
  164. package/dist/ui/assets/fortran-fixed-form-DEKoE2YW.js +1 -0
  165. package/dist/ui/assets/fortran-free-form-CYNrtFtB.js +1 -0
  166. package/dist/ui/assets/fsharp-D13ZGOAj.js +1 -0
  167. package/dist/ui/assets/gdresource-C0sCabJj.js +1 -0
  168. package/dist/ui/assets/gdscript-Cp2uCuqX.js +1 -0
  169. package/dist/ui/assets/gdshader-CBce3t8t.js +1 -0
  170. package/dist/ui/assets/genie-CV2tkWYe.js +1 -0
  171. package/dist/ui/assets/gherkin-DExj1W_8.js +1 -0
  172. package/dist/ui/assets/git-commit-BSykSTBG.js +1 -0
  173. package/dist/ui/assets/git-rebase-Bc7atMaV.js +1 -0
  174. package/dist/ui/assets/github-dark-C-LZuMrd.js +1 -0
  175. package/dist/ui/assets/github-dark-default-DXG-b-1a.js +1 -0
  176. package/dist/ui/assets/github-dark-dimmed-Bx1FflLF.js +1 -0
  177. package/dist/ui/assets/github-dark-high-contrast-B_tTalzw.js +1 -0
  178. package/dist/ui/assets/github-light-EUqPIrTm.js +1 -0
  179. package/dist/ui/assets/github-light-default-BXViO-2h.js +1 -0
  180. package/dist/ui/assets/github-light-high-contrast-B68TUdTA.js +1 -0
  181. package/dist/ui/assets/gleam-CSRkHgEL.js +1 -0
  182. package/dist/ui/assets/glimmer-js-DXeTDPtW.js +1 -0
  183. package/dist/ui/assets/glimmer-ts-CEOoXHU4.js +1 -0
  184. package/dist/ui/assets/glsl-5-43-Gsg.js +1 -0
  185. package/dist/ui/assets/gn-ilITqXS6.js +1 -0
  186. package/dist/ui/assets/gnuplot-7GGW24-e.js +1 -0
  187. package/dist/ui/assets/go-BJwz_mda.js +1 -0
  188. package/dist/ui/assets/graphql-Bk7Ah1KA.js +1 -0
  189. package/dist/ui/assets/groovy-CacY0gHj.js +1 -0
  190. package/dist/ui/assets/gruvbox-dark-hard-C820rvS2.js +1 -0
  191. package/dist/ui/assets/gruvbox-dark-medium-BPjhmG05.js +1 -0
  192. package/dist/ui/assets/gruvbox-dark-soft-MrdJrrXF.js +1 -0
  193. package/dist/ui/assets/gruvbox-light-hard-BC_s9l72.js +1 -0
  194. package/dist/ui/assets/gruvbox-light-medium-BAWPOn9u.js +1 -0
  195. package/dist/ui/assets/gruvbox-light-soft-BSMLrYjP.js +1 -0
  196. package/dist/ui/assets/hack-DUHz4rCJ.js +1 -0
  197. package/dist/ui/assets/haml-BPCuuTPR.js +1 -0
  198. package/dist/ui/assets/handlebars-CHxmUsnU.js +1 -0
  199. package/dist/ui/assets/haskell-D8IpX4py.js +1 -0
  200. package/dist/ui/assets/haxe-OTjmBuCE.js +1 -0
  201. package/dist/ui/assets/hcl-Dh228itO.js +1 -0
  202. package/dist/ui/assets/hjson-CxZEssPk.js +1 -0
  203. package/dist/ui/assets/hlsl-Cvrh5tZx.js +1 -0
  204. package/dist/ui/assets/horizon-CE9ld1lL.js +1 -0
  205. package/dist/ui/assets/horizon-bright-Br1oVSNq.js +1 -0
  206. package/dist/ui/assets/houston-CsvMBhTu.js +1 -0
  207. package/dist/ui/assets/html-BBJqizz0.js +1 -0
  208. package/dist/ui/assets/html-derivative-ShTPCcKN.js +1 -0
  209. package/dist/ui/assets/http-VFTyziwA.js +1 -0
  210. package/dist/ui/assets/hurl-B8yxTa4r.js +1 -0
  211. package/dist/ui/assets/hxml-B0Qn7Nwc.js +1 -0
  212. package/dist/ui/assets/hy-CZbG8q4J.js +1 -0
  213. package/dist/ui/assets/imba-DsUTQ-LC.js +1 -0
  214. package/dist/ui/assets/ini-B5eOa1yu.js +1 -0
  215. package/dist/ui/assets/java-BZ5DAgJZ.js +1 -0
  216. package/dist/ui/assets/javascript-C_zuIEaC.js +1 -0
  217. package/dist/ui/assets/jinja-DWd6xfNr.js +1 -0
  218. package/dist/ui/assets/jison-BbY63d1V.js +1 -0
  219. package/dist/ui/assets/json-C4DnajZs.js +1 -0
  220. package/dist/ui/assets/json5-BR5RXkoi.js +1 -0
  221. package/dist/ui/assets/jsonc-CYpm1nAK.js +1 -0
  222. package/dist/ui/assets/jsonl-CmCQp5Yx.js +1 -0
  223. package/dist/ui/assets/jsonnet-CJTPZ8u_.js +1 -0
  224. package/dist/ui/assets/jssm-DXw9l8Rf.js +1 -0
  225. package/dist/ui/assets/jsx-C4AACieZ.js +1 -0
  226. package/dist/ui/assets/julia-sRu7EFMW.js +1 -0
  227. package/dist/ui/assets/just-DpZ9Sx1v.js +1 -0
  228. package/dist/ui/assets/kanagawa-dragon-CXtmUGW6.js +1 -0
  229. package/dist/ui/assets/kanagawa-lotus-BN08jTvb.js +1 -0
  230. package/dist/ui/assets/kanagawa-wave-CTweb8Dz.js +1 -0
  231. package/dist/ui/assets/kdl-CsD5j6eV.js +1 -0
  232. package/dist/ui/assets/kotlin-DhhofPvG.js +1 -0
  233. package/dist/ui/assets/kusto-BUv0MjJC.js +1 -0
  234. package/dist/ui/assets/laserwave-C_8bwKvT.js +1 -0
  235. package/dist/ui/assets/latex-B6a_uum7.js +1 -0
  236. package/dist/ui/assets/lean-CewbzKMR.js +1 -0
  237. package/dist/ui/assets/less-DVTAwKKz.js +1 -0
  238. package/dist/ui/assets/light-plus-DVQuIRkW.js +1 -0
  239. package/dist/ui/assets/liquid-B2sVpjjr.js +1 -0
  240. package/dist/ui/assets/llvm-Cm23YOpf.js +1 -0
  241. package/dist/ui/assets/log-BNLmms1o.js +1 -0
  242. package/dist/ui/assets/logo-Cluzi2Zq.js +1 -0
  243. package/dist/ui/assets/lua-DxJJll61.js +1 -0
  244. package/dist/ui/assets/luau-CNKltnaQ.js +1 -0
  245. package/dist/ui/assets/make-Dixweg8N.js +1 -0
  246. package/dist/ui/assets/markdown-BYOwaDjH.js +1 -0
  247. package/dist/ui/assets/marko-Dx8mw-Wx.js +1 -0
  248. package/dist/ui/assets/material-theme-Bm3Qr25_.js +1 -0
  249. package/dist/ui/assets/material-theme-darker-2IIEA8gg.js +1 -0
  250. package/dist/ui/assets/material-theme-lighter-uhdI0v04.js +1 -0
  251. package/dist/ui/assets/material-theme-ocean-CHQ94UKr.js +1 -0
  252. package/dist/ui/assets/material-theme-palenight-B5W6OYN7.js +1 -0
  253. package/dist/ui/assets/matlab-D7qyCx1q.js +1 -0
  254. package/dist/ui/assets/mdc-vNKeXEwR.js +1 -0
  255. package/dist/ui/assets/mdx-DQZ5AkYe.js +1 -0
  256. package/dist/ui/assets/mermaid-Bk4SNUv9.js +1 -0
  257. package/dist/ui/assets/min-dark-BSWPekZh.js +1 -0
  258. package/dist/ui/assets/min-light-DDpmG2fV.js +1 -0
  259. package/dist/ui/assets/mipsasm-BMqwQI7S.js +1 -0
  260. package/dist/ui/assets/mojo-BgCJLMeH.js +1 -0
  261. package/dist/ui/assets/monokai-CdkpiU2Y.js +1 -0
  262. package/dist/ui/assets/moonbit-CaWjb8XO.js +1 -0
  263. package/dist/ui/assets/move-B1IS1UjX.js +1 -0
  264. package/dist/ui/assets/narrat-_X_XdTYD.js +1 -0
  265. package/dist/ui/assets/nextflow-Bbiyy34d.js +1 -0
  266. package/dist/ui/assets/nextflow-groovy-Dc_ddanL.js +1 -0
  267. package/dist/ui/assets/nginx-DScQAGLT.js +1 -0
  268. package/dist/ui/assets/night-owl-DhmEMT88.js +1 -0
  269. package/dist/ui/assets/night-owl-light-eJ-hLW7d.js +1 -0
  270. package/dist/ui/assets/nim-lAJch9uT.js +1 -0
  271. package/dist/ui/assets/nix-IvuFDN5E.js +1 -0
  272. package/dist/ui/assets/nord-Cb4Vim4T.js +1 -0
  273. package/dist/ui/assets/nushell-DcLAeLz5.js +1 -0
  274. package/dist/ui/assets/objective-c-D1A_Heim.js +1 -0
  275. package/dist/ui/assets/objective-cpp-BsSzOQcm.js +1 -0
  276. package/dist/ui/assets/ocaml-O90oeIOV.js +1 -0
  277. package/dist/ui/assets/odin-B1RWQWA5.js +1 -0
  278. package/dist/ui/assets/one-dark-pro-CLwyXe_n.js +1 -0
  279. package/dist/ui/assets/one-light-D7Lr4KcI.js +1 -0
  280. package/dist/ui/assets/openscad-BUDT5pXO.js +1 -0
  281. package/dist/ui/assets/pascal-4ZHwLPI5.js +1 -0
  282. package/dist/ui/assets/perl-C_GkVo_E.js +1 -0
  283. package/dist/ui/assets/php-DziV3K6J.js +1 -0
  284. package/dist/ui/assets/pierre-dark-CpLgRqie.js +1 -0
  285. package/dist/ui/assets/pierre-dark-protanopia-deuteranopia-B35FxJx-.js +1 -0
  286. package/dist/ui/assets/pierre-dark-soft-kZQmAZld.js +1 -0
  287. package/dist/ui/assets/pierre-dark-tritanopia-CpjhbsIL.js +1 -0
  288. package/dist/ui/assets/pierre-dark-vibrant-CpQYzh95.js +1 -0
  289. package/dist/ui/assets/pierre-light-CoaEpmwp.js +1 -0
  290. package/dist/ui/assets/pierre-light-protanopia-deuteranopia-0fSaH845.js +1 -0
  291. package/dist/ui/assets/pierre-light-soft-lWLdNTOI.js +1 -0
  292. package/dist/ui/assets/pierre-light-tritanopia-CEbqgOJL.js +1 -0
  293. package/dist/ui/assets/pierre-light-vibrant-D80Fkn33.js +1 -0
  294. package/dist/ui/assets/pkl-ot-7Btpt.js +1 -0
  295. package/dist/ui/assets/plastic-DQwYfKfQ.js +1 -0
  296. package/dist/ui/assets/plsql-DGHpHOYJ.js +1 -0
  297. package/dist/ui/assets/po-BiJDBrnU.js +1 -0
  298. package/dist/ui/assets/poimandres-DRFjx7u4.js +1 -0
  299. package/dist/ui/assets/polar-C7UOKdEL.js +1 -0
  300. package/dist/ui/assets/postcss-BXeXVLqQ.js +1 -0
  301. package/dist/ui/assets/powerquery-DNMTfnFr.js +1 -0
  302. package/dist/ui/assets/powershell-DshXNtvi.js +1 -0
  303. package/dist/ui/assets/prisma-BsRQq5mF.js +1 -0
  304. package/dist/ui/assets/prolog-iXnhIJG7.js +1 -0
  305. package/dist/ui/assets/proto-DB4EqR-F.js +1 -0
  306. package/dist/ui/assets/pug-z75UIWVK.js +1 -0
  307. package/dist/ui/assets/puppet-CDv2pdJW.js +1 -0
  308. package/dist/ui/assets/purescript-9MfHhQsQ.js +1 -0
  309. package/dist/ui/assets/python-gzcpVVnB.js +1 -0
  310. package/dist/ui/assets/qml-Cmm4coz1.js +1 -0
  311. package/dist/ui/assets/qmldir-DCQb3MpD.js +1 -0
  312. package/dist/ui/assets/qss-Fe1Jh2GI.js +1 -0
  313. package/dist/ui/assets/r-Brd0axBE.js +1 -0
  314. package/dist/ui/assets/racket-DcIDlBhZ.js +1 -0
  315. package/dist/ui/assets/raku-B3gFvitq.js +1 -0
  316. package/dist/ui/assets/razor-DSbwmoiu.js +1 -0
  317. package/dist/ui/assets/red-CJ3rzSJv.js +1 -0
  318. package/dist/ui/assets/reg-CRGYupPL.js +1 -0
  319. package/dist/ui/assets/regexp-Bs3Uk-pY.js +1 -0
  320. package/dist/ui/assets/rel-BtDbiS_P.js +1 -0
  321. package/dist/ui/assets/review-payload-CbwCBKB1.js +1580 -0
  322. package/dist/ui/assets/riscv-Ckw8ddFX.js +1 -0
  323. package/dist/ui/assets/ron-VUp2lXgN.js +1 -0
  324. package/dist/ui/assets/rose-pine-BthvhNj6.js +1 -0
  325. package/dist/ui/assets/rose-pine-dawn-Dg85fqjY.js +1 -0
  326. package/dist/ui/assets/rose-pine-moon-hon4tzzS.js +1 -0
  327. package/dist/ui/assets/rosmsg-CAekHB0j.js +1 -0
  328. package/dist/ui/assets/rst-ChIyKpUC.js +1 -0
  329. package/dist/ui/assets/ruby-BdAmvOMO.js +1 -0
  330. package/dist/ui/assets/rust-Cfkwpbl8.js +1 -0
  331. package/dist/ui/assets/sas-DpXn8hc5.js +1 -0
  332. package/dist/ui/assets/sass-DXrisJhu.js +1 -0
  333. package/dist/ui/assets/scala-DKOlJaKm.js +1 -0
  334. package/dist/ui/assets/scheme-DQCgrYNe.js +1 -0
  335. package/dist/ui/assets/scss-atX1Uuef.js +1 -0
  336. package/dist/ui/assets/sdbl-bTVj8UrX.js +1 -0
  337. package/dist/ui/assets/shaderlab-TOUzSsQk.js +1 -0
  338. package/dist/ui/assets/shellscript-BqgcAeMK.js +1 -0
  339. package/dist/ui/assets/shellsession-DfQSMRN5.js +1 -0
  340. package/dist/ui/assets/slack-dark-DnToyrRv.js +1 -0
  341. package/dist/ui/assets/slack-ochin-B2OO5cIa.js +1 -0
  342. package/dist/ui/assets/smalltalk-B16xEiuN.js +1 -0
  343. package/dist/ui/assets/snazzy-light-4G7pJPwS.js +1 -0
  344. package/dist/ui/assets/solarized-dark-DV17i1UV.js +1 -0
  345. package/dist/ui/assets/solarized-light-DSh2HLQt.js +1 -0
  346. package/dist/ui/assets/solidity-CKzVLygQ.js +1 -0
  347. package/dist/ui/assets/soy-DzP7zZTB.js +1 -0
  348. package/dist/ui/assets/sparql-D_iOobhT.js +1 -0
  349. package/dist/ui/assets/splunk-BC2Px7Mm.js +1 -0
  350. package/dist/ui/assets/sql-gmaLk66z.js +1 -0
  351. package/dist/ui/assets/ssh-config-BgfXC-Er.js +1 -0
  352. package/dist/ui/assets/stata-CJ0YTMcV.js +1 -0
  353. package/dist/ui/assets/stylus-B6D30XZt.js +1 -0
  354. package/dist/ui/assets/surrealql-LH7FciQz.js +1 -0
  355. package/dist/ui/assets/svelte-BME2PU6V.js +1 -0
  356. package/dist/ui/assets/swift-DonLKvLd.js +1 -0
  357. package/dist/ui/assets/synthwave-84-nFMaYfgc.js +1 -0
  358. package/dist/ui/assets/system-verilog-DJ5XKQeo.js +1 -0
  359. package/dist/ui/assets/systemd-BxMlprV5.js +1 -0
  360. package/dist/ui/assets/talonscript-CohzipZa.js +1 -0
  361. package/dist/ui/assets/tasl-DMoTqEGO.js +1 -0
  362. package/dist/ui/assets/tcl-CZd0xW_V.js +1 -0
  363. package/dist/ui/assets/templ-DHBNIfYW.js +1 -0
  364. package/dist/ui/assets/terraform-DswuEJGm.js +1 -0
  365. package/dist/ui/assets/tex-C8-kPEzO.js +1 -0
  366. package/dist/ui/assets/tokyo-night-oM2G3aXe.js +1 -0
  367. package/dist/ui/assets/toml-CcmNWLt0.js +1 -0
  368. package/dist/ui/assets/ts-tags-CiewV0vR.js +1 -0
  369. package/dist/ui/assets/tsv-sltzmVWM.js +1 -0
  370. package/dist/ui/assets/tsx-CUYPqmnq.js +1 -0
  371. package/dist/ui/assets/turtle-ByJddavk.js +1 -0
  372. package/dist/ui/assets/twig-BTkvsl0b.js +1 -0
  373. package/dist/ui/assets/typescript-DDQMaPwj.js +1 -0
  374. package/dist/ui/assets/typespec-B88KGewJ.js +1 -0
  375. package/dist/ui/assets/typst-DI99ib-x.js +1 -0
  376. package/dist/ui/assets/v-DETTlOr0.js +1 -0
  377. package/dist/ui/assets/vala-zf12oZj6.js +1 -0
  378. package/dist/ui/assets/vb-Djn5o6TS.js +1 -0
  379. package/dist/ui/assets/verilog-CiiDBU1e.js +1 -0
  380. package/dist/ui/assets/vesper-D5bVUKB1.js +1 -0
  381. package/dist/ui/assets/vhdl-BroJfC0k.js +1 -0
  382. package/dist/ui/assets/viml-DvXPmvsu.js +1 -0
  383. package/dist/ui/assets/vitesse-black-fwtXNY1n.js +1 -0
  384. package/dist/ui/assets/vitesse-dark-BZCL-v6S.js +1 -0
  385. package/dist/ui/assets/vitesse-light-VbXTXTou.js +1 -0
  386. package/dist/ui/assets/vue-BH5SEWRH.js +1 -0
  387. package/dist/ui/assets/vue-html-BT7yeYez.js +1 -0
  388. package/dist/ui/assets/vue-vine-Cs5IN2rs.js +1 -0
  389. package/dist/ui/assets/vyper-CgoNMtux.js +1 -0
  390. package/dist/ui/assets/wasm-BnjxR4X6.js +1 -0
  391. package/dist/ui/assets/wasm-ByWQv1Qj.js +1 -0
  392. package/dist/ui/assets/wenyan-C8pVoKbM.js +1 -0
  393. package/dist/ui/assets/wgsl-BsKzXJz4.js +1 -0
  394. package/dist/ui/assets/wikitext-ClFFjSW2.js +1 -0
  395. package/dist/ui/assets/wit-DdvCle-K.js +1 -0
  396. package/dist/ui/assets/wolfram-DLL8P-h_.js +1 -0
  397. package/dist/ui/assets/workspace-app-B_BnSEHO.css +1 -0
  398. package/dist/ui/assets/workspace-app-DSFpnrIC.js +115 -0
  399. package/dist/ui/assets/xml-D3_1BEcO.js +1 -0
  400. package/dist/ui/assets/xsl-BBOCDn4Y.js +1 -0
  401. package/dist/ui/assets/yaml-lThBDT45.js +1 -0
  402. package/dist/ui/assets/zenscript-BnlCZFoB.js +1 -0
  403. package/dist/ui/assets/zig-CMLA9XwU.js +1 -0
  404. package/dist/ui/workspace-app.html +15 -0
  405. package/dist/user-config.js +228 -0
  406. package/dist/verification.js +74 -0
  407. package/dist/workspace-store.js +133 -0
  408. package/dist/workspaces.js +433 -0
  409. package/docs/adr/devspace-x-implementation-adrs.md +159 -0
  410. package/docs/agent-profile-schema.md +203 -0
  411. package/docs/artifact-exchange.md +44 -0
  412. package/docs/assets/devspace-logo-light.png +0 -0
  413. package/docs/assets/devspace-screenshot.png +0 -0
  414. package/docs/assets/v11-review-ui-after.png +0 -0
  415. package/docs/assets/v11-review-ui-before.png +0 -0
  416. package/docs/chatgpt-coding-workflow.md +215 -0
  417. package/docs/configuration.md +217 -0
  418. package/docs/gotchas.md +294 -0
  419. package/docs/local-agent-daemon.md +101 -0
  420. package/docs/security.md +197 -0
  421. package/docs/setup.md +174 -0
  422. package/examples/agents/claude-implementer.md +30 -0
  423. package/examples/agents/codex-explorer.md +27 -0
  424. package/examples/agents/codex-qa-tester.md +29 -0
  425. package/examples/agents/codex-worker.md +25 -0
  426. package/examples/agents/copilot-reviewer.md +25 -0
  427. package/examples/agents/cursor-agent-worker.md +26 -0
  428. package/examples/agents/grok-builder.md +10 -0
  429. package/examples/agents/opencode-explorer.md +27 -0
  430. package/examples/agents/pi-reviewer.md +27 -0
  431. package/package.json +102 -0
  432. package/schema/v1/hearth.schema.json +529 -0
  433. package/scripts/copy-dashboard.mjs +9 -0
  434. package/scripts/fix-node-pty-permissions.mjs +22 -0
  435. package/scripts/generate-config-schema.ts +9 -0
  436. package/skills/subagents/SKILL.md +57 -0
@@ -0,0 +1,472 @@
1
+ import { access, mkdir, readFile, readdir, realpath, stat, writeFile } from "node:fs/promises";
2
+ import { existsSync, realpathSync } from "node:fs";
3
+ import { spawn } from "node:child_process";
4
+ import { homedir } from "node:os";
5
+ import { basename, dirname, join, relative, resolve } from "node:path";
6
+ import { SandboxManager, } from "@anthropic-ai/sandbox-runtime";
7
+ import { createBashTool, createEditTool, createFindTool, createGrepTool, createLsTool, createReadTool, createWriteTool, } from "@earendil-works/pi-coding-agent";
8
+ import { assertAllowedPath, isPathInsideRoot } from "./roots.js";
9
+ import { terminateProcessTree } from "./process-platform.js";
10
+ const PI_NETWORK_ALLOWLIST = [
11
+ "npmjs.org",
12
+ "*.npmjs.org",
13
+ "registry.npmjs.org",
14
+ "registry.yarnpkg.com",
15
+ "pypi.org",
16
+ "*.pypi.org",
17
+ "files.pythonhosted.org",
18
+ "github.com",
19
+ "*.github.com",
20
+ "api.github.com",
21
+ "raw.githubusercontent.com",
22
+ "gitlab.com",
23
+ "*.gitlab.com",
24
+ "bitbucket.org",
25
+ "*.bitbucket.org",
26
+ "crates.io",
27
+ "*.crates.io",
28
+ "rubygems.org",
29
+ "*.rubygems.org",
30
+ ];
31
+ // Pi does not provide a built-in sandbox. Keep the provider-native sandbox
32
+ // small and fail closed when a command needs a registry or host that is not
33
+ // explicitly allowed here; the agent can report that limitation to the user.
34
+ let sandboxInitialization;
35
+ let windowsSandboxWorkspace;
36
+ let windowsSandboxQueue = Promise.resolve();
37
+ let sandboxSessionCount = 0;
38
+ let sandboxCommandCount = 0;
39
+ const sandboxCommandWaiters = new Set();
40
+ const sessionStates = new WeakMap();
41
+ export function createPiSandboxModeRef(value) {
42
+ return { value };
43
+ }
44
+ export function createPiSandboxExtension(workspace, modeRef) {
45
+ return (pi) => {
46
+ const localRead = createReadTool(workspace);
47
+ const restrictedRead = createReadTool(workspace, { operations: createReadOperations(workspace) });
48
+ pi.registerTool(dynamicTool(localRead, restrictedRead, modeRef));
49
+ const localWrite = createWriteTool(workspace);
50
+ const restrictedWrite = createWriteTool(workspace, { operations: createWriteOperations(workspace) });
51
+ pi.registerTool(dynamicTool(localWrite, restrictedWrite, modeRef, true));
52
+ const localEdit = createEditTool(workspace);
53
+ const restrictedEdit = createEditTool(workspace, { operations: createEditOperations(workspace) });
54
+ pi.registerTool(dynamicTool(localEdit, restrictedEdit, modeRef, true));
55
+ const localGrep = createGrepTool(workspace);
56
+ const restrictedGrep = createGrepTool(workspace, { operations: createGrepOperations(workspace) });
57
+ pi.registerTool(dynamicTool(localGrep, restrictedGrep, modeRef));
58
+ const localFind = createFindTool(workspace);
59
+ const restrictedFind = createFindTool(workspace, { operations: createFindOperations(workspace) });
60
+ pi.registerTool(dynamicTool(localFind, restrictedFind, modeRef));
61
+ const localLs = createLsTool(workspace);
62
+ const restrictedLs = createLsTool(workspace, { operations: createLsOperations(workspace) });
63
+ pi.registerTool(dynamicTool(localLs, restrictedLs, modeRef));
64
+ const localBash = createBashTool(workspace);
65
+ const restrictedBash = createBashTool(workspace, {
66
+ operations: createSandboxedBashOperations(),
67
+ });
68
+ pi.registerTool(dynamicTool(localBash, restrictedBash, modeRef, true));
69
+ };
70
+ }
71
+ export function createPiSandboxConfig(workspace) {
72
+ const resolvedWorkspace = workspace ? resolveWorkspace(workspace) : undefined;
73
+ return {
74
+ network: {
75
+ allowedDomains: [...PI_NETWORK_ALLOWLIST],
76
+ deniedDomains: [],
77
+ strictAllowlist: true,
78
+ },
79
+ filesystem: {
80
+ denyRead: protectedHomePaths(),
81
+ allowWrite: process.platform === "win32" && resolvedWorkspace ? [resolvedWorkspace] : [],
82
+ denyWrite: resolvedWorkspace
83
+ ? [join(resolvedWorkspace, ".env"), join(resolvedWorkspace, ".env.local")]
84
+ : [],
85
+ allowRead: [],
86
+ },
87
+ };
88
+ }
89
+ export async function registerPiSandboxSession(session, workspace, modeRef, writeMode) {
90
+ const state = {
91
+ workspace: resolveWorkspace(workspace),
92
+ modeRef,
93
+ acquired: false,
94
+ };
95
+ sessionStates.set(session, state);
96
+ if (writeMode !== "full_access") {
97
+ await acquirePiSandbox(state);
98
+ }
99
+ }
100
+ export async function updatePiSandboxSession(session, workspace, writeMode) {
101
+ const state = sessionStates.get(session);
102
+ if (!state)
103
+ return;
104
+ state.workspace = resolveWorkspace(workspace);
105
+ state.modeRef.value = writeMode;
106
+ if (writeMode !== "full_access" && !state.acquired) {
107
+ await acquirePiSandbox(state);
108
+ }
109
+ }
110
+ export async function releasePiSandboxSession(session) {
111
+ const state = sessionStates.get(session);
112
+ if (!state)
113
+ return;
114
+ sessionStates.delete(session);
115
+ if (!state.acquired)
116
+ return;
117
+ state.acquired = false;
118
+ sandboxSessionCount = Math.max(0, sandboxSessionCount - 1);
119
+ if (sandboxSessionCount !== 0)
120
+ return;
121
+ await waitForSandboxCommands();
122
+ if (sandboxSessionCount !== 0)
123
+ return;
124
+ const reset = async () => {
125
+ try {
126
+ await SandboxManager.reset();
127
+ }
128
+ finally {
129
+ sandboxInitialization = undefined;
130
+ windowsSandboxWorkspace = undefined;
131
+ }
132
+ };
133
+ if (process.platform === "win32")
134
+ await enqueueWindowsSandbox(reset);
135
+ else
136
+ await reset();
137
+ }
138
+ function dynamicTool(unrestricted, restricted, modeRef, writeCapable = false) {
139
+ return {
140
+ ...restricted,
141
+ execute: (...args) => {
142
+ if (writeCapable && modeRef.value === "read_only") {
143
+ throw new Error("Pi read-only mode does not allow write-capable tools.");
144
+ }
145
+ return (modeRef.value === "full_access" ? unrestricted : restricted).execute(...args);
146
+ },
147
+ };
148
+ }
149
+ function createReadOperations(workspace) {
150
+ return {
151
+ readFile: async (path) => readFile(await assertPiWorkspacePath(path, workspace)),
152
+ access: async (path) => access(await assertPiWorkspacePath(path, workspace)),
153
+ };
154
+ }
155
+ function createWriteOperations(workspace) {
156
+ return {
157
+ writeFile: async (path, content) => writeFile(await assertPiWorkspacePath(path, workspace, true), content),
158
+ mkdir: async (path) => {
159
+ await mkdir(await assertPiWorkspacePath(path, workspace, true), { recursive: true });
160
+ },
161
+ };
162
+ }
163
+ function createEditOperations(workspace) {
164
+ return {
165
+ readFile: async (path) => readFile(await assertPiWorkspacePath(path, workspace)),
166
+ writeFile: async (path, content) => writeFile(await assertPiWorkspacePath(path, workspace, true), content),
167
+ access: async (path) => access(await assertPiWorkspacePath(path, workspace, true)),
168
+ };
169
+ }
170
+ function createGrepOperations(workspace) {
171
+ return {
172
+ isDirectory: async (path) => (await stat(await assertPiWorkspacePath(path, workspace))).isDirectory(),
173
+ readFile: async (path) => (await readFile(await assertPiWorkspacePath(path, workspace))).toString("utf8"),
174
+ };
175
+ }
176
+ function createFindOperations(workspace) {
177
+ return {
178
+ exists: async (path) => {
179
+ try {
180
+ await access(await assertPiWorkspacePath(path, workspace));
181
+ return true;
182
+ }
183
+ catch {
184
+ return false;
185
+ }
186
+ },
187
+ glob: async (pattern, cwd, options) => {
188
+ const searchRoot = await assertPiWorkspacePath(cwd, workspace);
189
+ const matcher = globToRegExp(pattern);
190
+ const results = [];
191
+ const ignoredDirectories = new Set([".git", "node_modules"]);
192
+ const visit = async (directory) => {
193
+ if (results.length >= options.limit)
194
+ return;
195
+ for (const entry of await readdir(directory, { withFileTypes: true })) {
196
+ if (entry.isSymbolicLink())
197
+ continue;
198
+ if (entry.isDirectory() && ignoredDirectories.has(entry.name))
199
+ continue;
200
+ const absolutePath = join(directory, entry.name);
201
+ const relativePath = relative(searchRoot, absolutePath).split("\\").join("/");
202
+ const candidate = pattern.includes("/") ? relativePath : basename(relativePath);
203
+ if (matcher.test(candidate))
204
+ results.push(absolutePath);
205
+ if (entry.isDirectory())
206
+ await visit(absolutePath);
207
+ if (results.length >= options.limit)
208
+ return;
209
+ }
210
+ };
211
+ await visit(searchRoot);
212
+ return results;
213
+ },
214
+ };
215
+ }
216
+ function createLsOperations(workspace) {
217
+ return {
218
+ exists: async (path) => {
219
+ try {
220
+ await access(await assertPiWorkspacePath(path, workspace));
221
+ return true;
222
+ }
223
+ catch {
224
+ return false;
225
+ }
226
+ },
227
+ stat: async (path) => stat(await assertPiWorkspacePath(path, workspace)),
228
+ readdir: async (path) => readdir(await assertPiWorkspacePath(path, workspace)),
229
+ };
230
+ }
231
+ function createSandboxedBashOperations() {
232
+ return {
233
+ exec: (command, cwd, options) => withSandboxCommand(async () => {
234
+ if (process.platform === "win32") {
235
+ return enqueueWindowsSandbox(async () => {
236
+ await ensureWindowsSandbox(cwd);
237
+ return runSandboxedCommand(command, cwd, options);
238
+ });
239
+ }
240
+ await ensureSandboxInitialized();
241
+ return runSandboxedCommand(command, cwd, options);
242
+ }),
243
+ };
244
+ }
245
+ async function acquirePiSandbox(state) {
246
+ if (state.acquired)
247
+ return;
248
+ state.acquired = true;
249
+ sandboxSessionCount += 1;
250
+ try {
251
+ if (process.platform === "win32") {
252
+ // Windows sandbox-runtime has process-global policy state. Serialize
253
+ // workspace changes with command execution so one session cannot reset
254
+ // another session's policy while its Bash command is running.
255
+ await enqueueWindowsSandbox(() => ensureWindowsSandbox(state.workspace));
256
+ }
257
+ else {
258
+ await ensureSandboxInitialized();
259
+ }
260
+ }
261
+ catch (error) {
262
+ state.acquired = false;
263
+ sandboxSessionCount = Math.max(0, sandboxSessionCount - 1);
264
+ throw error;
265
+ }
266
+ }
267
+ async function ensureSandboxInitialized() {
268
+ if (!SandboxManager.isSupportedPlatform()) {
269
+ throw new Error(`Pi allowed mode requires a sandbox, but ${process.platform} is not supported by sandbox-runtime.`);
270
+ }
271
+ if (!sandboxInitialization) {
272
+ sandboxInitialization = SandboxManager.initialize(createPiSandboxConfig()).catch((error) => {
273
+ sandboxInitialization = undefined;
274
+ throw new Error(`Pi allowed mode could not initialize its sandbox: ${error instanceof Error ? error.message : String(error)}`);
275
+ });
276
+ }
277
+ await sandboxInitialization;
278
+ }
279
+ async function ensureWindowsSandbox(workspace) {
280
+ const resolvedWorkspace = resolveWorkspace(workspace);
281
+ if (windowsSandboxWorkspace === resolvedWorkspace && sandboxInitialization) {
282
+ await sandboxInitialization;
283
+ return;
284
+ }
285
+ if (sandboxInitialization) {
286
+ try {
287
+ await SandboxManager.reset();
288
+ }
289
+ finally {
290
+ sandboxInitialization = undefined;
291
+ windowsSandboxWorkspace = undefined;
292
+ }
293
+ }
294
+ sandboxInitialization = SandboxManager.initialize(createPiSandboxConfig(resolvedWorkspace)).catch((error) => {
295
+ sandboxInitialization = undefined;
296
+ windowsSandboxWorkspace = undefined;
297
+ throw new Error(`Pi allowed mode could not initialize its Windows sandbox: ${error instanceof Error ? error.message : String(error)}`);
298
+ });
299
+ await sandboxInitialization;
300
+ windowsSandboxWorkspace = resolvedWorkspace;
301
+ }
302
+ function enqueueWindowsSandbox(operation) {
303
+ const next = windowsSandboxQueue.then(operation, operation);
304
+ windowsSandboxQueue = next.then(() => undefined, () => undefined);
305
+ return next;
306
+ }
307
+ async function runSandboxedCommand(command, cwd, options) {
308
+ if (options.signal?.aborted)
309
+ throw new Error("aborted");
310
+ const workspace = resolveWorkspace(cwd);
311
+ const customConfig = {
312
+ filesystem: createPiSandboxFilesystem(workspace),
313
+ };
314
+ const wrapped = await SandboxManager.wrapWithSandboxArgv(command, undefined, process.platform === "win32" ? undefined : customConfig, options.signal, workspace);
315
+ try {
316
+ return await spawnSandboxedCommand(wrapped.argv, wrapped.env, workspace, options);
317
+ }
318
+ finally {
319
+ SandboxManager.cleanupAfterCommand();
320
+ }
321
+ }
322
+ function spawnSandboxedCommand(argv, environment, cwd, options) {
323
+ const [executable, ...args] = argv;
324
+ if (!executable)
325
+ throw new Error("sandbox-runtime returned an empty command");
326
+ return new Promise((resolveResult, reject) => {
327
+ const child = spawn(executable, args, {
328
+ cwd,
329
+ env: { ...environment, ...options.env },
330
+ stdio: ["ignore", "pipe", "pipe"],
331
+ detached: process.platform !== "win32",
332
+ shell: false,
333
+ windowsHide: true,
334
+ });
335
+ let timedOut = false;
336
+ let settled = false;
337
+ let timer;
338
+ const detached = process.platform !== "win32";
339
+ const finish = (callback) => {
340
+ if (settled)
341
+ return;
342
+ settled = true;
343
+ if (timer)
344
+ clearTimeout(timer);
345
+ options.signal?.removeEventListener("abort", onAbort);
346
+ callback();
347
+ };
348
+ const kill = () => terminateProcessTree(child, "SIGKILL", detached);
349
+ const onAbort = () => kill();
350
+ options.signal?.addEventListener("abort", onAbort, { once: true });
351
+ if (options.timeout !== undefined && options.timeout > 0) {
352
+ timer = setTimeout(() => {
353
+ timedOut = true;
354
+ kill();
355
+ }, options.timeout * 1000);
356
+ }
357
+ child.stdout?.on("data", options.onData);
358
+ child.stderr?.on("data", options.onData);
359
+ child.once("error", (error) => finish(() => reject(error)));
360
+ child.once("close", (exitCode) => {
361
+ finish(() => {
362
+ if (options.signal?.aborted)
363
+ reject(new Error("aborted"));
364
+ else if (timedOut)
365
+ reject(new Error(`timeout:${options.timeout}`));
366
+ else
367
+ resolveResult({ exitCode });
368
+ });
369
+ });
370
+ });
371
+ }
372
+ function createPiSandboxFilesystem(workspace) {
373
+ return {
374
+ denyRead: protectedHomePaths(),
375
+ allowWrite: [workspace],
376
+ denyWrite: [join(workspace, ".env"), join(workspace, ".env.local")],
377
+ allowRead: [],
378
+ };
379
+ }
380
+ function protectedHomePaths() {
381
+ const home = homedir();
382
+ return [
383
+ join(home, ".ssh"),
384
+ join(home, ".aws"),
385
+ join(home, ".gnupg"),
386
+ join(home, ".config", "gcloud"),
387
+ join(home, ".netrc"),
388
+ join(home, ".npmrc"),
389
+ ];
390
+ }
391
+ async function assertPiWorkspacePath(path, workspace, _forWrite = false) {
392
+ const resolvedWorkspace = resolveWorkspace(workspace);
393
+ const absolutePath = resolve(path);
394
+ const { boundaryPath, suffix } = await resolveExistingBoundary(absolutePath);
395
+ if (!isPathInsideRoot(boundaryPath, resolvedWorkspace)) {
396
+ assertAllowedPath(boundaryPath, [resolvedWorkspace]);
397
+ }
398
+ const operationPath = suffix ? resolve(boundaryPath, suffix) : boundaryPath;
399
+ if (!isPathInsideRoot(operationPath, resolvedWorkspace)) {
400
+ assertAllowedPath(operationPath, [resolvedWorkspace]);
401
+ }
402
+ return operationPath;
403
+ }
404
+ async function resolveExistingBoundary(path) {
405
+ let candidate = path;
406
+ for (;;) {
407
+ try {
408
+ return {
409
+ boundaryPath: await realpath(candidate),
410
+ suffix: relative(candidate, path),
411
+ };
412
+ }
413
+ catch {
414
+ const parent = dirname(candidate);
415
+ if (parent === candidate)
416
+ return { boundaryPath: candidate, suffix: relative(candidate, path) };
417
+ candidate = parent;
418
+ }
419
+ }
420
+ }
421
+ async function withSandboxCommand(operation) {
422
+ sandboxCommandCount += 1;
423
+ try {
424
+ return await operation();
425
+ }
426
+ finally {
427
+ sandboxCommandCount = Math.max(0, sandboxCommandCount - 1);
428
+ if (sandboxCommandCount === 0) {
429
+ for (const resolveWaiter of sandboxCommandWaiters)
430
+ resolveWaiter();
431
+ sandboxCommandWaiters.clear();
432
+ }
433
+ }
434
+ }
435
+ function waitForSandboxCommands() {
436
+ if (sandboxCommandCount === 0)
437
+ return Promise.resolve();
438
+ return new Promise((resolveWaiter) => sandboxCommandWaiters.add(resolveWaiter));
439
+ }
440
+ function resolveWorkspace(workspace) {
441
+ const absolute = resolve(workspace);
442
+ if (!existsSync(absolute))
443
+ throw new Error(`Pi workspace does not exist: ${workspace}`);
444
+ return realpathSync(absolute);
445
+ }
446
+ function globToRegExp(pattern) {
447
+ const normalized = pattern.replaceAll("\\", "/").replace(/^\.\//, "");
448
+ let source = "^";
449
+ for (let index = 0; index < normalized.length; index += 1) {
450
+ const character = normalized[index];
451
+ if (character === "*" && normalized[index + 1] === "*") {
452
+ index += 1;
453
+ if (normalized[index + 1] === "/") {
454
+ index += 1;
455
+ source += "(?:.*/)?";
456
+ }
457
+ else {
458
+ source += ".*";
459
+ }
460
+ }
461
+ else if (character === "*") {
462
+ source += "[^/]*";
463
+ }
464
+ else if (character === "?") {
465
+ source += "[^/]";
466
+ }
467
+ else {
468
+ source += character.replace(/[\\^$.*+?()[\]{}|]/g, "\\$&");
469
+ }
470
+ }
471
+ return new RegExp(`${source}$`);
472
+ }