@henlii/pidance 0.2.6 → 0.2.7

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 (242) hide show
  1. package/.next/BUILD_ID +1 -1
  2. package/.next/app-path-routes-manifest.json +10 -9
  3. package/.next/build-manifest.json +3 -3
  4. package/.next/prerender-manifest.json +3 -3
  5. package/.next/required-server-files.json +4 -2
  6. package/.next/routes-manifest.json +6 -0
  7. package/.next/server/app/_global-error/page.js +3 -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.rsc +1 -1
  11. package/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  12. package/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  13. package/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  14. package/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  15. package/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  16. package/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  17. package/.next/server/app/_not-found/page.js +2 -2
  18. package/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  19. package/.next/server/app/_not-found.html +1 -1
  20. package/.next/server/app/_not-found.rsc +3 -3
  21. package/.next/server/app/_not-found.segments/_full.segment.rsc +3 -3
  22. package/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  23. package/.next/server/app/_not-found.segments/_index.segment.rsc +3 -3
  24. package/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  25. package/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  26. package/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -2
  27. package/.next/server/app/api/about/route.js +1 -1
  28. package/.next/server/app/api/agent/[id]/bash-output/route.js +1 -1
  29. package/.next/server/app/api/agent/[id]/events/route.js +2 -2
  30. package/.next/server/app/api/agent/[id]/route.js +1 -1
  31. package/.next/server/app/api/agent/new/route.js +1 -1
  32. package/.next/server/app/api/agent/running/events/route.js +1 -1
  33. package/.next/server/app/api/agent/running/route.js +1 -1
  34. package/.next/server/app/api/agent-settings/route.js +2 -2
  35. package/.next/server/app/api/attachments/route.js +1 -1
  36. package/.next/server/app/api/auth/all-providers/route.js +1 -1
  37. package/.next/server/app/api/auth/api-key/[provider]/route.js +1 -1
  38. package/.next/server/app/api/auth/login/[provider]/route.js +2 -2
  39. package/.next/server/app/api/auth/logout/[provider]/route.js +1 -1
  40. package/.next/server/app/api/auth/providers/route.js +1 -1
  41. package/.next/server/app/api/auth/ui-session/route.js +1 -1
  42. package/.next/server/app/api/cwd/browse/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 +2 -2
  47. package/.next/server/app/api/git/diff/route.js +1 -1
  48. package/.next/server/app/api/git/status/route.js +1 -1
  49. package/.next/server/app/api/home/route.js +1 -1
  50. package/.next/server/app/api/models/route.js +1 -1
  51. package/.next/server/app/api/models-config/raw/route.js +1 -1
  52. package/.next/server/app/api/models-config/route.js +1 -1
  53. package/.next/server/app/api/models-config/test/route.js +1 -1
  54. package/.next/server/app/api/plugins/route.js +1 -1
  55. package/.next/server/app/api/plugins/search/route.js +1 -1
  56. package/.next/server/app/api/plugins/updates/route.js +1 -1
  57. package/.next/server/app/api/preferences/route.js +1 -1
  58. package/.next/server/app/api/project-assets/route.js +2 -2
  59. package/.next/server/app/api/prompts/route.js +1 -1
  60. package/.next/server/app/api/pty/route.js +3 -0
  61. package/.next/server/app/api/pty/route_client-reference-manifest.js +1 -0
  62. package/.next/server/app/api/sessions/[id]/archive/route.js +1 -1
  63. package/.next/server/app/api/sessions/[id]/auto-name/route.js +3 -3
  64. package/.next/server/app/api/sessions/[id]/command-entry/route.js +1 -1
  65. package/.next/server/app/api/sessions/[id]/context/route.js +1 -1
  66. package/.next/server/app/api/sessions/[id]/entries/[entryId]/thinking/route.js +1 -1
  67. package/.next/server/app/api/sessions/[id]/export/route.js +3 -3
  68. package/.next/server/app/api/sessions/[id]/info/route.js +1 -1
  69. package/.next/server/app/api/sessions/[id]/route.js +1 -1
  70. package/.next/server/app/api/sessions/[id]/state/route.js +1 -1
  71. package/.next/server/app/api/sessions/[id]/tool-results/[toolCallId]/route.js +1 -1
  72. package/.next/server/app/api/sessions/route.js +1 -1
  73. package/.next/server/app/api/sessions/search/route.js +1 -1
  74. package/.next/server/app/api/settings/raw/route.js +2 -2
  75. package/.next/server/app/api/skills/check/route.js +1 -1
  76. package/.next/server/app/api/skills/install/route.js +1 -1
  77. package/.next/server/app/api/skills/route.js +2 -2
  78. package/.next/server/app/api/skills/search/route.js +1 -1
  79. package/.next/server/app/api/skills/update/route.js +1 -1
  80. package/.next/server/app/api/subagent-runs/route.js +1 -1
  81. package/.next/server/app/api/update/apply/route.js +3 -3
  82. package/.next/server/app/api/update/check/route.js +2 -2
  83. package/.next/server/app/api/worktrees/route.js +1 -1
  84. package/.next/server/app/icon.png/route.js +1 -1
  85. package/.next/server/app/index.html +1 -1
  86. package/.next/server/app/index.rsc +6 -5
  87. package/.next/server/app/index.segments/__PAGE__.segment.rsc +4 -3
  88. package/.next/server/app/index.segments/_full.segment.rsc +6 -5
  89. package/.next/server/app/index.segments/_head.segment.rsc +1 -1
  90. package/.next/server/app/index.segments/_index.segment.rsc +3 -3
  91. package/.next/server/app/index.segments/_tree.segment.rsc +3 -2
  92. package/.next/server/app/page.js +22 -6
  93. package/.next/server/app/page_client-reference-manifest.js +1 -1
  94. package/.next/server/app-paths-manifest.json +10 -9
  95. package/.next/server/chunks/188.js +1 -1
  96. package/.next/server/chunks/5582.js +1 -1
  97. package/.next/server/chunks/7594.js +1 -1
  98. package/.next/server/middleware-build-manifest.js +1 -1
  99. package/.next/server/pages/404.html +1 -1
  100. package/.next/server/pages/500.html +1 -1
  101. package/.next/server/server-reference-manifest.json +1 -1
  102. package/.next/static/01veEEO0MbroyjY72tWyr/_buildManifest.js +1 -0
  103. package/.next/static/chunks/7874-4f48b670898adf75.js +1 -0
  104. package/.next/static/chunks/9780-96bbb56af7ed70f1.js +1 -0
  105. package/.next/static/chunks/app/_global-error/page-212bed9d7023fb3f.js +1 -0
  106. package/.next/static/chunks/app/api/about/route-212bed9d7023fb3f.js +1 -0
  107. package/.next/static/chunks/app/api/agent/[id]/bash-output/route-212bed9d7023fb3f.js +1 -0
  108. package/.next/static/chunks/app/api/agent/[id]/events/route-212bed9d7023fb3f.js +1 -0
  109. package/.next/static/chunks/app/api/agent/[id]/route-212bed9d7023fb3f.js +1 -0
  110. package/.next/static/chunks/app/api/agent/new/route-212bed9d7023fb3f.js +1 -0
  111. package/.next/static/chunks/app/api/agent/running/events/route-212bed9d7023fb3f.js +1 -0
  112. package/.next/static/chunks/app/api/agent/running/route-212bed9d7023fb3f.js +1 -0
  113. package/.next/static/chunks/app/api/agent-settings/route-212bed9d7023fb3f.js +1 -0
  114. package/.next/static/chunks/app/api/attachments/route-212bed9d7023fb3f.js +1 -0
  115. package/.next/static/chunks/app/api/auth/all-providers/route-212bed9d7023fb3f.js +1 -0
  116. package/.next/static/chunks/app/api/auth/api-key/[provider]/route-212bed9d7023fb3f.js +1 -0
  117. package/.next/static/chunks/app/api/auth/login/[provider]/route-212bed9d7023fb3f.js +1 -0
  118. package/.next/static/chunks/app/api/auth/logout/[provider]/route-212bed9d7023fb3f.js +1 -0
  119. package/.next/static/chunks/app/api/auth/providers/route-212bed9d7023fb3f.js +1 -0
  120. package/.next/static/chunks/app/api/auth/ui-session/route-212bed9d7023fb3f.js +1 -0
  121. package/.next/static/chunks/app/api/cwd/browse/route-212bed9d7023fb3f.js +1 -0
  122. package/.next/static/chunks/app/api/cwd/validate/route-212bed9d7023fb3f.js +1 -0
  123. package/.next/static/chunks/app/api/default-cwd/route-212bed9d7023fb3f.js +1 -0
  124. package/.next/static/chunks/app/api/file-index/route-212bed9d7023fb3f.js +1 -0
  125. package/.next/static/chunks/app/api/files/[...path]/route-212bed9d7023fb3f.js +1 -0
  126. package/.next/static/chunks/app/api/git/diff/route-212bed9d7023fb3f.js +1 -0
  127. package/.next/static/chunks/app/api/git/status/route-212bed9d7023fb3f.js +1 -0
  128. package/.next/static/chunks/app/api/home/route-212bed9d7023fb3f.js +1 -0
  129. package/.next/static/chunks/app/api/models/route-212bed9d7023fb3f.js +1 -0
  130. package/.next/static/chunks/app/api/models-config/raw/route-212bed9d7023fb3f.js +1 -0
  131. package/.next/static/chunks/app/api/models-config/route-212bed9d7023fb3f.js +1 -0
  132. package/.next/static/chunks/app/api/models-config/test/route-212bed9d7023fb3f.js +1 -0
  133. package/.next/static/chunks/app/api/plugins/route-212bed9d7023fb3f.js +1 -0
  134. package/.next/static/chunks/app/api/plugins/search/route-212bed9d7023fb3f.js +1 -0
  135. package/.next/static/chunks/app/api/plugins/updates/route-212bed9d7023fb3f.js +1 -0
  136. package/.next/static/chunks/app/api/preferences/route-212bed9d7023fb3f.js +1 -0
  137. package/.next/static/chunks/app/api/project-assets/route-212bed9d7023fb3f.js +1 -0
  138. package/.next/static/chunks/app/api/prompts/route-212bed9d7023fb3f.js +1 -0
  139. package/.next/static/chunks/app/api/pty/route-212bed9d7023fb3f.js +1 -0
  140. package/.next/static/chunks/app/api/sessions/[id]/archive/route-212bed9d7023fb3f.js +1 -0
  141. package/.next/static/chunks/app/api/sessions/[id]/auto-name/route-212bed9d7023fb3f.js +1 -0
  142. package/.next/static/chunks/app/api/sessions/[id]/command-entry/route-212bed9d7023fb3f.js +1 -0
  143. package/.next/static/chunks/app/api/sessions/[id]/context/route-212bed9d7023fb3f.js +1 -0
  144. package/.next/static/chunks/app/api/sessions/[id]/entries/[entryId]/thinking/route-212bed9d7023fb3f.js +1 -0
  145. package/.next/static/chunks/app/api/sessions/[id]/export/route-212bed9d7023fb3f.js +1 -0
  146. package/.next/static/chunks/app/api/sessions/[id]/info/route-212bed9d7023fb3f.js +1 -0
  147. package/.next/static/chunks/app/api/sessions/[id]/route-212bed9d7023fb3f.js +1 -0
  148. package/.next/static/chunks/app/api/sessions/[id]/state/route-212bed9d7023fb3f.js +1 -0
  149. package/.next/static/chunks/app/api/sessions/[id]/tool-results/[toolCallId]/route-212bed9d7023fb3f.js +1 -0
  150. package/.next/static/chunks/app/api/sessions/route-212bed9d7023fb3f.js +1 -0
  151. package/.next/static/chunks/app/api/sessions/search/route-212bed9d7023fb3f.js +1 -0
  152. package/.next/static/chunks/app/api/settings/raw/route-212bed9d7023fb3f.js +1 -0
  153. package/.next/static/chunks/app/api/skills/check/route-212bed9d7023fb3f.js +1 -0
  154. package/.next/static/chunks/app/api/skills/install/route-212bed9d7023fb3f.js +1 -0
  155. package/.next/static/chunks/app/api/skills/route-212bed9d7023fb3f.js +1 -0
  156. package/.next/static/chunks/app/api/skills/search/route-212bed9d7023fb3f.js +1 -0
  157. package/.next/static/chunks/app/api/skills/update/route-212bed9d7023fb3f.js +1 -0
  158. package/.next/static/chunks/app/api/subagent-runs/route-212bed9d7023fb3f.js +1 -0
  159. package/.next/static/chunks/app/api/update/apply/route-212bed9d7023fb3f.js +1 -0
  160. package/.next/static/chunks/app/api/update/check/route-212bed9d7023fb3f.js +1 -0
  161. package/.next/static/chunks/app/api/worktrees/route-212bed9d7023fb3f.js +1 -0
  162. package/.next/static/chunks/app/page-c76a709acf636b23.js +25 -0
  163. package/.next/static/chunks/e868780c-16e43c5968ccf2bf.js +18 -0
  164. package/.next/static/chunks/next/dist/client/components/builtin/app-error-212bed9d7023fb3f.js +1 -0
  165. package/.next/static/chunks/next/dist/client/components/builtin/forbidden-212bed9d7023fb3f.js +1 -0
  166. package/.next/static/chunks/next/dist/client/components/builtin/not-found-212bed9d7023fb3f.js +1 -0
  167. package/.next/static/chunks/next/dist/client/components/builtin/unauthorized-212bed9d7023fb3f.js +1 -0
  168. package/.next/static/chunks/{webpack-9f5e68be126b5e81.js → webpack-d2379fd13c5c78c6.js} +1 -1
  169. package/.next/static/css/659eccb5db697b76.css +1 -0
  170. package/.next/static/css/{6faea79e75763a6a.css → b890757d9e0dd456.css} +1 -1
  171. package/README.md +1 -1
  172. package/bin/pidance-http-server.js +101 -0
  173. package/bin/pidance.js +45 -74
  174. package/bin/pty-manager.cjs +149 -0
  175. package/bin/pty-worker.js +48 -0
  176. package/bin/pty-ws.js +271 -0
  177. package/package.json +13 -3
  178. package/.next/static/HW-Jlwn4MNQKUjCkayKg3/_buildManifest.js +0 -1
  179. package/.next/static/chunks/1-a030cc9570b4428a.js +0 -1
  180. package/.next/static/chunks/9780-6931a654abc0ac16.js +0 -1
  181. package/.next/static/chunks/app/_global-error/page-c74291295bcd24a9.js +0 -1
  182. package/.next/static/chunks/app/api/about/route-c74291295bcd24a9.js +0 -1
  183. package/.next/static/chunks/app/api/agent/[id]/bash-output/route-c74291295bcd24a9.js +0 -1
  184. package/.next/static/chunks/app/api/agent/[id]/events/route-c74291295bcd24a9.js +0 -1
  185. package/.next/static/chunks/app/api/agent/[id]/route-c74291295bcd24a9.js +0 -1
  186. package/.next/static/chunks/app/api/agent/new/route-c74291295bcd24a9.js +0 -1
  187. package/.next/static/chunks/app/api/agent/running/events/route-c74291295bcd24a9.js +0 -1
  188. package/.next/static/chunks/app/api/agent/running/route-c74291295bcd24a9.js +0 -1
  189. package/.next/static/chunks/app/api/agent-settings/route-c74291295bcd24a9.js +0 -1
  190. package/.next/static/chunks/app/api/attachments/route-c74291295bcd24a9.js +0 -1
  191. package/.next/static/chunks/app/api/auth/all-providers/route-c74291295bcd24a9.js +0 -1
  192. package/.next/static/chunks/app/api/auth/api-key/[provider]/route-c74291295bcd24a9.js +0 -1
  193. package/.next/static/chunks/app/api/auth/login/[provider]/route-c74291295bcd24a9.js +0 -1
  194. package/.next/static/chunks/app/api/auth/logout/[provider]/route-c74291295bcd24a9.js +0 -1
  195. package/.next/static/chunks/app/api/auth/providers/route-c74291295bcd24a9.js +0 -1
  196. package/.next/static/chunks/app/api/auth/ui-session/route-c74291295bcd24a9.js +0 -1
  197. package/.next/static/chunks/app/api/cwd/browse/route-c74291295bcd24a9.js +0 -1
  198. package/.next/static/chunks/app/api/cwd/validate/route-c74291295bcd24a9.js +0 -1
  199. package/.next/static/chunks/app/api/default-cwd/route-c74291295bcd24a9.js +0 -1
  200. package/.next/static/chunks/app/api/file-index/route-c74291295bcd24a9.js +0 -1
  201. package/.next/static/chunks/app/api/files/[...path]/route-c74291295bcd24a9.js +0 -1
  202. package/.next/static/chunks/app/api/git/diff/route-c74291295bcd24a9.js +0 -1
  203. package/.next/static/chunks/app/api/git/status/route-c74291295bcd24a9.js +0 -1
  204. package/.next/static/chunks/app/api/home/route-c74291295bcd24a9.js +0 -1
  205. package/.next/static/chunks/app/api/models/route-c74291295bcd24a9.js +0 -1
  206. package/.next/static/chunks/app/api/models-config/raw/route-c74291295bcd24a9.js +0 -1
  207. package/.next/static/chunks/app/api/models-config/route-c74291295bcd24a9.js +0 -1
  208. package/.next/static/chunks/app/api/models-config/test/route-c74291295bcd24a9.js +0 -1
  209. package/.next/static/chunks/app/api/plugins/route-c74291295bcd24a9.js +0 -1
  210. package/.next/static/chunks/app/api/plugins/search/route-c74291295bcd24a9.js +0 -1
  211. package/.next/static/chunks/app/api/plugins/updates/route-c74291295bcd24a9.js +0 -1
  212. package/.next/static/chunks/app/api/preferences/route-c74291295bcd24a9.js +0 -1
  213. package/.next/static/chunks/app/api/project-assets/route-c74291295bcd24a9.js +0 -1
  214. package/.next/static/chunks/app/api/prompts/route-c74291295bcd24a9.js +0 -1
  215. package/.next/static/chunks/app/api/sessions/[id]/archive/route-c74291295bcd24a9.js +0 -1
  216. package/.next/static/chunks/app/api/sessions/[id]/auto-name/route-c74291295bcd24a9.js +0 -1
  217. package/.next/static/chunks/app/api/sessions/[id]/command-entry/route-c74291295bcd24a9.js +0 -1
  218. package/.next/static/chunks/app/api/sessions/[id]/context/route-c74291295bcd24a9.js +0 -1
  219. package/.next/static/chunks/app/api/sessions/[id]/entries/[entryId]/thinking/route-c74291295bcd24a9.js +0 -1
  220. package/.next/static/chunks/app/api/sessions/[id]/export/route-c74291295bcd24a9.js +0 -1
  221. package/.next/static/chunks/app/api/sessions/[id]/info/route-c74291295bcd24a9.js +0 -1
  222. package/.next/static/chunks/app/api/sessions/[id]/route-c74291295bcd24a9.js +0 -1
  223. package/.next/static/chunks/app/api/sessions/[id]/state/route-c74291295bcd24a9.js +0 -1
  224. package/.next/static/chunks/app/api/sessions/[id]/tool-results/[toolCallId]/route-c74291295bcd24a9.js +0 -1
  225. package/.next/static/chunks/app/api/sessions/route-c74291295bcd24a9.js +0 -1
  226. package/.next/static/chunks/app/api/sessions/search/route-c74291295bcd24a9.js +0 -1
  227. package/.next/static/chunks/app/api/settings/raw/route-c74291295bcd24a9.js +0 -1
  228. package/.next/static/chunks/app/api/skills/check/route-c74291295bcd24a9.js +0 -1
  229. package/.next/static/chunks/app/api/skills/install/route-c74291295bcd24a9.js +0 -1
  230. package/.next/static/chunks/app/api/skills/route-c74291295bcd24a9.js +0 -1
  231. package/.next/static/chunks/app/api/skills/search/route-c74291295bcd24a9.js +0 -1
  232. package/.next/static/chunks/app/api/skills/update/route-c74291295bcd24a9.js +0 -1
  233. package/.next/static/chunks/app/api/subagent-runs/route-c74291295bcd24a9.js +0 -1
  234. package/.next/static/chunks/app/api/update/apply/route-c74291295bcd24a9.js +0 -1
  235. package/.next/static/chunks/app/api/update/check/route-c74291295bcd24a9.js +0 -1
  236. package/.next/static/chunks/app/api/worktrees/route-c74291295bcd24a9.js +0 -1
  237. package/.next/static/chunks/app/page-dc174ab4b86d5192.js +0 -25
  238. package/.next/static/chunks/next/dist/client/components/builtin/app-error-c74291295bcd24a9.js +0 -1
  239. package/.next/static/chunks/next/dist/client/components/builtin/forbidden-c74291295bcd24a9.js +0 -1
  240. package/.next/static/chunks/next/dist/client/components/builtin/not-found-c74291295bcd24a9.js +0 -1
  241. package/.next/static/chunks/next/dist/client/components/builtin/unauthorized-c74291295bcd24a9.js +0 -1
  242. /package/.next/static/{HW-Jlwn4MNQKUjCkayKg3 → 01veEEO0MbroyjY72tWyr}/_ssgManifest.js +0 -0
@@ -0,0 +1,149 @@
1
+ "use strict";
2
+ /* eslint-disable @typescript-eslint/no-require-imports */
3
+
4
+ const { existsSync, realpathSync } = require("fs");
5
+ const { WebSocketServer } = require("ws");
6
+ const ptyWss = new WebSocketServer({ noServer: true });
7
+
8
+ function sanitizeEnv(env) {
9
+ const next = { ...env };
10
+ delete next.PI_WEB_PASSWORD;
11
+ delete next.PIDANCE_PASSWORD;
12
+ return next;
13
+ }
14
+
15
+ function tryLoadNodePty() {
16
+ try {
17
+ const loaded = require("node-pty");
18
+ if (typeof loaded.spawn !== "function") return null;
19
+ return loaded;
20
+ } catch {
21
+ return null;
22
+ }
23
+ }
24
+
25
+ function resolvePtyCwd(cwd) {
26
+ if (!existsSync(cwd)) throw new Error("PTY cwd 不存在");
27
+ return realpathSync(cwd);
28
+ }
29
+
30
+ function startPtySession(options) {
31
+ const spawner = options.pty === undefined ? tryLoadNodePty() : options.pty;
32
+ if (!spawner) throw new Error("node-pty 不可用");
33
+ const cwd = resolvePtyCwd(options.cwd);
34
+ const cols = options.cols && options.cols > 0 ? options.cols : 80;
35
+ const rows = options.rows && options.rows > 0 ? options.rows : 24;
36
+ const shell = process.env.SHELL && process.env.SHELL.length > 0 ? process.env.SHELL : "/bin/bash";
37
+ const proc = spawner.spawn(shell, [], {
38
+ name: "xterm-256color",
39
+ cols,
40
+ rows,
41
+ cwd,
42
+ env: sanitizeEnv(options.env ?? process.env),
43
+ });
44
+ let disposed = false;
45
+ const onChunk = (data) => {
46
+ if (!disposed) {
47
+ const text = typeof data === "string" ? data : data.toString();
48
+ options.onData(text);
49
+ }
50
+ };
51
+ if (typeof proc.on === "function") proc.on("data", onChunk);
52
+ else if (typeof proc.onData === "function") proc.onData(onChunk);
53
+ const onGone = (e) => {
54
+ if (!disposed) options.onExit(typeof e === "object" && e ? e.exitCode : 0);
55
+ };
56
+ if (typeof proc.on === "function") proc.on("exit", onGone);
57
+ else if (typeof proc.onExit === "function") proc.onExit(onGone);
58
+ return {
59
+ pid: proc.pid,
60
+ write: (data) => {
61
+ if (!disposed) proc.write(data);
62
+ },
63
+ resize: (nextCols, nextRows) => {
64
+ if (!disposed && nextCols > 0 && nextRows > 0) proc.resize(nextCols, nextRows);
65
+ },
66
+ dispose: () => {
67
+ if (disposed) return;
68
+ disposed = true;
69
+ try {
70
+ if (proc.pid > 0) process.kill(-proc.pid, "SIGTERM");
71
+ } catch {
72
+ /* 进程组可能已不在 */
73
+ }
74
+ try {
75
+ proc.kill("SIGTERM");
76
+ } catch {
77
+ /* 已退出 */
78
+ }
79
+ },
80
+ };
81
+ }
82
+
83
+ function attachPtyToWebSocket(ws, cwd) {
84
+ const { spawn } = require("child_process");
85
+ const path = require("path");
86
+ const workerPath = path.join(__dirname, "pty-worker.js");
87
+ const child = spawn(process.execPath, [workerPath, cwd, "80", "24"], {
88
+ stdio: ["pipe", "pipe", "pipe"],
89
+ env: process.env,
90
+ });
91
+ child.stderr.setEncoding("utf8");
92
+ child.stderr.on("data", (data) => console.warn("[pidance] pty-worker stderr", data));
93
+ child.on("error", (error) => console.warn("[pidance] pty-worker spawn", error.message));
94
+ const session = {
95
+ pid: child.pid,
96
+ write: (data) => child.stdin.write(`${JSON.stringify({ type: "in", d: data })}\n`),
97
+ resize: (cols, rows) => child.stdin.write(`${JSON.stringify({ type: "rs", cols, rows })}\n`),
98
+ dispose: () => {
99
+ try { child.kill("SIGTERM"); } catch { /* ignore */ }
100
+ },
101
+ };
102
+ child.stdout.setEncoding("utf8");
103
+ // pty-worker 输出按 JSON Lines 帧化:{type:"out",d:...},避免与终端原始输出混淆。
104
+ let stdoutBuf = "";
105
+ child.stdout.on("data", (data) => {
106
+ stdoutBuf += typeof data === "string" ? data : Buffer.from(data).toString("utf8");
107
+ let idx;
108
+ while ((idx = stdoutBuf.indexOf("\n")) >= 0) {
109
+ const line = stdoutBuf.slice(0, idx);
110
+ stdoutBuf = stdoutBuf.slice(idx + 1);
111
+ if (!line) continue;
112
+ try {
113
+ const msg = JSON.parse(line);
114
+ if (msg && msg.type === "out" && typeof msg.d === "string") {
115
+ // 统一用 JSON 帧发给浏览器,避免普通输出与控制消息混淆。
116
+ ws.send(JSON.stringify({ type: "out", d: msg.d }));
117
+ }
118
+ } catch { /* 非 JSON 的旧协议输出,尽量原样转发 */ try { ws.send(line); } catch { /* ignore */ } }
119
+ }
120
+ });
121
+ child.on("exit", (code) => {
122
+ try {
123
+ if (ws.readyState === 1) {
124
+ ws.send(JSON.stringify({ type: "exit", code: code ?? 0 }));
125
+ ws.close();
126
+ }
127
+ } catch { /* ignore */ }
128
+ });
129
+ ws.on("message", (raw) => {
130
+ const text = typeof raw === "string" ? raw : raw.toString();
131
+ let parsed;
132
+ try { parsed = JSON.parse(text); } catch { return; }
133
+ if (parsed && parsed.type === "in" && typeof parsed.d === "string") session.write(parsed.d);
134
+ if (parsed && parsed.type === "rs" && parsed.cols > 0 && parsed.rows > 0) session.resize(parsed.cols, parsed.rows);
135
+ });
136
+ ws.on("close", () => session.dispose());
137
+ ws.on("error", () => session.dispose());
138
+ try { ws.send(JSON.stringify({ type: "out", d: "\r\n[pidance] terminal ready\r\n" })); } catch { /* ignore */ }
139
+ return session;
140
+ }
141
+
142
+ function completePtyUpgrade(req, socket, head, cwd) {
143
+ ptyWss.handleUpgrade(req, socket, head, (ws) => {
144
+ ptyWss.emit("connection", ws, req);
145
+ attachPtyToWebSocket(ws, cwd);
146
+ });
147
+ }
148
+
149
+ module.exports = { startPtySession, tryLoadNodePty, resolvePtyCwd, attachPtyToWebSocket, completePtyUpgrade };
@@ -0,0 +1,48 @@
1
+ "use strict";
2
+ /* eslint-disable @typescript-eslint/no-require-imports */
3
+
4
+ const pty = require("node-pty");
5
+
6
+ const cwd = process.argv[2] || process.cwd();
7
+ const cols = Number(process.argv[3]) || 80;
8
+ const rows = Number(process.argv[4]) || 24;
9
+ const shell = process.env.SHELL && process.env.SHELL.length > 0 ? process.env.SHELL : "/bin/bash";
10
+ const env = { ...process.env };
11
+ delete env.PI_WEB_PASSWORD;
12
+ delete env.PIDANCE_PASSWORD;
13
+
14
+ const proc = pty.spawn(shell, [], {
15
+ name: "xterm-256color",
16
+ cols,
17
+ rows,
18
+ cwd,
19
+ env,
20
+ });
21
+
22
+ proc.onData((data) => {
23
+ process.stdout.write(JSON.stringify({ type: "out", d: data }) + "\n");
24
+ });
25
+ proc.onExit((e) => {
26
+ process.exit(e.exitCode ?? 0);
27
+ });
28
+
29
+ process.stdin.setEncoding("utf8");
30
+ let buf = "";
31
+ process.stdin.on("data", (chunk) => {
32
+ buf += chunk;
33
+ let idx;
34
+ while ((idx = buf.indexOf("\n")) >= 0) {
35
+ const line = buf.slice(0, idx);
36
+ buf = buf.slice(idx + 1);
37
+ if (!line) continue;
38
+ let msg;
39
+ try { msg = JSON.parse(line); } catch { continue; }
40
+ if (msg.type === "in" && typeof msg.d === "string") proc.write(msg.d);
41
+ if (msg.type === "rs" && msg.cols > 0 && msg.rows > 0) proc.resize(msg.cols, msg.rows);
42
+ }
43
+ });
44
+
45
+ process.on("SIGTERM", () => {
46
+ try { proc.kill("SIGTERM"); } catch { /* ignore */ }
47
+ process.exit(0);
48
+ });
package/bin/pty-ws.js ADDED
@@ -0,0 +1,271 @@
1
+ "use strict";
2
+
3
+ // Pidance PTY WebSocket upgrade 处理器(发布包自包含:不依赖 lib/ 源码树)。
4
+ // 守卫逻辑与 lib/request-guard.ts / lib/ui-session.ts 保持一致的精简内联版:
5
+ // - Host 白名单(DNS rebinding 防护)
6
+ // - 可选认证:PIDANCE_PASSWORD / PI_WEB_PASSWORD 启用时接受 UI 会话 Cookie(JWT)或 Basic
7
+ // - 兜底:未设置密码时仅放行回环请求(fail-closed)
8
+ // WebSocket 升级不做 CSRF 校验:部分手机浏览器 Origin / sec-fetch 不完整。
9
+
10
+ /* eslint-disable @typescript-eslint/no-require-imports */
11
+ const { existsSync } = require("fs");
12
+ const { homedir } = require("os");
13
+ const { createHash, createHmac, randomBytes, timingSafeEqual } = require("crypto");
14
+ const { isIP } = require("net");
15
+ const fs = require("fs");
16
+ const path = require("path");
17
+ const { tryLoadNodePty, completePtyUpgrade } = require("./pty-manager.cjs");
18
+
19
+ // ── Host 白名单(对齐 lib/request-guard.ts)──────────────────────────────
20
+
21
+ function normalizeHostname(hostname) {
22
+ return (hostname.startsWith("[") && hostname.endsWith("]") ? hostname.slice(1, -1) : hostname)
23
+ .toLowerCase()
24
+ .replace(/\.$/, "");
25
+ }
26
+
27
+ function hostnameFromHostHeader(host) {
28
+ if (!host || /[\s/@\\]/.test(host)) return null;
29
+ try {
30
+ const url = new URL(`http://${host}`);
31
+ if (url.username || url.password || url.pathname !== "/" || url.search || url.hash) return null;
32
+ return normalizeHostname(url.hostname);
33
+ } catch {
34
+ return null;
35
+ }
36
+ }
37
+
38
+ function allowedHosts(env) {
39
+ return [
40
+ env.PI_WEB_HOSTNAME,
41
+ ...(env.PI_WEB_ALLOWED_HOSTS ? String(env.PI_WEB_ALLOWED_HOSTS).split(",") : []),
42
+ ]
43
+ .filter((h) => typeof h === "string" && h.trim().length > 0)
44
+ .map((h) => h.trim());
45
+ }
46
+
47
+ function isTrustedHost(hostHeader, env) {
48
+ const hostname = hostHeader ? hostnameFromHostHeader(hostHeader) : null;
49
+ if (!hostname) return false;
50
+ if (hostname === "localhost" || hostname.endsWith(".localhost") || isIP(hostname) !== 0) return true;
51
+ const names = allowedHosts(env)
52
+ .map((h) => hostnameFromHostHeader(h))
53
+ .filter((n) => n !== null);
54
+ return names.includes(hostname);
55
+ }
56
+
57
+ function isLoopbackHost(hostHeader) {
58
+ const hostname = hostHeader ? hostnameFromHostHeader(hostHeader) : null;
59
+ if (!hostname) return false;
60
+ if (hostname === "localhost" || hostname.endsWith(".localhost")) return true;
61
+ const ip = isIP(hostname);
62
+ if (ip === 4) return hostname.startsWith("127.");
63
+ if (ip === 6) return hostname === "::1" || hostname === "0:0:0:0:0:0:0:1";
64
+ return false;
65
+ }
66
+
67
+ // ── 认证(对齐 lib/request-guard.ts + lib/ui-session.ts 精简版)────────────
68
+
69
+ const UI_SESSION_COOKIE_NAME = "pidance_ui_session";
70
+
71
+ function resolvePassword(env) {
72
+ const p =
73
+ env && env.PIDANCE_PASSWORD && env.PIDANCE_PASSWORD.length > 0
74
+ ? env.PIDANCE_PASSWORD
75
+ : env && env.PI_WEB_PASSWORD;
76
+ return typeof p === "string" && p.length > 0 ? p : null;
77
+ }
78
+
79
+ function passwordEnabled(env) {
80
+ return resolvePassword(env) !== null;
81
+ }
82
+
83
+ function sha256(input) {
84
+ return createHash("sha256").update(input, "utf8").digest();
85
+ }
86
+
87
+ function safeEqual(a, b) {
88
+ return timingSafeEqual(sha256(a), sha256(b));
89
+ }
90
+
91
+ function checkBasicAuth(headers, env) {
92
+ const password = resolvePassword(env);
93
+ if (!passwordEnabled(env) || !password) return false;
94
+ const auth = headers.authorization;
95
+ if (!auth) return false;
96
+ const match = /^Basic\s+(\S+)$/i.exec(auth);
97
+ if (!match) return false;
98
+ let decoded;
99
+ try {
100
+ const buf = Buffer.from(match[1], "base64");
101
+ if (buf.toString("base64") !== match[1]) return false;
102
+ decoded = new TextDecoder("utf-8", { fatal: true }).decode(buf);
103
+ } catch {
104
+ return false;
105
+ }
106
+ const idx = decoded.indexOf(":");
107
+ if (idx === -1) return false;
108
+ return safeEqual(decoded.slice(0, idx), "pi") && safeEqual(decoded.slice(idx + 1), password);
109
+ }
110
+
111
+ function parseCookieValue(cookieHeader, name) {
112
+ if (!cookieHeader) return null;
113
+ for (const part of String(cookieHeader).split(";")) {
114
+ const idx = part.indexOf("=");
115
+ if (idx <= 0) continue;
116
+ const key = part.slice(0, idx).trim();
117
+ if (key !== name) continue;
118
+ const raw = part.slice(idx + 1).trim();
119
+ try {
120
+ return decodeURIComponent(raw);
121
+ } catch {
122
+ return raw;
123
+ }
124
+ }
125
+ return null;
126
+ }
127
+
128
+ function defaultSecretFilePath() {
129
+ const root = process.env.PI_CODING_AGENT_DIR || path.join(homedir(), ".pi", "agent");
130
+ return path.join(root, "pidance-ui-jwt-secret");
131
+ }
132
+
133
+ function getOrCreateJwtSecret(env) {
134
+ const fromEnv = env.PIDANCE_UI_JWT_SECRET || env.OPENCODE_JWT_SECRET;
135
+ if (typeof fromEnv === "string" && fromEnv.length > 0) return fromEnv.trim();
136
+ const filePath = defaultSecretFilePath();
137
+ try {
138
+ if (fs.existsSync(filePath)) {
139
+ const existing = fs.readFileSync(filePath, "utf8").trim();
140
+ if (existing) return existing;
141
+ }
142
+ } catch {
143
+ // 读失败则重建
144
+ }
145
+ const secret = randomBytes(32).toString("hex");
146
+ try {
147
+ fs.mkdirSync(path.dirname(filePath), { recursive: true });
148
+ fs.writeFileSync(filePath, secret, { mode: 0o600 });
149
+ } catch {
150
+ // 无法落盘时仍返回内存密钥(进程内有效)
151
+ }
152
+ return secret;
153
+ }
154
+
155
+ function verifyUiSessionJwt(token, secret, nowMs) {
156
+ if (!token || !secret) return false;
157
+ const parts = token.split(".");
158
+ if (parts.length !== 3) return false;
159
+ const [header, payload, sig] = parts;
160
+ const data = `${header}.${payload}`;
161
+ const expected = createHmac("sha256", secret).update(data).digest();
162
+ let actual;
163
+ try {
164
+ actual = Buffer.from(sig, "base64url");
165
+ } catch {
166
+ return false;
167
+ }
168
+ if (actual.length !== expected.length || !timingSafeEqual(actual, expected)) return false;
169
+ try {
170
+ const body = JSON.parse(Buffer.from(payload, "base64url").toString("utf8"));
171
+ if (body.type !== "ui-session") return false;
172
+ if (typeof body.exp !== "number" || body.exp * 1000 <= nowMs) return false;
173
+ return true;
174
+ } catch {
175
+ return false;
176
+ }
177
+ }
178
+
179
+ function checkUiSessionCookie(headers, env) {
180
+ if (!passwordEnabled(env)) return false;
181
+ const token = parseCookieValue(headers.cookie, UI_SESSION_COOKIE_NAME);
182
+ if (!token) return false;
183
+ return verifyUiSessionJwt(token, getOrCreateJwtSecret(env), Date.now());
184
+ }
185
+
186
+ function checkAuthenticated(headers, env) {
187
+ return checkUiSessionCookie(headers, env) || checkBasicAuth(headers, env);
188
+ }
189
+
190
+ // ── upgrade 处理(原 lib/pty-ws.ts)─────────────────────────────────────
191
+
192
+ function header(req, name) {
193
+ const value = req.headers[name];
194
+ if (typeof value === "string") return value;
195
+ if (Array.isArray(value) && typeof value[0] === "string") return value[0];
196
+ return null;
197
+ }
198
+
199
+ function ptyGuardHeaders(req) {
200
+ const host = header(req, "host");
201
+ const rawUrl = req.url || "/api/pty";
202
+ const url = `http://${host || "127.0.0.1"}${rawUrl}`;
203
+ let pathname = "/api/pty";
204
+ try {
205
+ pathname = new URL(url).pathname;
206
+ } catch {
207
+ // 用默认
208
+ }
209
+ return {
210
+ host,
211
+ origin: header(req, "origin"),
212
+ secFetchSite: header(req, "sec-fetch-site"),
213
+ secFetchMode: header(req, "sec-fetch-mode"),
214
+ secFetchDest: header(req, "sec-fetch-dest"),
215
+ secFetchUser: header(req, "sec-fetch-user"),
216
+ authorization: header(req, "authorization"),
217
+ cookie: header(req, "cookie"),
218
+ method: "GET",
219
+ url,
220
+ pathname,
221
+ };
222
+ }
223
+
224
+ function reject(socket, status, message) {
225
+ try {
226
+ socket.write(`HTTP/1.1 ${status} ${message}\r\nConnection: close\r\nContent-Length: 0\r\n\r\n`);
227
+ } catch {
228
+ // ignore
229
+ }
230
+ try {
231
+ socket.destroy();
232
+ } catch {
233
+ // ignore
234
+ }
235
+ }
236
+
237
+ async function handlePtyUpgrade(req, socket, head) {
238
+ if (!tryLoadNodePty()) {
239
+ reject(socket, 503, "PTY Unavailable");
240
+ return;
241
+ }
242
+ const guardHeaders = ptyGuardHeaders(req);
243
+ if (!guardHeaders.pathname.startsWith("/api/pty")) {
244
+ reject(socket, 404, "Not Found");
245
+ return;
246
+ }
247
+ // WebSocket 升级:部分手机浏览器 Origin / sec-fetch 不完整,CSRF 会误杀。
248
+ // 仍校验 Host 白名单和登录(Cookie / Basic)。
249
+ if (!isTrustedHost(guardHeaders.host, process.env)) {
250
+ reject(socket, 403, "untrusted-host");
251
+ return;
252
+ }
253
+ if (passwordEnabled(process.env)) {
254
+ if (!checkAuthenticated(guardHeaders, process.env)) {
255
+ reject(socket, 401, "auth-required");
256
+ return;
257
+ }
258
+ } else if (!isLoopbackHost(guardHeaders.host)) {
259
+ // fail-closed 兜底:未设密码时仅放行回环请求(与 middleware 一致)。
260
+ reject(socket, 401, "auth-required");
261
+ return;
262
+ }
263
+ const cwd = homedir();
264
+ if (!existsSync(cwd)) {
265
+ reject(socket, 500, "home not found");
266
+ return;
267
+ }
268
+ completePtyUpgrade(req, socket, head, cwd);
269
+ }
270
+
271
+ module.exports = { handlePtyUpgrade, ptyGuardHeaders };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@henlii/pidance",
3
- "version": "0.2.6",
3
+ "version": "0.2.7",
4
4
  "description": "Pidance:面向 Pi coding agent 的开源 Web 客户端",
5
5
  "homepage": "https://github.com/henlii/pidance#readme",
6
6
  "repository": {
@@ -44,24 +44,30 @@
44
44
  "scripts": {
45
45
  "dev": "next dev -p 31415",
46
46
  "build": "next build --webpack",
47
- "start": "next start -p 31415",
47
+ "start": "node bin/pidance.js",
48
48
  "lint": "eslint .",
49
49
  "typecheck": "tsc --noEmit",
50
50
  "test": "node --test lib/*.test.mjs components/*.test.mjs hooks/*.test.mjs bin/*.test.mjs",
51
51
  "verify:render-bridge": "node scripts/verify-subagent-render-bridge.mjs",
52
+ "verify:render-bridge:installed": "node scripts/verify-installed-render-bridge.mjs",
52
53
  "test:browser": "node --test scripts/browser-regression.test.mjs",
53
54
  "check": "npm run typecheck && npm run lint && npm run test",
54
55
  "release:audit": "node scripts/audit-release-package.mjs --pre",
55
56
  "release:audit:tgz": "node scripts/audit-release-package.mjs --tgz",
57
+ "package:candidate": "node scripts/make-candidate-package.mjs",
56
58
  "release:check": "npm run check && npm run build && npm run release:audit"
57
59
  },
58
60
  "dependencies": {
59
61
  "@earendil-works/pi-coding-agent": "0.84.1",
62
+ "@xterm/addon-fit": "^0.11.0",
63
+ "@xterm/xterm": "^6.0.0",
64
+ "jiti": "^2.7.0",
60
65
  "lucide-react": "^0.562.0",
61
66
  "next": "16.2.11",
62
67
  "react": "^19.2.4",
63
68
  "react-dom": "^19.2.4",
64
- "undici": "8.5.0"
69
+ "undici": "8.5.0",
70
+ "ws": "^8.21.3"
65
71
  },
66
72
  "devDependencies": {
67
73
  "@lobehub/icons": "^5.6.0",
@@ -70,6 +76,7 @@
70
76
  "@types/react": "^19",
71
77
  "@types/react-dom": "^19",
72
78
  "@types/react-syntax-highlighter": "^15.5.13",
79
+ "@types/ws": "^8.18.1",
73
80
  "eslint": "^9",
74
81
  "eslint-config-next": "16.2.11",
75
82
  "jiti": "^2.7.0",
@@ -86,5 +93,8 @@
86
93
  "remark-math": "^6.0.0",
87
94
  "tailwindcss": "^4.2.2",
88
95
  "typescript": "^5"
96
+ },
97
+ "optionalDependencies": {
98
+ "node-pty": "^1.1.0"
89
99
  }
90
100
  }
@@ -1 +0,0 @@
1
- self.__BUILD_MANIFEST={__rewrites:{afterFiles:[],beforeFiles:[],fallback:[]},__routerFilterStatic:{numItems:42,errorRate:1e-4,numBits:806,numHashes:14,bitArray:[1,0,0,1,0,0,0,1,0,0,0,0,0,0,1,0,0,1,0,0,1,0,1,0,1,1,1,1,0,0,1,0,0,1,1,0,0,0,1,1,1,1,1,0,1,1,0,1,1,0,1,0,0,1,1,0,1,1,0,0,1,0,1,0,1,0,0,0,1,0,1,1,0,0,1,0,1,0,0,0,0,1,0,1,1,1,1,0,1,0,1,0,1,1,1,0,0,0,1,0,1,0,1,1,0,0,1,0,1,0,1,0,0,1,1,1,0,0,1,0,1,1,0,1,1,0,0,0,1,1,1,0,1,0,0,0,1,1,1,1,0,0,0,0,0,1,0,1,1,0,1,0,1,0,1,0,1,0,0,1,1,0,0,1,0,0,1,1,0,0,0,0,0,1,1,0,0,0,1,0,1,1,1,1,1,0,1,1,0,0,0,1,1,1,1,0,1,1,0,0,1,1,1,1,0,1,1,1,1,0,1,0,0,1,1,1,0,1,0,1,1,0,1,1,0,1,0,0,0,1,1,1,0,0,0,0,1,1,0,1,1,0,1,0,1,0,0,1,0,1,1,1,1,1,0,1,1,1,1,1,0,0,0,0,1,0,1,1,1,0,0,1,1,0,1,0,0,1,0,0,0,0,0,1,0,1,0,0,1,0,0,1,0,1,1,0,1,0,1,1,1,1,1,1,0,0,1,0,0,0,0,1,1,0,0,1,0,0,1,1,0,0,0,0,0,1,0,0,0,0,0,1,0,1,1,0,0,1,0,1,1,1,0,1,0,0,0,0,1,1,0,1,1,0,1,0,0,1,0,0,0,1,0,0,0,1,1,0,0,0,0,1,1,0,1,0,1,0,1,0,0,1,0,1,1,1,0,1,0,1,1,0,1,1,1,1,0,1,0,0,1,0,1,0,1,0,1,0,1,0,1,1,0,1,0,1,0,1,0,0,0,1,1,0,0,1,1,1,0,0,0,0,1,0,1,1,1,1,1,0,1,0,0,0,1,0,1,1,1,0,0,1,0,0,0,0,0,1,0,1,0,0,1,1,0,1,0,0,1,0,0,1,0,1,1,1,1,1,1,0,1,1,0,0,0,0,1,1,1,0,0,1,0,1,0,1,1,1,1,0,0,1,0,1,1,1,1,1,0,1,0,0,0,1,1,1,1,0,0,0,1,0,0,1,1,1,1,1,1,0,1,1,0,1,1,1,0,0,0,1,0,1,1,1,0,1,0,0,1,0,0,1,1,1,1,0,0,0,0,1,0,1,0,0,1,1,1,0,0,0,1,0,1,1,0,1,1,0,1,1,1,1,0,0,1,0,0,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,0,1,0,0,0,0,0,0,0,0,0,1,0,0,1,1,1,0,1,0,0,0,1,1,0,0,1,1,0,1,0,1,0,0,1,0,0,1,1,1,1,1,0,0,1,0,1,1,0,0,0,0,1,0,0,1,1,1,1,0,0,0,1,0,1,1,1,1,1,0,1,1,1,1,0,1,0,1,0,1,1,1,1,0,0,1,1,1,1,0,1,0,1,1,0,1,1,0,0,0,1,0,0,0,1,1,1,1,1,0,0,0,1,1,0,1,0,0,1,0,1,1,0,1,1,1,1,0,1,0,1,1,0,1,0,1,0,0,0,1,1,0,0,1,0,0,1,0,1,0,0,1,0,1,0,1,1,0,1,0,1,1,0,0,0,1,1,1,1,1,0,0,1,0,0,1,1,0,1,1,1,1,0,0,0,1,0,1,0,1,1,1,0,1,0,1,0,0,1,1,1,0,0,0]},__routerFilterDynamic:{numItems:6,errorRate:1e-4,numBits:116,numHashes:14,bitArray:[1,1,0,0,0,1,0,1,1,1,1,0,1,0,1,0,0,1,1,1,0,1,1,0,1,1,0,1,0,1,1,0,0,0,1,0,0,1,0,1,1,0,0,1,1,1,0,0,0,1,0,0,1,1,0,0,0,0,1,1,1,1,1,0,0,1,1,1,1,0,0,0,0,0,1,0,0,0,1,1,1,0,1,0,0,1,0,1,0,0,0,1,0,0,1,0,0,0,1,1,1,1,1,1,0,0,1,0,1,0,0,1,1,0,0,0]},sortedPages:["/_app"]},self.__BUILD_MANIFEST_CB&&self.__BUILD_MANIFEST_CB();