@henlii/pidance 0.2.37 → 0.2.40

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 (334) hide show
  1. package/.next/BUILD_ID +1 -1
  2. package/.next/app-path-routes-manifest.json +12 -9
  3. package/.next/build-manifest.json +6 -6
  4. package/.next/prerender-manifest.json +18 -3
  5. package/.next/required-server-files.json +29 -9
  6. package/.next/routes-manifest.json +20 -0
  7. package/.next/server/app/_global-error/page.js +2 -3
  8. package/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
  9. package/.next/server/app/_global-error.html +1 -1
  10. package/.next/server/app/_global-error.meta +16 -5
  11. package/.next/server/app/_global-error.rsc +3 -3
  12. package/.next/server/app/_global-error.segments/_full.segment.rsc +3 -3
  13. package/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +16 -1
  14. package/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  15. package/.next/server/app/_not-found/page.js +1 -2
  16. package/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  17. package/.next/server/app/_not-found.html +1 -1
  18. package/.next/server/app/_not-found.meta +16 -5
  19. package/.next/server/app/_not-found.rsc +7 -7
  20. package/.next/server/app/_not-found.segments/_full.segment.rsc +7 -7
  21. package/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +20 -1
  22. package/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -2
  23. package/.next/server/app/api/about/route.js +1 -1
  24. package/.next/server/app/api/agent/[id]/bash-output/route.js +1 -1
  25. package/.next/server/app/api/agent/[id]/events/route.js +2 -2
  26. package/.next/server/app/api/agent/[id]/route.js +1 -1
  27. package/.next/server/app/api/agent/new/route.js +1 -1
  28. package/.next/server/app/api/agent/running/events/route.js +2 -2
  29. package/.next/server/app/api/agent/running/route.js +1 -1
  30. package/.next/server/app/api/agent/submissions/[submissionId]/route.js +1 -1
  31. package/.next/server/app/api/agent-settings/route.js +2 -2
  32. package/.next/server/app/api/attachments/route.js +1 -1
  33. package/.next/server/app/api/auth/all-providers/route.js +1 -1
  34. package/.next/server/app/api/auth/api-key/[provider]/route.js +1 -1
  35. package/.next/server/app/api/auth/login/[provider]/route.js +2 -2
  36. package/.next/server/app/api/auth/logout/[provider]/route.js +1 -1
  37. package/.next/server/app/api/auth/providers/route.js +1 -1
  38. package/.next/server/app/api/auth/ui-session/route.js +1 -1
  39. package/.next/server/app/api/auth/ui-sessions/[id]/route.js +1 -1
  40. package/.next/server/app/api/auth/ui-sessions/route.js +1 -1
  41. package/.next/server/app/api/cwd/browse/route.js +1 -1
  42. package/.next/server/app/api/cwd/create/route.js +1 -1
  43. package/.next/server/app/api/cwd/validate/route.js +1 -1
  44. package/.next/server/app/api/default-cwd/route.js +1 -1
  45. package/.next/server/app/api/file-index/route.js +1 -1
  46. package/.next/server/app/api/files/[...path]/route.js +3 -3
  47. package/.next/server/app/api/files/save-as/route.js +1 -1
  48. package/.next/server/app/api/git/diff/route.js +1 -1
  49. package/.next/server/app/api/git/status/route.js +1 -1
  50. package/.next/server/app/api/home/route.js +1 -1
  51. package/.next/server/app/api/message-media/route.js +1 -1
  52. package/.next/server/app/api/models/enabled/route.js +1 -0
  53. package/.next/server/app/api/models/enabled/route_client-reference-manifest.js +1 -0
  54. package/.next/server/app/api/models/refresh/route.js +1 -0
  55. package/.next/server/app/api/models/refresh/route_client-reference-manifest.js +1 -0
  56. package/.next/server/app/api/models/route.js +1 -1
  57. package/.next/server/app/api/models-config/raw/route.js +1 -1
  58. package/.next/server/app/api/models-config/route.js +1 -1
  59. package/.next/server/app/api/models-config/test/route.js +1 -1
  60. package/.next/server/app/api/plugins/route.js +1 -1
  61. package/.next/server/app/api/plugins/search/route.js +1 -1
  62. package/.next/server/app/api/plugins/updates/route.js +2 -1
  63. package/.next/server/app/api/preferences/route.js +1 -1
  64. package/.next/server/app/api/project-assets/route.js +2 -2
  65. package/.next/server/app/api/prompts/route.js +1 -1
  66. package/.next/server/app/api/pty/route.js +4 -3
  67. package/.next/server/app/api/sessions/[id]/archive/route.js +1 -1
  68. package/.next/server/app/api/sessions/[id]/auto-name/route.js +1 -1
  69. package/.next/server/app/api/sessions/[id]/command-entry/route.js +1 -1
  70. package/.next/server/app/api/sessions/[id]/context/route.js +1 -1
  71. package/.next/server/app/api/sessions/[id]/entries/[entryId]/thinking/route.js +1 -1
  72. package/.next/server/app/api/sessions/[id]/export/route.js +1 -1
  73. package/.next/server/app/api/sessions/[id]/info/route.js +1 -1
  74. package/.next/server/app/api/sessions/[id]/lock/route.js +1 -0
  75. package/.next/server/app/api/sessions/[id]/lock/route_client-reference-manifest.js +1 -0
  76. package/.next/server/app/api/sessions/[id]/outline/route.js +1 -1
  77. package/.next/server/app/api/sessions/[id]/route.js +1 -1
  78. package/.next/server/app/api/sessions/[id]/state/route.js +1 -1
  79. package/.next/server/app/api/sessions/[id]/tool-results/[toolCallId]/route.js +1 -1
  80. package/.next/server/app/api/sessions/route.js +1 -1
  81. package/.next/server/app/api/sessions/search/route.js +1 -1
  82. package/.next/server/app/api/settings/raw/route.js +2 -2
  83. package/.next/server/app/api/settings/remote/route.js +1 -1
  84. package/.next/server/app/api/skills/check/route.js +1 -1
  85. package/.next/server/app/api/skills/install/route.js +1 -1
  86. package/.next/server/app/api/skills/route.js +2 -2
  87. package/.next/server/app/api/skills/search/route.js +1 -1
  88. package/.next/server/app/api/skills/update/route.js +1 -1
  89. package/.next/server/app/api/subagent-runs/route.js +1 -1
  90. package/.next/server/app/api/update/apply/route.js +2 -2
  91. package/.next/server/app/api/update/check/route.js +1 -1
  92. package/.next/server/app/icon.png/route.js +1 -1
  93. package/.next/server/app/index.html +1 -1
  94. package/.next/server/app/index.meta +11 -4
  95. package/.next/server/app/index.rsc +5 -5
  96. package/.next/server/app/index.segments/__PAGE__.segment.rsc +19 -3
  97. package/.next/server/app/index.segments/_full.segment.rsc +5 -5
  98. package/.next/server/app/index.segments/_tree.segment.rsc +2 -2
  99. package/.next/server/app/page.js +13 -14
  100. package/.next/server/app/page_client-reference-manifest.js +1 -1
  101. package/.next/server/app-paths-manifest.json +12 -9
  102. package/.next/server/chunks/1069.js +1 -1
  103. package/.next/server/chunks/1207.js +2 -2
  104. package/.next/server/chunks/1813.js +1 -1
  105. package/.next/server/chunks/2325.js +2 -2
  106. package/.next/server/chunks/2430.js +193 -0
  107. package/.next/server/chunks/329.js +1 -1
  108. package/.next/server/chunks/3379.js +1 -1
  109. package/.next/server/chunks/3557.js +1 -1
  110. package/.next/server/chunks/3908.js +1 -0
  111. package/.next/server/chunks/3960.js +1 -1
  112. package/.next/server/chunks/4127.js +1 -1
  113. package/.next/server/chunks/42.js +1 -0
  114. package/.next/server/chunks/4367.js +1 -1
  115. package/.next/server/chunks/4511.js +1 -0
  116. package/.next/server/chunks/4674.js +1 -1
  117. package/.next/server/chunks/4741.js +152 -7
  118. package/.next/server/chunks/4980.js +1 -1
  119. package/.next/server/chunks/5274.js +1 -1
  120. package/.next/server/chunks/5277.js +1 -1
  121. package/.next/server/chunks/5304.js +2 -2
  122. package/.next/server/chunks/5318.js +1 -1
  123. package/.next/server/chunks/5420.js +1 -0
  124. package/.next/server/chunks/5726.js +1 -1
  125. package/.next/server/chunks/7307.js +1 -1
  126. package/.next/server/chunks/7594.js +11 -11
  127. package/.next/server/chunks/7818.js +1 -0
  128. package/.next/server/chunks/8443.js +1 -0
  129. package/.next/server/chunks/8645.js +1 -1
  130. package/.next/server/chunks/9032.js +1 -0
  131. package/.next/server/chunks/9280.js +3 -3
  132. package/.next/server/chunks/940.js +1 -1
  133. package/.next/server/chunks/9460.js +2 -0
  134. package/.next/server/chunks/981.js +1 -1
  135. package/.next/server/instrumentation.js +1 -1
  136. package/.next/server/middleware-build-manifest.js +1 -1
  137. package/.next/server/middleware-react-loadable-manifest.js +1 -1
  138. package/.next/server/middleware.js +151 -6
  139. package/.next/server/pages/404.html +1 -1
  140. package/.next/server/pages/500.html +1 -1
  141. package/.next/server/prefetch-hints.json +39 -1
  142. package/.next/server/server-reference-manifest.json +1 -1
  143. package/.next/static/chunks/{1377.e883e13864574c26.js → 1377.540f9477711dcf8f.js} +1 -1
  144. package/.next/static/chunks/{3308.23eadd1744bb967c.js → 3308.c0a1a01bfd826d65.js} +2 -2
  145. package/.next/static/chunks/{370.57cfa27da8567918.js → 370.8e8f3cf8eb0e29dd.js} +1 -1
  146. package/.next/static/chunks/3794-0a1186eb85c3950f.js +52 -0
  147. package/.next/static/chunks/4bd1b696-8a4ab4fdf0ae305a.js +1 -0
  148. package/.next/static/chunks/6121.eb9023b1cbc78ee2.js +1 -0
  149. package/.next/static/chunks/{5519-9fb47277a49697d8.js → 7444-80a846a8795bf6f4.js} +1 -1
  150. package/.next/static/chunks/{776.fe8e64ab3669a915.js → 776.4d418d68f76336c7.js} +1 -1
  151. package/.next/static/chunks/{8233.a465d18b04719c6d.js → 8233.e3b47a59bd72a3b3.js} +1 -1
  152. package/.next/static/chunks/{90542734.b75ad0df50bf68f5.js → 90542734.ae439f2382f58c51.js} +1 -1
  153. package/.next/static/chunks/9780-3879ff424362f71a.js +1 -0
  154. package/.next/static/chunks/app/_global-error/page-8f70dda1817cd20c.js +1 -0
  155. package/.next/static/chunks/app/api/about/route-8f70dda1817cd20c.js +1 -0
  156. package/.next/static/chunks/app/api/agent/[id]/bash-output/route-8f70dda1817cd20c.js +1 -0
  157. package/.next/static/chunks/app/api/agent/[id]/events/route-8f70dda1817cd20c.js +1 -0
  158. package/.next/static/chunks/app/api/agent/[id]/route-8f70dda1817cd20c.js +1 -0
  159. package/.next/static/chunks/app/api/agent/new/route-8f70dda1817cd20c.js +1 -0
  160. package/.next/static/chunks/app/api/agent/running/events/route-8f70dda1817cd20c.js +1 -0
  161. package/.next/static/chunks/app/api/agent/running/route-8f70dda1817cd20c.js +1 -0
  162. package/.next/static/chunks/app/api/agent/submissions/[submissionId]/route-8f70dda1817cd20c.js +1 -0
  163. package/.next/static/chunks/app/api/agent-settings/route-8f70dda1817cd20c.js +1 -0
  164. package/.next/static/chunks/app/api/attachments/route-8f70dda1817cd20c.js +1 -0
  165. package/.next/static/chunks/app/api/auth/all-providers/route-8f70dda1817cd20c.js +1 -0
  166. package/.next/static/chunks/app/api/auth/api-key/[provider]/route-8f70dda1817cd20c.js +1 -0
  167. package/.next/static/chunks/app/api/auth/login/[provider]/route-8f70dda1817cd20c.js +1 -0
  168. package/.next/static/chunks/app/api/auth/logout/[provider]/route-8f70dda1817cd20c.js +1 -0
  169. package/.next/static/chunks/app/api/auth/providers/route-8f70dda1817cd20c.js +1 -0
  170. package/.next/static/chunks/app/api/auth/ui-session/route-8f70dda1817cd20c.js +1 -0
  171. package/.next/static/chunks/app/api/auth/ui-sessions/[id]/route-8f70dda1817cd20c.js +1 -0
  172. package/.next/static/chunks/app/api/auth/ui-sessions/route-8f70dda1817cd20c.js +1 -0
  173. package/.next/static/chunks/app/api/cwd/browse/route-8f70dda1817cd20c.js +1 -0
  174. package/.next/static/chunks/app/api/cwd/create/route-8f70dda1817cd20c.js +1 -0
  175. package/.next/static/chunks/app/api/cwd/validate/route-8f70dda1817cd20c.js +1 -0
  176. package/.next/static/chunks/app/api/default-cwd/route-8f70dda1817cd20c.js +1 -0
  177. package/.next/static/chunks/app/api/file-index/route-8f70dda1817cd20c.js +1 -0
  178. package/.next/static/chunks/app/api/files/[...path]/route-8f70dda1817cd20c.js +1 -0
  179. package/.next/static/chunks/app/api/files/save-as/route-8f70dda1817cd20c.js +1 -0
  180. package/.next/static/chunks/app/api/git/diff/route-8f70dda1817cd20c.js +1 -0
  181. package/.next/static/chunks/app/api/git/status/route-8f70dda1817cd20c.js +1 -0
  182. package/.next/static/chunks/app/api/home/route-8f70dda1817cd20c.js +1 -0
  183. package/.next/static/chunks/app/api/message-media/route-8f70dda1817cd20c.js +1 -0
  184. package/.next/static/chunks/app/api/models/enabled/route-8f70dda1817cd20c.js +1 -0
  185. package/.next/static/chunks/app/api/models/refresh/route-8f70dda1817cd20c.js +1 -0
  186. package/.next/static/chunks/app/api/models/route-8f70dda1817cd20c.js +1 -0
  187. package/.next/static/chunks/app/api/models-config/raw/route-8f70dda1817cd20c.js +1 -0
  188. package/.next/static/chunks/app/api/models-config/route-8f70dda1817cd20c.js +1 -0
  189. package/.next/static/chunks/app/api/models-config/test/route-8f70dda1817cd20c.js +1 -0
  190. package/.next/static/chunks/app/api/plugins/route-8f70dda1817cd20c.js +1 -0
  191. package/.next/static/chunks/app/api/plugins/search/route-8f70dda1817cd20c.js +1 -0
  192. package/.next/static/chunks/app/api/plugins/updates/route-8f70dda1817cd20c.js +1 -0
  193. package/.next/static/chunks/app/api/preferences/route-8f70dda1817cd20c.js +1 -0
  194. package/.next/static/chunks/app/api/project-assets/route-8f70dda1817cd20c.js +1 -0
  195. package/.next/static/chunks/app/api/prompts/route-8f70dda1817cd20c.js +1 -0
  196. package/.next/static/chunks/app/api/pty/route-8f70dda1817cd20c.js +1 -0
  197. package/.next/static/chunks/app/api/sessions/[id]/archive/route-8f70dda1817cd20c.js +1 -0
  198. package/.next/static/chunks/app/api/sessions/[id]/auto-name/route-8f70dda1817cd20c.js +1 -0
  199. package/.next/static/chunks/app/api/sessions/[id]/command-entry/route-8f70dda1817cd20c.js +1 -0
  200. package/.next/static/chunks/app/api/sessions/[id]/context/route-8f70dda1817cd20c.js +1 -0
  201. package/.next/static/chunks/app/api/sessions/[id]/entries/[entryId]/thinking/route-8f70dda1817cd20c.js +1 -0
  202. package/.next/static/chunks/app/api/sessions/[id]/export/route-8f70dda1817cd20c.js +1 -0
  203. package/.next/static/chunks/app/api/sessions/[id]/info/route-8f70dda1817cd20c.js +1 -0
  204. package/.next/static/chunks/app/api/sessions/[id]/lock/route-8f70dda1817cd20c.js +1 -0
  205. package/.next/static/chunks/app/api/sessions/[id]/outline/route-8f70dda1817cd20c.js +1 -0
  206. package/.next/static/chunks/app/api/sessions/[id]/route-8f70dda1817cd20c.js +1 -0
  207. package/.next/static/chunks/app/api/sessions/[id]/state/route-8f70dda1817cd20c.js +1 -0
  208. package/.next/static/chunks/app/api/sessions/[id]/tool-results/[toolCallId]/route-8f70dda1817cd20c.js +1 -0
  209. package/.next/static/chunks/app/api/sessions/route-8f70dda1817cd20c.js +1 -0
  210. package/.next/static/chunks/app/api/sessions/search/route-8f70dda1817cd20c.js +1 -0
  211. package/.next/static/chunks/app/api/settings/raw/route-8f70dda1817cd20c.js +1 -0
  212. package/.next/static/chunks/app/api/settings/remote/route-8f70dda1817cd20c.js +1 -0
  213. package/.next/static/chunks/app/api/skills/check/route-8f70dda1817cd20c.js +1 -0
  214. package/.next/static/chunks/app/api/skills/install/route-8f70dda1817cd20c.js +1 -0
  215. package/.next/static/chunks/app/api/skills/route-8f70dda1817cd20c.js +1 -0
  216. package/.next/static/chunks/app/api/skills/search/route-8f70dda1817cd20c.js +1 -0
  217. package/.next/static/chunks/app/api/skills/update/route-8f70dda1817cd20c.js +1 -0
  218. package/.next/static/chunks/app/api/subagent-runs/route-8f70dda1817cd20c.js +1 -0
  219. package/.next/static/chunks/app/api/update/apply/route-8f70dda1817cd20c.js +1 -0
  220. package/.next/static/chunks/app/api/update/check/route-8f70dda1817cd20c.js +1 -0
  221. package/.next/static/chunks/app/page-03ce7a25f33f4d70.js +24 -0
  222. package/.next/static/chunks/{da12927c.00775c0e4542fd3e.js → da12927c.476aa688a637649c.js} +2 -2
  223. package/.next/static/chunks/{e868780c-16e43c5968ccf2bf.js → e868780c-1584512c612787d7.js} +1 -1
  224. package/.next/static/chunks/framework-b33a8f5d57cd8d87.js +1 -0
  225. package/.next/static/chunks/main-1b407bf74905d84a.js +5 -0
  226. package/.next/static/chunks/{main-app-06b2b50b226e40d1.js → main-app-d353053e6467499a.js} +1 -1
  227. package/.next/static/chunks/next/dist/client/components/builtin/app-error-8f70dda1817cd20c.js +1 -0
  228. package/.next/static/chunks/next/dist/client/components/builtin/forbidden-8f70dda1817cd20c.js +1 -0
  229. package/.next/static/chunks/next/dist/client/components/builtin/not-found-8f70dda1817cd20c.js +1 -0
  230. package/.next/static/chunks/next/dist/client/components/builtin/unauthorized-8f70dda1817cd20c.js +1 -0
  231. package/.next/static/chunks/{webpack-d2379fd13c5c78c6.js → webpack-2423c4442766d244.js} +1 -1
  232. package/.next/static/css/1ad5c09cc7ca816b.css +1 -0
  233. package/.next/static/qrH41YQOkbPr0RvEZs8IZ/_buildManifest.js +1 -0
  234. package/README.en.md +10 -1
  235. package/README.md +10 -1
  236. package/bin/pidance-auth-gate.js +41 -11
  237. package/bin/pidance-http-server.js +7 -0
  238. package/bin/pidance.js +5 -1
  239. package/bin/pty-manager.cjs +65 -12
  240. package/bin/pty-process.cjs +135 -0
  241. package/bin/pty-worker.js +17 -3
  242. package/bin/pty-ws.js +126 -3
  243. package/package.json +6 -4
  244. package/.next/server/app/_global-error.segments/_global-error.segment.rsc +0 -5
  245. package/.next/server/app/_global-error.segments/_head.segment.rsc +0 -5
  246. package/.next/server/app/_global-error.segments/_index.segment.rsc +0 -5
  247. package/.next/server/app/_not-found.segments/_head.segment.rsc +0 -6
  248. package/.next/server/app/_not-found.segments/_index.segment.rsc +0 -7
  249. package/.next/server/app/_not-found.segments/_not-found.segment.rsc +0 -5
  250. package/.next/server/app/index.segments/_head.segment.rsc +0 -6
  251. package/.next/server/app/index.segments/_index.segment.rsc +0 -7
  252. package/.next/server/chunks/188.js +0 -1
  253. package/.next/server/chunks/319.js +0 -45
  254. package/.next/server/chunks/6953.js +0 -1
  255. package/.next/server/chunks/8359.js +0 -2
  256. package/.next/server/chunks/9935.js +0 -1
  257. package/.next/static/WyhxhOSSU4IaU7cnCvJTt/_buildManifest.js +0 -1
  258. package/.next/static/chunks/3794-907785a527d8128b.js +0 -32
  259. package/.next/static/chunks/4bd1b696-e356ca5ba0218e27.js +0 -1
  260. package/.next/static/chunks/6121.5b8cb3199531d194.js +0 -1
  261. package/.next/static/chunks/9780-190981a7d5f4799b.js +0 -1
  262. package/.next/static/chunks/app/_global-error/page-7c63ab7d3880fba7.js +0 -1
  263. package/.next/static/chunks/app/api/about/route-7c63ab7d3880fba7.js +0 -1
  264. package/.next/static/chunks/app/api/agent/[id]/bash-output/route-7c63ab7d3880fba7.js +0 -1
  265. package/.next/static/chunks/app/api/agent/[id]/events/route-7c63ab7d3880fba7.js +0 -1
  266. package/.next/static/chunks/app/api/agent/[id]/route-7c63ab7d3880fba7.js +0 -1
  267. package/.next/static/chunks/app/api/agent/new/route-7c63ab7d3880fba7.js +0 -1
  268. package/.next/static/chunks/app/api/agent/running/events/route-7c63ab7d3880fba7.js +0 -1
  269. package/.next/static/chunks/app/api/agent/running/route-7c63ab7d3880fba7.js +0 -1
  270. package/.next/static/chunks/app/api/agent/submissions/[submissionId]/route-7c63ab7d3880fba7.js +0 -1
  271. package/.next/static/chunks/app/api/agent-settings/route-7c63ab7d3880fba7.js +0 -1
  272. package/.next/static/chunks/app/api/attachments/route-7c63ab7d3880fba7.js +0 -1
  273. package/.next/static/chunks/app/api/auth/all-providers/route-7c63ab7d3880fba7.js +0 -1
  274. package/.next/static/chunks/app/api/auth/api-key/[provider]/route-7c63ab7d3880fba7.js +0 -1
  275. package/.next/static/chunks/app/api/auth/login/[provider]/route-7c63ab7d3880fba7.js +0 -1
  276. package/.next/static/chunks/app/api/auth/logout/[provider]/route-7c63ab7d3880fba7.js +0 -1
  277. package/.next/static/chunks/app/api/auth/providers/route-7c63ab7d3880fba7.js +0 -1
  278. package/.next/static/chunks/app/api/auth/ui-session/route-7c63ab7d3880fba7.js +0 -1
  279. package/.next/static/chunks/app/api/auth/ui-sessions/[id]/route-7c63ab7d3880fba7.js +0 -1
  280. package/.next/static/chunks/app/api/auth/ui-sessions/route-7c63ab7d3880fba7.js +0 -1
  281. package/.next/static/chunks/app/api/cwd/browse/route-7c63ab7d3880fba7.js +0 -1
  282. package/.next/static/chunks/app/api/cwd/create/route-7c63ab7d3880fba7.js +0 -1
  283. package/.next/static/chunks/app/api/cwd/validate/route-7c63ab7d3880fba7.js +0 -1
  284. package/.next/static/chunks/app/api/default-cwd/route-7c63ab7d3880fba7.js +0 -1
  285. package/.next/static/chunks/app/api/file-index/route-7c63ab7d3880fba7.js +0 -1
  286. package/.next/static/chunks/app/api/files/[...path]/route-7c63ab7d3880fba7.js +0 -1
  287. package/.next/static/chunks/app/api/files/save-as/route-7c63ab7d3880fba7.js +0 -1
  288. package/.next/static/chunks/app/api/git/diff/route-7c63ab7d3880fba7.js +0 -1
  289. package/.next/static/chunks/app/api/git/status/route-7c63ab7d3880fba7.js +0 -1
  290. package/.next/static/chunks/app/api/home/route-7c63ab7d3880fba7.js +0 -1
  291. package/.next/static/chunks/app/api/message-media/route-7c63ab7d3880fba7.js +0 -1
  292. package/.next/static/chunks/app/api/models/route-7c63ab7d3880fba7.js +0 -1
  293. package/.next/static/chunks/app/api/models-config/raw/route-7c63ab7d3880fba7.js +0 -1
  294. package/.next/static/chunks/app/api/models-config/route-7c63ab7d3880fba7.js +0 -1
  295. package/.next/static/chunks/app/api/models-config/test/route-7c63ab7d3880fba7.js +0 -1
  296. package/.next/static/chunks/app/api/plugins/route-7c63ab7d3880fba7.js +0 -1
  297. package/.next/static/chunks/app/api/plugins/search/route-7c63ab7d3880fba7.js +0 -1
  298. package/.next/static/chunks/app/api/plugins/updates/route-7c63ab7d3880fba7.js +0 -1
  299. package/.next/static/chunks/app/api/preferences/route-7c63ab7d3880fba7.js +0 -1
  300. package/.next/static/chunks/app/api/project-assets/route-7c63ab7d3880fba7.js +0 -1
  301. package/.next/static/chunks/app/api/prompts/route-7c63ab7d3880fba7.js +0 -1
  302. package/.next/static/chunks/app/api/pty/route-7c63ab7d3880fba7.js +0 -1
  303. package/.next/static/chunks/app/api/sessions/[id]/archive/route-7c63ab7d3880fba7.js +0 -1
  304. package/.next/static/chunks/app/api/sessions/[id]/auto-name/route-7c63ab7d3880fba7.js +0 -1
  305. package/.next/static/chunks/app/api/sessions/[id]/command-entry/route-7c63ab7d3880fba7.js +0 -1
  306. package/.next/static/chunks/app/api/sessions/[id]/context/route-7c63ab7d3880fba7.js +0 -1
  307. package/.next/static/chunks/app/api/sessions/[id]/entries/[entryId]/thinking/route-7c63ab7d3880fba7.js +0 -1
  308. package/.next/static/chunks/app/api/sessions/[id]/export/route-7c63ab7d3880fba7.js +0 -1
  309. package/.next/static/chunks/app/api/sessions/[id]/info/route-7c63ab7d3880fba7.js +0 -1
  310. package/.next/static/chunks/app/api/sessions/[id]/outline/route-7c63ab7d3880fba7.js +0 -1
  311. package/.next/static/chunks/app/api/sessions/[id]/route-7c63ab7d3880fba7.js +0 -1
  312. package/.next/static/chunks/app/api/sessions/[id]/state/route-7c63ab7d3880fba7.js +0 -1
  313. package/.next/static/chunks/app/api/sessions/[id]/tool-results/[toolCallId]/route-7c63ab7d3880fba7.js +0 -1
  314. package/.next/static/chunks/app/api/sessions/route-7c63ab7d3880fba7.js +0 -1
  315. package/.next/static/chunks/app/api/sessions/search/route-7c63ab7d3880fba7.js +0 -1
  316. package/.next/static/chunks/app/api/settings/raw/route-7c63ab7d3880fba7.js +0 -1
  317. package/.next/static/chunks/app/api/settings/remote/route-7c63ab7d3880fba7.js +0 -1
  318. package/.next/static/chunks/app/api/skills/check/route-7c63ab7d3880fba7.js +0 -1
  319. package/.next/static/chunks/app/api/skills/install/route-7c63ab7d3880fba7.js +0 -1
  320. package/.next/static/chunks/app/api/skills/route-7c63ab7d3880fba7.js +0 -1
  321. package/.next/static/chunks/app/api/skills/search/route-7c63ab7d3880fba7.js +0 -1
  322. package/.next/static/chunks/app/api/skills/update/route-7c63ab7d3880fba7.js +0 -1
  323. package/.next/static/chunks/app/api/subagent-runs/route-7c63ab7d3880fba7.js +0 -1
  324. package/.next/static/chunks/app/api/update/apply/route-7c63ab7d3880fba7.js +0 -1
  325. package/.next/static/chunks/app/api/update/check/route-7c63ab7d3880fba7.js +0 -1
  326. package/.next/static/chunks/app/page-d0e064d91cca6351.js +0 -24
  327. package/.next/static/chunks/framework-711ef29bc66f648c.js +0 -1
  328. package/.next/static/chunks/main-8e7ef001ea9dd641.js +0 -5
  329. package/.next/static/chunks/next/dist/client/components/builtin/app-error-7c63ab7d3880fba7.js +0 -1
  330. package/.next/static/chunks/next/dist/client/components/builtin/forbidden-7c63ab7d3880fba7.js +0 -1
  331. package/.next/static/chunks/next/dist/client/components/builtin/not-found-7c63ab7d3880fba7.js +0 -1
  332. package/.next/static/chunks/next/dist/client/components/builtin/unauthorized-7c63ab7d3880fba7.js +0 -1
  333. package/.next/static/css/846691607ee7f74d.css +0 -1
  334. /package/.next/static/{WyhxhOSSU4IaU7cnCvJTt → qrH41YQOkbPr0RvEZs8IZ}/_ssgManifest.js +0 -0
@@ -0,0 +1 @@
1
+ self.__BUILD_MANIFEST={__rewrites:{afterFiles:[],beforeFiles:[],fallback:[]},__routerFilterStatic:{numItems:49,errorRate:1e-4,numBits:940,numHashes:14,bitArray:[1,0,1,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,0,0,0,1,1,0,1,1,0,1,0,1,0,0,0,1,1,1,1,0,1,0,1,0,1,0,0,0,1,0,0,1,1,0,0,1,0,1,0,1,0,1,1,1,0,0,1,1,1,0,0,0,0,1,0,0,1,1,1,0,1,1,1,1,0,0,0,0,0,1,1,1,0,0,0,0,1,1,1,0,0,0,0,1,1,1,0,0,0,0,0,1,0,0,1,1,0,1,0,0,1,0,0,0,0,0,0,1,0,1,1,1,1,1,0,0,1,1,0,1,1,1,1,0,0,1,0,1,0,0,1,0,1,1,1,0,1,0,1,1,0,0,0,0,0,1,1,1,1,0,1,0,0,0,1,1,1,0,1,1,1,0,0,0,0,0,1,1,1,0,1,1,1,1,0,1,1,0,0,0,1,1,1,1,1,1,0,0,0,0,0,1,1,1,0,0,1,0,1,0,1,0,0,1,0,1,1,1,0,1,0,0,1,0,0,0,0,1,1,0,1,0,0,0,0,0,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,1,0,1,1,1,1,1,1,1,1,1,0,1,1,1,1,0,1,0,0,0,1,1,1,0,0,0,0,1,1,1,0,0,1,0,1,1,1,0,1,1,0,0,1,0,0,1,0,1,1,0,0,1,0,1,0,1,1,0,0,1,0,1,0,1,1,1,0,1,0,1,0,0,0,1,1,1,0,0,0,1,0,1,1,0,1,1,0,1,0,0,0,1,1,1,1,0,1,1,0,0,0,1,1,1,0,1,1,0,0,1,1,0,1,1,1,0,0,1,1,1,0,0,0,1,1,1,0,1,1,0,0,0,1,0,0,1,0,0,0,0,1,0,0,1,0,0,1,0,0,0,1,1,0,0,0,0,0,1,0,0,1,0,0,1,1,1,1,0,0,0,0,0,0,1,1,0,0,1,0,0,1,1,1,0,0,0,1,0,0,1,1,1,0,1,0,0,1,1,1,0,1,1,1,1,1,1,1,1,0,0,1,0,1,0,1,0,0,0,1,0,1,0,0,1,0,1,1,1,0,0,0,1,0,0,1,1,1,1,1,0,1,0,1,0,1,0,1,1,0,0,1,1,1,0,1,0,0,0,0,0,1,1,1,0,0,0,0,0,1,1,0,1,1,1,0,1,1,0,1,0,0,1,1,1,0,0,1,0,0,1,1,1,0,1,0,0,1,0,0,1,1,0,0,1,0,0,0,1,1,1,1,0,1,1,0,1,1,1,0,1,1,0,0,1,0,0,0,1,0,0,1,1,1,0,0,0,0,0,1,0,0,1,0,0,1,1,1,0,0,1,0,1,1,0,1,1,1,1,0,1,1,1,1,1,1,0,0,0,1,1,0,1,1,0,0,0,1,1,1,1,0,1,1,1,0,1,0,1,1,0,1,1,0,0,0,0,1,0,0,0,1,1,0,1,0,1,1,1,0,0,0,1,1,1,1,1,1,0,1,0,1,1,1,1,0,0,1,1,1,1,0,1,1,1,0,0,0,1,0,0,1,1,0,0,0,0,1,1,0,0,1,1,0,0,0,1,0,1,0,0,1,0,0,0,1,1,1,0,0,0,1,1,1,0,1,0,1,0,1,1,1,0,1,1,0,0,1,0,0,1,1,0,1,1,0,0,0,0,0,1,0,1,1,0,0,0,0,0,1,0,1,0,0,0,1,0,1,1,0,1,0,0,1,1,1,1,0,1,0,0,0,0,1,1,0,1,1,1,0,1,0,1,1,0,0,1,0,0,0,0,0,0,1,0,1,0,1,0,0,1,1,1,1,0,1,0,1,0,1,1,0,0,0,0,0,1,1,1,0,1,0,0,1,0,0,0,0,1,0,0,1,0,0,0,1,0,1,0,0,1,0,1,0,0,0,0,1,0,1,0,1,1,0,0,1,0,1,0,0,1,0,1,0,1,0,1,0,0,1,0,1,1,0,1,1,1,1,1,0,0,0,1,1,1,1,0,0,1,1,0,0,1,0,0,0,1,1,1,1,0,1,1,1,0,0,0,1]},__routerFilterDynamic:{numItems:8,errorRate:1e-4,numBits:154,numHashes:14,bitArray:[1,0,0,0,1,1,1,0,1,0,1,1,1,1,1,1,1,1,0,1,0,0,1,0,1,0,0,1,1,0,0,0,1,1,0,1,0,1,1,0,1,1,1,1,0,1,1,1,1,0,1,0,0,0,0,1,0,0,1,1,0,1,0,1,0,1,1,1,1,1,0,1,1,0,0,1,1,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,1,0,0,1,1,1,0,1,0,1,0,0,1,1,1,1,0,0,0,0,0,1,1,1,1,0,0,0,1,1,0,0,1,1,1,1,1,1,1,1,0,1,1,0,1,0,1,0,0,1,0,0,0,0,1,1,1,0,0,0,1,0]},sortedPages:["/_app"]},self.__BUILD_MANIFEST_CB&&self.__BUILD_MANIFEST_CB();
package/README.en.md CHANGED
@@ -10,7 +10,16 @@
10
10
 
11
11
  Pidance is an open-source web client for the [Pi](https://github.com/badlogic/pi-mono) coding agent. It reads local Pi session files directly and preserves Pi SDK session and runtime semantics, bringing live chat, project files, Git, subagents, and configuration into one browser workspace. Pi remains the source of truth for data and execution semantics; Pidance provides a clearer and more complete interface.
12
12
 
13
- > Current version: `0.2.37` · npm package: `@henlii/pidance` · CLI: `pidance`
13
+ > Current version: `0.2.40` · npm package: `@henlii/pidance` · CLI: `pidance`
14
+
15
+ ## Design principles
16
+
17
+ **Compatibility first, then general display improvements on top of it.**
18
+
19
+ 1. **Content completeness comes first.** Pidance aims to let you experience what a native TUI session shows — **including extension (plugin) custom UI** — in the browser. Anything the native TUI can display, Pidance should display too; prefer showing it as-is over hiding it because it “looks off on the web”.
20
+ 2. **Compatibility outranks looks.** Content a plugin expresses through the TUI extension API (self-drawn components, overlays, widgets, status lines, dialogs) must always have a landing spot. When a capability is missing, degrade **visibly** — notify or return an explicit value, never drop it silently (silence makes plugin authors think it worked).
21
+ 3. **Improvements must be general.** Display-layer work (layout, collapsing, card shells, titles, accessibility) goes through mechanisms shared by every plugin — no per-plugin special cases. Plugin-specific code is allowed only in the compatibility layer: parsing a plugin's private payloads, or bridging TUI semantics to the web.
22
+ 4. **Pi stays the source of truth.** Session files, tool execution, compaction and branch semantics are decided by the Pi SDK; Pidance only projects and presents them. See [`docs/ui-vs-tui.md`](./docs/ui-vs-tui.md) for the surface-by-surface mapping.
14
23
 
15
24
  ## Preview
16
25
 
package/README.md CHANGED
@@ -10,7 +10,16 @@
10
10
 
11
11
  Pidance 是面向 [Pi](https://github.com/badlogic/pi-mono) coding agent 的开源 Web 客户端。它直接读取本机 Pi 会话文件,并沿用 Pi SDK 的会话与运行时语义,把实时对话、项目文件、Git、工作树、子代理和配置管理汇集到一个浏览器工作区。Pi 仍是数据与执行语义的事实来源;Pidance 负责提供更清晰、更完整的操作界面。
12
12
 
13
- > 当前版本:`0.2.37` · npm 包:`@henlii/pidance` · CLI:`pidance`
13
+ > 当前版本:`0.2.40` · npm 包:`@henlii/pidance` · CLI:`pidance`
14
+
15
+ ## 设计原则
16
+
17
+ **兼容优先,然后在兼容之上做通用的显示优化。**
18
+
19
+ 1. **内容完整优先**:Pidance 的目标是在浏览器里体验原生 TUI 会话的内容,**包括扩展(插件)自定义的界面**。原生 TUI 里能显示的东西,Pidance 都要能显示;宁可先原样呈现,也不要因为「Web 里不好看」而少显示。
20
+ 2. **兼容高于观感**:插件用 TUI 扩展 API 表达的内容(自绘组件、overlay、widget、状态条、对话框)都必须有落点。暂不具备的能力按**可见方式**降级——给出提示或明确返回值,不静默丢弃(静默会让插件作者以为生效了)。
21
+ 3. **优化必须通用**:显示层的改进(排版、折叠、卡片壳、标题、无障碍)要走所有插件共用的机制,不为个别插件写特例。插件专属代码只允许出现在兼容层:解析它发的私有载荷、把 TUI 语义桥到 Web。
22
+ 4. **Pi 仍是事实来源**:会话文件、工具执行、压缩与分支语义由 Pi SDK 决定;Pidance 不复制、不覆盖这些语义,只负责投影与呈现。界面分区对照见 [`docs/ui-vs-tui.md`](./docs/ui-vs-tui.md)。
14
23
 
15
24
  ## 界面预览
16
25
 
@@ -2,11 +2,50 @@
2
2
 
3
3
  // 启动认证门禁纯逻辑(CLI 门禁用;与 lib/request-guard.ts 的 isLoopbackHost 语义保持一致):
4
4
  // 监听非回环地址且未设置认证密码 → 拒绝启动(fail-closed,发布阻断 P0)。
5
- // 密码来源:PIDANCE_PASSWORD 优先(产品名),兼容回退旧变量 PI_WEB_PASSWORD。
5
+ // 密码来源:启动缓存(已搬走)→ PIDANCE_PASSWORD(产品名)→ 旧变量 PI_WEB_PASSWORD。
6
6
 
7
7
  // eslint-disable-next-line @typescript-eslint/no-require-imports
8
8
  const { isIP } = require("net");
9
9
 
10
+ /**
11
+ * 进程内密码缓存键,与 lib/request-guard.ts 的 __piAuthPassword 同形。
12
+ *
13
+ * 同进程共享:middleware / route / CLI 共用 globalThis(Next 的 Node middleware 是
14
+ * require 进同进程的),所以 CLI 写、服务端读。
15
+ */
16
+ const AUTH_PASSWORD_CACHE_KEY = "__piAuthPassword";
17
+
18
+ function readPasswordFromEnv(env) {
19
+ const p =
20
+ env && env.PIDANCE_PASSWORD && env.PIDANCE_PASSWORD.length > 0
21
+ ? env.PIDANCE_PASSWORD
22
+ : env && env.PI_WEB_PASSWORD;
23
+ return typeof p === "string" && p.length > 0 ? p : null;
24
+ }
25
+
26
+ /** 解析认证密码:启动缓存优先,否则读 env。 */
27
+ function resolvePassword(env) {
28
+ const cached = globalThis[AUTH_PASSWORD_CACHE_KEY];
29
+ if (cached) return cached.value;
30
+ return readPasswordFromEnv(env);
31
+ }
32
+
33
+ /**
34
+ * 把 env 里的密码搬进进程内缓存,并从 process.env 删掉两个变量名。
35
+ *
36
+ * 为什么必须搬:主 agent 的 SDK bash 工具用 `{ ...process.env }` 构造命令环境,
37
+ * 密码留在 env 里会被 agent 一条 `env` 打进会话并永久落盘。删掉后命令环境拿不到,
38
+ * 认证改读缓存(只删不搬会让 resolvePassword fail-open)。
39
+ * 缓存不写盘。
40
+ */
41
+ function primeAndScrubPassword(env = process.env) {
42
+ const value = readPasswordFromEnv(env);
43
+ globalThis[AUTH_PASSWORD_CACHE_KEY] = { value };
44
+ delete env.PIDANCE_PASSWORD;
45
+ delete env.PI_WEB_PASSWORD;
46
+ return value;
47
+ }
48
+
10
49
  /** host 是否为回环(localhost / *.localhost / IPv4 127.x / IPv6 ::1)。 */
11
50
  function isLoopbackHost(host) {
12
51
  if (typeof host !== "string" || host.length === 0) return false; // 未指定 → Pidance 默认绑定 127.0.0.1
@@ -19,15 +58,6 @@ function isLoopbackHost(host) {
19
58
  return false;
20
59
  }
21
60
 
22
- /** 解析认证密码:PIDANCE_PASSWORD 优先(产品名,空/缺失时回退),兼容旧变量 PI_WEB_PASSWORD。 */
23
- function resolvePassword(env) {
24
- const p =
25
- env && env.PIDANCE_PASSWORD && env.PIDANCE_PASSWORD.length > 0
26
- ? env.PIDANCE_PASSWORD
27
- : env && env.PI_WEB_PASSWORD;
28
- return typeof p === "string" && p.length > 0 ? p : null;
29
- }
30
-
31
61
  /**
32
62
  * 是否需要强制认证:非回环监听地址 + 未设置密码(env 明文或设置 → 通用 保存的服务端密码)。
33
63
  * serverConfig 来自 bin/pidance-server-config.js 的 { passwordSet, remoteEnabled } 投影。
@@ -44,4 +74,4 @@ function describeHost(host) {
44
74
  return typeof host === "string" && host.length > 0 ? host : "127.0.0.1(默认本机绑定)";
45
75
  }
46
76
 
47
- module.exports = { isLoopbackHost, resolvePassword, shouldRequireAuth, describeHost };
77
+ module.exports = { isLoopbackHost, resolvePassword, primeAndScrubPassword, shouldRequireAuth, describeHost };
@@ -58,6 +58,13 @@ async function startPidanceHttpServer(options) {
58
58
  const handle = app.getRequestHandler();
59
59
  const server = createHttpServer((req, res) => {
60
60
  installUpgradeHandler();
61
+ // 对端地址是我们唯一可信的客户端身份来源:先删掉客户端自带的同名头,
62
+ // 再写入 socket 地址。限流分桶读它(middleware 里读不到 socket)。
63
+ if (req.headers) {
64
+ delete req.headers["x-pidance-peer-ip"];
65
+ const address = req.socket?.remoteAddress;
66
+ if (address) req.headers["x-pidance-peer-ip"] = address;
67
+ }
61
68
  // Next 的 compress 只在它自己的内置服务器(router-server)里生效;
62
69
  // 自管 server 必须自己压缩,否则 JSON/HTML 明文下发。
63
70
  // 见 bin/pidance-compression.js。
package/bin/pidance.js CHANGED
@@ -12,7 +12,7 @@ const { parseLaunchOptions } = require("./pidance-options");
12
12
  // eslint-disable-next-line @typescript-eslint/no-require-imports
13
13
  const { loadServerConfig } = require("./pidance-server-config");
14
14
  // eslint-disable-next-line @typescript-eslint/no-require-imports
15
- const { shouldRequireAuth, resolvePassword, describeHost } = require("./pidance-auth-gate");
15
+ const { shouldRequireAuth, resolvePassword, primeAndScrubPassword, describeHost } = require("./pidance-auth-gate");
16
16
  // eslint-disable-next-line @typescript-eslint/no-require-imports
17
17
  const { startPidanceHttpServer } = require("./pidance-http-server");
18
18
 
@@ -39,6 +39,10 @@ if (!nodeMeetsMin(process.versions.node)) {
39
39
 
40
40
  const { port: explicitPort, hostname: explicitHostname, openBrowser } = parseLaunchOptions();
41
41
  const serverConfig = loadServerConfig();
42
+ // 密码只活在进程内缓存里:把 env 里的密码搬进缓存、再删掉两个变量名。
43
+ // 必须在启动 Next 之前做——middleware / route / SDK bash 都在同一进程,读的是 globalThis
44
+ // 缓存;env 里留着的密码会被 agent 的 bash 一条 `env` 打进会话并永久落盘。
45
+ primeAndScrubPassword(process.env);
42
46
  // 默认绑定:设置 → 通用 开启远程服务 → 0.0.0.0;否则仅本机 127.0.0.1(免密码)。
43
47
  // 显式 --hostname / -H / HOSTNAME env 优先;显式 0.0.0.0 仍走密码门禁。
44
48
  const hostname = explicitHostname ?? (serverConfig.remoteEnabled ? "0.0.0.0" : "127.0.0.1");
@@ -4,6 +4,7 @@
4
4
  const { existsSync, realpathSync } = require("fs");
5
5
  const { WebSocketServer } = require("ws");
6
6
  const { resolveShell } = require("./pty-shell.cjs");
7
+ const { killPtyProcess, disposeWorkerChild } = require("./pty-process.cjs");
7
8
  const ptyWss = new WebSocketServer({ noServer: true });
8
9
 
9
10
  function sanitizeEnv(env) {
@@ -68,17 +69,57 @@ function startPtySession(options) {
68
69
  dispose: () => {
69
70
  if (disposed) return;
70
71
  disposed = true;
72
+ killPtyProcess(proc);
73
+ },
74
+ };
75
+ }
76
+
77
+ const PTY_HEARTBEAT_MS = 30_000;
78
+ const PTY_HEARTBEAT_MAX_MISSED = 2;
79
+ // 取舍:看的是 WebSocket 协议级 ping/pong(浏览器自动回 pong),**不是**终端有没有输出,
80
+ // 所以前台跑 `sleep 600` 之类不会因为「没输出」被判死。代价是:手机锁屏后网络栈不再回 pong,
81
+ // 连续 3 拍(约 90 秒)没有任何 pong 就会 terminate → 面板重连时是**新** shell。
82
+ // 要更宽松就调大这两个常量;不要改成按终端输出判活(那会杀掉长任务)。
83
+
84
+ /**
85
+ * 判断这条连接是真死还是只是安静:手机掉网、进程被冻住时 TCP 不会发 FIN,
86
+ * 服务端会一直攥着 ws 和它背后的 shell(孤儿进程,还占着端口/内存)。
87
+ * 按 ping/pong 收尾,连续几轮没有 pong 就 terminate(触发 close → dispose)。
88
+ * 计时器与 readyState 判定可注入,单测用假计时器驱动。
89
+ */
90
+ function startPtyHeartbeat(ws, options = {}) {
91
+ const intervalMs = options.intervalMs ?? PTY_HEARTBEAT_MS;
92
+ const maxMissed = options.maxMissed ?? PTY_HEARTBEAT_MAX_MISSED;
93
+ const setIntervalFn = options.setIntervalFn ?? setInterval;
94
+ const clearIntervalFn = options.clearIntervalFn ?? clearInterval;
95
+ const isOpen = options.isOpen ?? (() => ws.readyState === 1);
96
+ let missedPongs = 0;
97
+ const onPong = () => {
98
+ missedPongs = 0;
99
+ };
100
+ ws.on("pong", onPong);
101
+ const timer = setIntervalFn(() => {
102
+ if (!isOpen()) return;
103
+ if (missedPongs >= maxMissed) {
71
104
  try {
72
- if (proc.pid > 0) process.kill(-proc.pid, "SIGTERM");
73
- } catch {
74
- /* 进程组可能已不在 */
75
- }
76
- try {
77
- proc.kill("SIGTERM");
105
+ ws.terminate();
78
106
  } catch {
79
- /* 已退出 */
107
+ /* 已断开 */
80
108
  }
81
- },
109
+ return;
110
+ }
111
+ missedPongs += 1;
112
+ try {
113
+ ws.ping();
114
+ } catch {
115
+ /* 已断开 */
116
+ }
117
+ }, intervalMs);
118
+ // unref:别让心跳计时器把进程吊在退出前。
119
+ if (timer && typeof timer.unref === "function") timer.unref();
120
+ return () => {
121
+ clearIntervalFn(timer);
122
+ if (typeof ws.off === "function") ws.off("pong", onPong);
82
123
  };
83
124
  }
84
125
 
@@ -86,10 +127,13 @@ function attachPtyToWebSocket(ws, cwd) {
86
127
  const { spawn } = require("child_process");
87
128
  const path = require("path");
88
129
  const workerPath = path.join(__dirname, "pty-worker.js");
130
+ let disposed = false;
89
131
  const child = spawn(process.execPath, [workerPath, cwd, "80", "24"], {
90
132
  stdio: ["pipe", "pipe", "pipe"],
91
133
  env: process.env,
92
134
  });
135
+ // stdin 在子进程已退出后写入会异步抛 EPIPE:这里吞掉,避免拆连接时崩服务端。
136
+ child.stdin.on("error", () => {});
93
137
  child.stderr.setEncoding("utf8");
94
138
  child.stderr.on("data", (data) => console.warn("[pidance] pty-worker stderr", data));
95
139
  child.on("error", (error) => console.warn("[pidance] pty-worker spawn", error.message));
@@ -98,7 +142,10 @@ function attachPtyToWebSocket(ws, cwd) {
98
142
  write: (data) => child.stdin.write(`${JSON.stringify({ type: "in", d: data })}\n`),
99
143
  resize: (cols, rows) => child.stdin.write(`${JSON.stringify({ type: "rs", cols, rows })}\n`),
100
144
  dispose: () => {
101
- try { child.kill("SIGTERM"); } catch { /* ignore */ }
145
+ if (disposed) return;
146
+ disposed = true;
147
+ // 先请 worker 自己收尾,再按平台决定强杀时机(Windows 上不能同拍强杀,见 disposeWorkerChild)。
148
+ disposeWorkerChild(child);
102
149
  },
103
150
  };
104
151
  child.stdout.setEncoding("utf8");
@@ -135,8 +182,14 @@ function attachPtyToWebSocket(ws, cwd) {
135
182
  if (parsed && parsed.type === "in" && typeof parsed.d === "string") session.write(parsed.d);
136
183
  if (parsed && parsed.type === "rs" && parsed.cols > 0 && parsed.rows > 0) session.resize(parsed.cols, parsed.rows);
137
184
  });
138
- ws.on("close", () => session.dispose());
139
- ws.on("error", () => session.dispose());
185
+ // 心跳与 dispose 一起收:连接没了就别再 ping(也避免计时器残留)。
186
+ const stopHeartbeat = startPtyHeartbeat(ws);
187
+ const disposeSession = () => {
188
+ stopHeartbeat();
189
+ session.dispose();
190
+ };
191
+ ws.on("close", disposeSession);
192
+ ws.on("error", disposeSession);
140
193
  try { ws.send(JSON.stringify({ type: "out", d: "\r\n[pidance] terminal ready\r\n" })); } catch { /* ignore */ }
141
194
  return session;
142
195
  }
@@ -148,4 +201,4 @@ function completePtyUpgrade(req, socket, head, cwd) {
148
201
  });
149
202
  }
150
203
 
151
- module.exports = { startPtySession, tryLoadNodePty, resolvePtyCwd, attachPtyToWebSocket, completePtyUpgrade };
204
+ module.exports = { startPtySession, tryLoadNodePty, resolvePtyCwd, attachPtyToWebSocket, completePtyUpgrade, startPtyHeartbeat };
@@ -0,0 +1,135 @@
1
+ "use strict";
2
+
3
+ /**
4
+ * PTY 子进程的收尾规则(bin/pty-manager.cjs 与 bin/pty-worker.js 共用一份)。
5
+ *
6
+ * 为什么不能只 `proc.kill(signal)`:node-pty 的 Unix 实现就是只杀那一个 pid
7
+ * (`node_modules/node-pty/lib/unixTerminal.js` 的 `kill` 里是 `process.kill(this.pid, signal)`),
8
+ * 而 shell 在**同一进程组**里起的后代(例如 `sh -c "sleep 600 & wait"` 那种同组后台作业)会被留下。
9
+ *
10
+ * forkpty 会让 shell 成为会话/进程组组长,所以先补一刀 `-pid` 打整组,再按 pid 收尾
11
+ * (组长可能已不在,两步都要容错)。
12
+ *
13
+ * 边界(别把组杀想得比它更大):交互式 bash 里直接敲的 `sleep 600 &` 会被 job control 放进
14
+ * **另一个**进程组,`kill(-shellPid)` **打不中**它 —— 逃出会话组的后代本来就要按 SID 遍历进程树才收得掉,
15
+ * 那是平台相关的产品取舍,这里不做。
16
+ *
17
+ * Windows 上 `process.kill(-pid)` 会抛错(不支持杀进程组),而 node-pty 的
18
+ * `WindowsTerminal.kill(signal)` 在真正清理(`_close()` / `_agent.kill()`)**之前**就
19
+ * `throw new Error("Signals not supported on windows.")`(`node_modules/node-pty/lib/windowsTerminal.js`)——
20
+ * 所以 win32 必须**不传 signal** 地调用 `kill()`,否则那条真正的 ConPTY 清理会被空 catch 当成「已经退出」吞掉。
21
+ */
22
+ function killPtyProcess(proc, signal = "SIGTERM", platform = process.platform) {
23
+ if (!proc || !(proc.pid > 0)) return;
24
+ // 进程组那一刀只在支持它的平台做(Windows 传负 pid 会抛)。
25
+ if (platform !== "win32") {
26
+ try {
27
+ process.kill(-proc.pid, signal);
28
+ } catch {
29
+ /* 进程组可能已不在 */
30
+ }
31
+ }
32
+ if (typeof proc.kill === "function") {
33
+ try {
34
+ // Windows:不能传 signal,否则 node-pty 在真正清理前就抛错(见文件头)。
35
+ if (platform === "win32") proc.kill();
36
+ else proc.kill(signal);
37
+ } catch {
38
+ /* 已退出 */
39
+ }
40
+ }
41
+ }
42
+
43
+ /**
44
+ * 请 pty-worker 自己收尾(发一条 {type:"bye"} 帧)。
45
+ * 为什么不能只靠 child.kill:Windows 上 Node 会忽略信号种类直接强杀 worker,
46
+ * worker 里的信号处理跑不到 → node-pty 的真实清理也跑不到。帧发不出去就返回 false,
47
+ * 由调用方继续走强杀兜底。
48
+ */
49
+ function requestWorkerShutdown(child) {
50
+ try {
51
+ if (!child || !child.stdin || child.stdin.writable === false) return false;
52
+ child.stdin.write(`${JSON.stringify({ type: "bye" })}\n`);
53
+ return true;
54
+ } catch {
55
+ return false;
56
+ }
57
+ }
58
+
59
+ /** 请 worker 自己收尾之后等它退出的上限(Windows 上必须等:见 disposeWorkerChild)。 */
60
+ const WORKER_SHUTDOWN_GRACE_MS = 2000;
61
+
62
+ /**
63
+ * 关掉一条终端时收尾 pty-worker。
64
+ *
65
+ * Linux:worker 收到 SIGTERM 会跑自己的 shutdown(killPtyProcess + exit),所以直接发信号。
66
+ * Windows:`child.kill` 会**忽略信号种类、强制结束**(Node 文档:similar to SIGKILL),
67
+ * 同一次同步调用里就把 worker 结束了 —— 它下一次事件循环才会读到 stdin,所以先写 bye 帧再立刻
68
+ * 强杀等于 bye 从来没送到,worker 里的 node-pty 真实清理也跑不到。因此 win32 上先发 bye,
69
+ * 让它自己退出;只有超时未退才强杀。
70
+ */
71
+ function disposeWorkerChild(child, options = {}) {
72
+ const platform = options.platform ?? process.platform;
73
+ const graceMs = options.graceMs ?? WORKER_SHUTDOWN_GRACE_MS;
74
+ const setTimer = options.setTimer ?? setTimeout;
75
+ const clearTimer = options.clearTimer ?? clearTimeout;
76
+ const kill = () => {
77
+ try {
78
+ child.kill("SIGTERM");
79
+ } catch {
80
+ /* 已退出 */
81
+ }
82
+ };
83
+ // 只在真的要等它的平台上发 bye 帧:非 win32 的路径与改动前逐字一致(就一次 SIGTERM)。
84
+ if (platform === "win32" && requestWorkerShutdown(child)) {
85
+ const timer = setTimer(kill, graceMs);
86
+ if (timer && typeof timer.unref === "function") timer.unref();
87
+ if (typeof child.once === "function") child.once("exit", () => clearTimer(timer));
88
+ return;
89
+ }
90
+ kill();
91
+ }
92
+
93
+ const PARENT_WATCH_MS = 5000;
94
+ /** 连续探不到父进程几次才收尾(见 startParentWatchdog)。 */
95
+ const PARENT_WATCH_MISSES = 2;
96
+
97
+ /**
98
+ * 父进程被硬杀(SIGKILL / 崩溃 / 被强制结束)时不会发 SIGTERM,PTY worker 会连同
99
+ * 它下面的 shell 一起变成孤儿 —— 实测:改前(没有看护)worker 在父进程被 SIGKILL
100
+ * 之后一直活着,改后退出。定期确认父进程还在,不在了就收尾。
101
+ * 依赖与计时器可注入,单测用假计时器驱动。
102
+ */
103
+ function startParentWatchdog(options = {}) {
104
+ const parentPid = options.parentPid ?? process.ppid;
105
+ const intervalMs = options.intervalMs ?? PARENT_WATCH_MS;
106
+ const missThreshold = options.missThreshold ?? PARENT_WATCH_MISSES;
107
+ const setIntervalFn = options.setIntervalFn ?? setInterval;
108
+ const clearIntervalFn = options.clearIntervalFn ?? clearInterval;
109
+ // 只看「进程不存在」(ESRCH):EPERM 是「存在但不是我们能碰的」,绝不能当死亡,
110
+ // 否则一次权限异常就会在 5 秒后拆掉用户的终端。
111
+ const isAlive = options.isAlive ?? ((pid) => {
112
+ try {
113
+ process.kill(pid, 0);
114
+ return true;
115
+ } catch (error) {
116
+ return error && error.code === "EPERM";
117
+ }
118
+ });
119
+ const onGone = options.onGone ?? (() => {});
120
+ // 连续两次探不到才收尾:杀错(拆掉用户正在用的终端)比晚 5 秒收尾严重得多。
121
+ let missed = 0;
122
+ const timer = setIntervalFn(() => {
123
+ if (isAlive(parentPid)) {
124
+ missed = 0;
125
+ return;
126
+ }
127
+ missed += 1;
128
+ if (missed >= missThreshold) onGone();
129
+ }, intervalMs);
130
+ // unref:看护计时器不该把进程吊住,worker 是靠 pty 活着的。
131
+ if (timer && typeof timer.unref === "function") timer.unref();
132
+ return () => clearIntervalFn(timer);
133
+ }
134
+
135
+ module.exports = { killPtyProcess, startParentWatchdog, requestWorkerShutdown, disposeWorkerChild };
package/bin/pty-worker.js CHANGED
@@ -3,6 +3,7 @@
3
3
 
4
4
  const pty = require("node-pty");
5
5
  const { resolveShell } = require("./pty-shell.cjs");
6
+ const { killPtyProcess, startParentWatchdog } = require("./pty-process.cjs");
6
7
 
7
8
  const cwd = process.argv[2] || process.cwd();
8
9
  const cols = Number(process.argv[3]) || 80;
@@ -48,10 +49,23 @@ process.stdin.on("data", (chunk) => {
48
49
  try { msg = JSON.parse(line); } catch { continue; }
49
50
  if (msg.type === "in" && typeof msg.d === "string") proc.write(msg.d);
50
51
  if (msg.type === "rs" && msg.cols > 0 && msg.rows > 0) proc.resize(msg.cols, msg.rows);
52
+ // 父进程请求收尾:Windows 上 child.kill 会忽略信号种类直接强杀 worker,
53
+ // worker 侧的信号处理跑不到,所以正常关闭走这条显式请求。
54
+ if (msg.type === "bye") shutdown();
51
55
  }
52
56
  });
53
57
 
54
- process.on("SIGTERM", () => {
55
- try { proc.kill("SIGTERM"); } catch { /* ignore */ }
58
+ // 收尾:Linux 走父进程的 SIGTERM / SIGINT,Windows 走父进程发来的 bye 帧
59
+ // (那边 child.kill 会忽略信号种类直接强杀,信号处理跑不到);异常路径由下面的父进程看护兜底。
60
+ let exiting = false;
61
+ const shutdown = () => {
62
+ if (exiting) return;
63
+ exiting = true;
64
+ killPtyProcess(proc);
56
65
  process.exit(0);
57
- });
66
+ };
67
+ process.on("SIGTERM", shutdown);
68
+ process.on("SIGINT", shutdown);
69
+ // 父进程真的没了才收尾:stdin EOF 不等于父进程退出(写端关闭就会 EOF,
70
+ // 而父进程可能还在),所以这里看的是父进程本身还在不在。
71
+ startParentWatchdog({ onGone: shutdown });
package/bin/pty-ws.js CHANGED
@@ -69,6 +69,10 @@ function isLoopbackHost(hostHeader) {
69
69
  const UI_SESSION_COOKIE_NAME = "pidance_ui_session";
70
70
 
71
71
  function resolvePassword(env) {
72
+ // 启动时密码已搬进同进程 globalThis 缓存(bin/pidance-auth-gate.js 的
73
+ // primeAndScrubPassword),env 里不再有明文;两条来源同形,缺一不可。
74
+ const cached = globalThis.__piAuthPassword;
75
+ if (cached) return cached.value;
72
76
  const p =
73
77
  env && env.PIDANCE_PASSWORD && env.PIDANCE_PASSWORD.length > 0
74
78
  ? env.PIDANCE_PASSWORD
@@ -215,15 +219,22 @@ function ptyGuardHeaders(req) {
215
219
  secFetchUser: header(req, "sec-fetch-user"),
216
220
  authorization: header(req, "authorization"),
217
221
  cookie: header(req, "cookie"),
222
+ xForwardedFor: header(req, "x-forwarded-for"),
218
223
  method: "GET",
219
224
  url,
220
225
  pathname,
221
226
  };
222
227
  }
223
228
 
224
- function reject(socket, status, message) {
229
+ function reject(socket, status, message, extraHeaders) {
230
+ const headers = {
231
+ Connection: "close",
232
+ "Content-Length": 0,
233
+ ...(extraHeaders || {}),
234
+ };
235
+ const lines = Object.keys(headers).map((name) => `${name}: ${headers[name]}\r\n`).join("");
225
236
  try {
226
- socket.write(`HTTP/1.1 ${status} ${message}\r\nConnection: close\r\nContent-Length: 0\r\n\r\n`);
237
+ socket.write(`HTTP/1.1 ${status} ${message}\r\n${lines}\r\n`);
227
238
  } catch {
228
239
  // ignore
229
240
  }
@@ -234,6 +245,99 @@ function reject(socket, status, message) {
234
245
  }
235
246
  }
236
247
 
248
+ // ── 密码尝试限流(与 lib/auth-throttle.ts 同桶)──────────────────────────
249
+ //
250
+ // WebSocket 升级不经过 Next middleware,所以这里必须自己挡一次:否则 /api/pty
251
+ // 就是一条不限速的密码预言机(Basic 可全速猜)。状态放在与 lib/auth-throttle.ts
252
+ // 相同的 globalThis 键、相同结构上,两条入口在同进程里共用同一个桶。
253
+ //
254
+ // bin/ 是自包含发布物(见文件头注释,不依赖 lib/ 源码树),所以退避公式与常量
255
+ // 在内联实现里保持语义一致;bin/pty-ws.test.mjs 有一条与 lib/auth-throttle.ts
256
+ // 的 parity 断言,改一边不改另一边会红。
257
+
258
+ const AUTH_THROTTLE_GLOBAL_KEY = "__piAuthThrottle";
259
+ const AUTH_THROTTLE_BASE_DELAY_MS = 1000;
260
+ const AUTH_THROTTLE_MAX_DELAY_MS = 60000;
261
+ const AUTH_THROTTLE_RESET_AFTER_MS = 5 * 60 * 1000;
262
+ const AUTH_THROTTLE_MAX_BUCKETS = 256;
263
+
264
+ function authThrottleStore() {
265
+ if (!globalThis[AUTH_THROTTLE_GLOBAL_KEY]) globalThis[AUTH_THROTTLE_GLOBAL_KEY] = new Map();
266
+ return globalThis[AUTH_THROTTLE_GLOBAL_KEY];
267
+ }
268
+
269
+ function backoffDelayMs(failures) {
270
+ if (failures <= 0) return 0;
271
+ const exponent = Math.min(failures - 1, 31);
272
+ return Math.min(AUTH_THROTTLE_BASE_DELAY_MS * 2 ** exponent, AUTH_THROTTLE_MAX_DELAY_MS);
273
+ }
274
+
275
+ function expireIfStale(state, now) {
276
+ if (state.failures > 0 && now - state.lastFailureAt >= AUTH_THROTTLE_RESET_AFTER_MS) {
277
+ state.failures = 0;
278
+ state.lastFailureAt = 0;
279
+ state.blockedUntil = 0;
280
+ }
281
+ }
282
+
283
+ /** 该桶还需等多久(毫秒);0 表示可以尝试。 */
284
+ function getAuthRetryAfterMs(key, now = Date.now()) {
285
+ const state = authThrottleStore().get(key);
286
+ if (!state) return 0;
287
+ expireIfStale(state, now);
288
+ return Math.max(0, state.blockedUntil - now);
289
+ }
290
+
291
+ function pruneAuthThrottle(now) {
292
+ const map = authThrottleStore();
293
+ if (map.size <= AUTH_THROTTLE_MAX_BUCKETS) return;
294
+ for (const [key, state] of map) {
295
+ if (state.failures === 0 || now - state.lastFailureAt >= AUTH_THROTTLE_RESET_AFTER_MS) map.delete(key);
296
+ }
297
+ while (map.size > AUTH_THROTTLE_MAX_BUCKETS) {
298
+ const oldest = [...map.entries()].sort((a, b) => a[1].lastFailureAt - b[1].lastFailureAt)[0];
299
+ if (!oldest) break;
300
+ map.delete(oldest[0]);
301
+ }
302
+ }
303
+
304
+ /** 记一次失败并返回施加的退避(毫秒)。 */
305
+ function recordAuthFailure(key, now = Date.now()) {
306
+ const map = authThrottleStore();
307
+ let state = map.get(key);
308
+ if (!state) {
309
+ state = { failures: 0, lastFailureAt: 0, blockedUntil: 0 };
310
+ map.set(key, state);
311
+ }
312
+ expireIfStale(state, now);
313
+ state.failures += 1;
314
+ state.lastFailureAt = now;
315
+ state.blockedUntil = now + backoffDelayMs(state.failures);
316
+ pruneAuthThrottle(now);
317
+ return backoffDelayMs(state.failures);
318
+ }
319
+
320
+ /**
321
+ * 限流分桶的身份,与 lib/request-guard.ts 的 `authIdentity` 同规则:
322
+ * 只在显式 `PIDANCE_TRUST_PROXY` 时信 `x-forwarded-for`,否则用对端地址;
323
+ * 都拿不到时退回固定全局桶(宁可误伤也不放行)。
324
+ */
325
+ function authThrottleKey(socket, headers, env) {
326
+ const trustProxy = env.PIDANCE_TRUST_PROXY === "1" || env.PIDANCE_TRUST_PROXY === "true";
327
+ if (trustProxy) {
328
+ const first = (headers.xForwardedFor || "").split(",")[0];
329
+ const trimmed = first ? first.trim() : "";
330
+ if (trimmed) return trimmed.replace(/^::ffff:/, "");
331
+ }
332
+ const peer = typeof socket?.remoteAddress === "string" ? socket.remoteAddress.trim() : "";
333
+ if (peer) return peer.replace(/^::ffff:/, "");
334
+ return "unknown";
335
+ }
336
+
337
+ function retryAfterSeconds(retryAfterMs) {
338
+ return Math.max(1, Math.ceil(retryAfterMs / 1000));
339
+ }
340
+
237
341
  async function handlePtyUpgrade(req, socket, head) {
238
342
  if (!tryLoadNodePty()) {
239
343
  reject(socket, 503, "PTY Unavailable");
@@ -251,10 +355,20 @@ async function handlePtyUpgrade(req, socket, head) {
251
355
  return;
252
356
  }
253
357
  if (passwordEnabled(process.env)) {
358
+ // 与 middleware / 登录表单共用同一个桶:封锁期内密码正确也不放行,
359
+ // 否则升级路径就是一条不限速的密码预言机。
360
+ const throttleKey = authThrottleKey(socket, guardHeaders, process.env);
361
+ const retryAfterMs = getAuthRetryAfterMs(throttleKey);
362
+ if (retryAfterMs > 0) {
363
+ reject(socket, 429, "Too Many Requests", { "Retry-After": retryAfterSeconds(retryAfterMs) });
364
+ return;
365
+ }
254
366
  if (!checkAuthenticated(guardHeaders, process.env)) {
367
+ recordAuthFailure(throttleKey);
255
368
  reject(socket, 401, "auth-required");
256
369
  return;
257
370
  }
371
+ // 成功不回退计数:Basic 每个请求都带,复位会让穿插猜测回到基准延迟。
258
372
  } else if (!isLoopbackHost(guardHeaders.host)) {
259
373
  // fail-closed 兜底:未设密码时仅放行回环请求(与 middleware 一致)。
260
374
  reject(socket, 401, "auth-required");
@@ -268,4 +382,13 @@ async function handlePtyUpgrade(req, socket, head) {
268
382
  completePtyUpgrade(req, socket, head, cwd);
269
383
  }
270
384
 
271
- module.exports = { handlePtyUpgrade, ptyGuardHeaders };
385
+ module.exports = {
386
+ handlePtyUpgrade,
387
+ ptyGuardHeaders,
388
+ // 导出限流内联实现:bin/pty-ws.test.mjs 用它断言与 lib/auth-throttle.ts 的
389
+ // 退避公式一致、且两条入口共用同一个桶。
390
+ authThrottleKey,
391
+ backoffDelayMs,
392
+ getAuthRetryAfterMs,
393
+ recordAuthFailure,
394
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@henlii/pidance",
3
- "version": "0.2.37",
3
+ "version": "0.2.40",
4
4
  "description": "Pidance:面向 Pi coding agent 的开源 Web 客户端",
5
5
  "homepage": "https://github.com/henlii/pidance#readme",
6
6
  "repository": {
@@ -55,20 +55,22 @@
55
55
  "check": "npm run typecheck && npm run lint && npm run test",
56
56
  "release:audit": "node scripts/audit-release-package.mjs --pre",
57
57
  "release:audit:tgz": "node scripts/audit-release-package.mjs --tgz",
58
+ "release:desktop-check": "node scripts/check-desktop-lockfile.mjs",
58
59
  "package:candidate": "node scripts/make-candidate-package.mjs",
59
60
  "release:check": "npm run check && npm run build && npm run release:audit",
60
61
  "test:browser:sse": "node --test scripts/sse-recording-replay.test.mjs"
61
62
  },
62
63
  "dependencies": {
63
- "@earendil-works/pi-coding-agent": "0.85.1",
64
+ "@earendil-works/pi-coding-agent": "0.87.0",
65
+ "@earendil-works/pi-tui": "0.87.0",
64
66
  "@xterm/addon-fit": "^0.11.0",
65
67
  "@xterm/xterm": "^6.0.0",
66
68
  "jiti": "^2.7.0",
67
69
  "lucide-react": "^0.562.0",
68
- "next": "16.2.11",
70
+ "next": "16.3.6",
69
71
  "react": "^19.2.4",
70
72
  "react-dom": "^19.2.4",
71
- "undici": "8.5.0",
73
+ "undici": "8.11.0",
72
74
  "ws": "^8.21.3"
73
75
  },
74
76
  "devDependencies": {
@@ -1,5 +0,0 @@
1
- 1:"$Sreact.fragment"
2
- 2:I[57121,[],""]
3
- 3:I[74581,[],""]
4
- 4:[]
5
- 0:{"rsc":["$","$1","c",{"children":[null,["$","$L2",null,{"parallelRouterKey":"children","template":["$","$L3",null,{}]}]]}],"isPartial":false,"staleTime":300,"varyParams":"$W4","buildId":"WyhxhOSSU4IaU7cnCvJTt"}