@pi-harness/pi-harness 0.1.22 → 0.1.23

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 (289) hide show
  1. package/README.md +1 -1
  2. package/apps/web/dist/assets/index-Bo9CNI_U.js +22 -0
  3. package/apps/web/dist/index.html +1 -1
  4. package/apps/web/package.json +6 -6
  5. package/apps/web/server-dist/bin.js +18 -5
  6. package/apps/web/server-dist/bin.js.map +1 -1
  7. package/apps/web/src/server/bin.ts +18 -5
  8. package/apps/web/test/bin.test.ts +90 -0
  9. package/node_modules/@pi-harness/api-gateway/dist/index.d.ts.map +1 -1
  10. package/node_modules/@pi-harness/api-gateway/dist/index.js +204 -66
  11. package/node_modules/@pi-harness/api-gateway/dist/index.js.map +1 -1
  12. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/agent-teams.json +1 -1
  13. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/anchored-standard.json +1 -1
  14. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/annotation.json +1 -1
  15. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/archify.json +1 -1
  16. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/at-file.json +1 -1
  17. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/auto-mode.json +1 -1
  18. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/better-sidebar.json +1 -1
  19. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/browser-fetch.json +1 -1
  20. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/browser-session.json +1 -1
  21. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/canvas-draw.json +1 -1
  22. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/change-verifier.json +1 -1
  23. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/cleaner.json +1 -1
  24. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/cli-notifier.json +1 -1
  25. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/code2skill.json +1 -1
  26. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/colleague-skill.json +1 -1
  27. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/context-doctor.json +1 -1
  28. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/context.json +1 -1
  29. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/cost-meter.json +1 -1
  30. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/dependency-checker.json +1 -1
  31. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/docker-sandbox.json +1 -1
  32. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/fail-logger.json +1 -1
  33. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/genui.json +1 -1
  34. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/git-time-capsule.json +1 -1
  35. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/graph-memory.json +1 -1
  36. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/history-compressor.json +1 -1
  37. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/hol-guard.json +3 -3
  38. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/i18n-pair.json +1 -1
  39. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/image-compressor.json +1 -1
  40. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/llm-verifier.json +1 -1
  41. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/mcp-client.json +1 -1
  42. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/mcp-panel.json +1 -1
  43. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/memory.json +1 -1
  44. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/mirage-bridge.json +1 -1
  45. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/mock-server.json +1 -1
  46. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/modlens.json +1 -1
  47. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/module-search.json +1 -1
  48. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/obsidian-sync.json +1 -1
  49. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/openpets.json +1 -1
  50. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/plan-execute.json +1 -1
  51. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/plugin-check.json +1 -1
  52. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/plugin-dev.json +1 -1
  53. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/plugin-finder.json +1 -1
  54. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/plugin-radar.json +1 -1
  55. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/plugin-stars.json +1 -1
  56. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/prompt-guard.json +1 -1
  57. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/prompt-library.json +1 -1
  58. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/readme-gen.json +1 -1
  59. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/recall-unread.json +1 -1
  60. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/reverse-skill.json +1 -1
  61. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/reviewer-bot.json +1 -1
  62. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/runtime-doctor.json +1 -1
  63. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/secure-audit.json +1 -1
  64. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/session-bookmarks.json +1 -1
  65. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/session-bridge.json +1 -1
  66. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/session-compare.json +1 -1
  67. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/session-export.json +1 -1
  68. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/session-insights.json +1 -1
  69. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/session-search.json +1 -1
  70. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/skill-catalog.json +1 -1
  71. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/skill-guard.json +1 -1
  72. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/sql-lens.json +1 -1
  73. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/synapse.json +1 -1
  74. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/tab-manager.json +1 -1
  75. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/taskboard.json +1 -1
  76. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/telemetry-blocker.json +1 -1
  77. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/test-harness.json +1 -1
  78. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/theme-studio.json +1 -1
  79. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/token-guard.json +1 -1
  80. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/turn-rewind.json +1 -1
  81. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/undo-savepoint.json +1 -1
  82. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/vision-toolkit.json +1 -1
  83. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/web-research.json +1 -1
  84. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/workspace-navigator.json +1 -1
  85. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/workspace-search.json +1 -1
  86. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/yaml-validator.json +1 -1
  87. package/node_modules/@pi-harness/api-gateway/package.json +1 -1
  88. package/node_modules/@pi-harness/cli/dist/node-stdio.d.ts.map +1 -1
  89. package/node_modules/@pi-harness/cli/dist/node-stdio.js +3 -1
  90. package/node_modules/@pi-harness/cli/dist/node-stdio.js.map +1 -1
  91. package/node_modules/@pi-harness/cli/dist/relaunch.d.ts.map +1 -1
  92. package/node_modules/@pi-harness/cli/dist/relaunch.js +6 -1
  93. package/node_modules/@pi-harness/cli/dist/relaunch.js.map +1 -1
  94. package/node_modules/@pi-harness/cli/package.json +1 -1
  95. package/node_modules/@pi-harness/host-webserver/dist/index.d.ts.map +1 -1
  96. package/node_modules/@pi-harness/host-webserver/dist/index.js +52 -3
  97. package/node_modules/@pi-harness/host-webserver/dist/index.js.map +1 -1
  98. package/node_modules/@pi-harness/host-webserver/package.json +1 -1
  99. package/node_modules/@pi-harness/web-app/dist/index.d.ts +3 -0
  100. package/node_modules/@pi-harness/web-app/dist/index.d.ts.map +1 -1
  101. package/node_modules/@pi-harness/web-app/dist/index.js +9 -5
  102. package/node_modules/@pi-harness/web-app/dist/index.js.map +1 -1
  103. package/node_modules/@pi-harness/web-app/package.json +1 -1
  104. package/package.json +7 -7
  105. package/packages/api-gateway/dist/index.d.ts.map +1 -1
  106. package/packages/api-gateway/dist/index.js +204 -66
  107. package/packages/api-gateway/dist/index.js.map +1 -1
  108. package/packages/api-gateway/dist/marketplace-entries/official/agent-teams.json +1 -1
  109. package/packages/api-gateway/dist/marketplace-entries/official/anchored-standard.json +1 -1
  110. package/packages/api-gateway/dist/marketplace-entries/official/annotation.json +1 -1
  111. package/packages/api-gateway/dist/marketplace-entries/official/archify.json +1 -1
  112. package/packages/api-gateway/dist/marketplace-entries/official/at-file.json +1 -1
  113. package/packages/api-gateway/dist/marketplace-entries/official/auto-mode.json +1 -1
  114. package/packages/api-gateway/dist/marketplace-entries/official/better-sidebar.json +1 -1
  115. package/packages/api-gateway/dist/marketplace-entries/official/browser-fetch.json +1 -1
  116. package/packages/api-gateway/dist/marketplace-entries/official/browser-session.json +1 -1
  117. package/packages/api-gateway/dist/marketplace-entries/official/canvas-draw.json +1 -1
  118. package/packages/api-gateway/dist/marketplace-entries/official/change-verifier.json +1 -1
  119. package/packages/api-gateway/dist/marketplace-entries/official/cleaner.json +1 -1
  120. package/packages/api-gateway/dist/marketplace-entries/official/cli-notifier.json +1 -1
  121. package/packages/api-gateway/dist/marketplace-entries/official/code2skill.json +1 -1
  122. package/packages/api-gateway/dist/marketplace-entries/official/colleague-skill.json +1 -1
  123. package/packages/api-gateway/dist/marketplace-entries/official/context-doctor.json +1 -1
  124. package/packages/api-gateway/dist/marketplace-entries/official/context.json +1 -1
  125. package/packages/api-gateway/dist/marketplace-entries/official/cost-meter.json +1 -1
  126. package/packages/api-gateway/dist/marketplace-entries/official/dependency-checker.json +1 -1
  127. package/packages/api-gateway/dist/marketplace-entries/official/docker-sandbox.json +1 -1
  128. package/packages/api-gateway/dist/marketplace-entries/official/fail-logger.json +1 -1
  129. package/packages/api-gateway/dist/marketplace-entries/official/genui.json +1 -1
  130. package/packages/api-gateway/dist/marketplace-entries/official/git-time-capsule.json +1 -1
  131. package/packages/api-gateway/dist/marketplace-entries/official/graph-memory.json +1 -1
  132. package/packages/api-gateway/dist/marketplace-entries/official/history-compressor.json +1 -1
  133. package/packages/api-gateway/dist/marketplace-entries/official/hol-guard.json +3 -3
  134. package/packages/api-gateway/dist/marketplace-entries/official/i18n-pair.json +1 -1
  135. package/packages/api-gateway/dist/marketplace-entries/official/image-compressor.json +1 -1
  136. package/packages/api-gateway/dist/marketplace-entries/official/llm-verifier.json +1 -1
  137. package/packages/api-gateway/dist/marketplace-entries/official/mcp-client.json +1 -1
  138. package/packages/api-gateway/dist/marketplace-entries/official/mcp-panel.json +1 -1
  139. package/packages/api-gateway/dist/marketplace-entries/official/memory.json +1 -1
  140. package/packages/api-gateway/dist/marketplace-entries/official/mirage-bridge.json +1 -1
  141. package/packages/api-gateway/dist/marketplace-entries/official/mock-server.json +1 -1
  142. package/packages/api-gateway/dist/marketplace-entries/official/modlens.json +1 -1
  143. package/packages/api-gateway/dist/marketplace-entries/official/module-search.json +1 -1
  144. package/packages/api-gateway/dist/marketplace-entries/official/obsidian-sync.json +1 -1
  145. package/packages/api-gateway/dist/marketplace-entries/official/openpets.json +1 -1
  146. package/packages/api-gateway/dist/marketplace-entries/official/plan-execute.json +1 -1
  147. package/packages/api-gateway/dist/marketplace-entries/official/plugin-check.json +1 -1
  148. package/packages/api-gateway/dist/marketplace-entries/official/plugin-dev.json +1 -1
  149. package/packages/api-gateway/dist/marketplace-entries/official/plugin-finder.json +1 -1
  150. package/packages/api-gateway/dist/marketplace-entries/official/plugin-radar.json +1 -1
  151. package/packages/api-gateway/dist/marketplace-entries/official/plugin-stars.json +1 -1
  152. package/packages/api-gateway/dist/marketplace-entries/official/prompt-guard.json +1 -1
  153. package/packages/api-gateway/dist/marketplace-entries/official/prompt-library.json +1 -1
  154. package/packages/api-gateway/dist/marketplace-entries/official/readme-gen.json +1 -1
  155. package/packages/api-gateway/dist/marketplace-entries/official/recall-unread.json +1 -1
  156. package/packages/api-gateway/dist/marketplace-entries/official/reverse-skill.json +1 -1
  157. package/packages/api-gateway/dist/marketplace-entries/official/reviewer-bot.json +1 -1
  158. package/packages/api-gateway/dist/marketplace-entries/official/runtime-doctor.json +1 -1
  159. package/packages/api-gateway/dist/marketplace-entries/official/secure-audit.json +1 -1
  160. package/packages/api-gateway/dist/marketplace-entries/official/session-bookmarks.json +1 -1
  161. package/packages/api-gateway/dist/marketplace-entries/official/session-bridge.json +1 -1
  162. package/packages/api-gateway/dist/marketplace-entries/official/session-compare.json +1 -1
  163. package/packages/api-gateway/dist/marketplace-entries/official/session-export.json +1 -1
  164. package/packages/api-gateway/dist/marketplace-entries/official/session-insights.json +1 -1
  165. package/packages/api-gateway/dist/marketplace-entries/official/session-search.json +1 -1
  166. package/packages/api-gateway/dist/marketplace-entries/official/skill-catalog.json +1 -1
  167. package/packages/api-gateway/dist/marketplace-entries/official/skill-guard.json +1 -1
  168. package/packages/api-gateway/dist/marketplace-entries/official/sql-lens.json +1 -1
  169. package/packages/api-gateway/dist/marketplace-entries/official/synapse.json +1 -1
  170. package/packages/api-gateway/dist/marketplace-entries/official/tab-manager.json +1 -1
  171. package/packages/api-gateway/dist/marketplace-entries/official/taskboard.json +1 -1
  172. package/packages/api-gateway/dist/marketplace-entries/official/telemetry-blocker.json +1 -1
  173. package/packages/api-gateway/dist/marketplace-entries/official/test-harness.json +1 -1
  174. package/packages/api-gateway/dist/marketplace-entries/official/theme-studio.json +1 -1
  175. package/packages/api-gateway/dist/marketplace-entries/official/token-guard.json +1 -1
  176. package/packages/api-gateway/dist/marketplace-entries/official/turn-rewind.json +1 -1
  177. package/packages/api-gateway/dist/marketplace-entries/official/undo-savepoint.json +1 -1
  178. package/packages/api-gateway/dist/marketplace-entries/official/vision-toolkit.json +1 -1
  179. package/packages/api-gateway/dist/marketplace-entries/official/web-research.json +1 -1
  180. package/packages/api-gateway/dist/marketplace-entries/official/workspace-navigator.json +1 -1
  181. package/packages/api-gateway/dist/marketplace-entries/official/workspace-search.json +1 -1
  182. package/packages/api-gateway/dist/marketplace-entries/official/yaml-validator.json +1 -1
  183. package/packages/api-gateway/package.json +1 -1
  184. package/packages/api-gateway/src/index.ts +227 -68
  185. package/packages/api-gateway/src/marketplace-entries/official/agent-teams.json +1 -1
  186. package/packages/api-gateway/src/marketplace-entries/official/anchored-standard.json +1 -1
  187. package/packages/api-gateway/src/marketplace-entries/official/annotation.json +1 -1
  188. package/packages/api-gateway/src/marketplace-entries/official/archify.json +1 -1
  189. package/packages/api-gateway/src/marketplace-entries/official/at-file.json +1 -1
  190. package/packages/api-gateway/src/marketplace-entries/official/auto-mode.json +1 -1
  191. package/packages/api-gateway/src/marketplace-entries/official/better-sidebar.json +1 -1
  192. package/packages/api-gateway/src/marketplace-entries/official/browser-fetch.json +1 -1
  193. package/packages/api-gateway/src/marketplace-entries/official/browser-session.json +1 -1
  194. package/packages/api-gateway/src/marketplace-entries/official/canvas-draw.json +1 -1
  195. package/packages/api-gateway/src/marketplace-entries/official/change-verifier.json +1 -1
  196. package/packages/api-gateway/src/marketplace-entries/official/cleaner.json +1 -1
  197. package/packages/api-gateway/src/marketplace-entries/official/cli-notifier.json +1 -1
  198. package/packages/api-gateway/src/marketplace-entries/official/code2skill.json +1 -1
  199. package/packages/api-gateway/src/marketplace-entries/official/colleague-skill.json +1 -1
  200. package/packages/api-gateway/src/marketplace-entries/official/context-doctor.json +1 -1
  201. package/packages/api-gateway/src/marketplace-entries/official/context.json +1 -1
  202. package/packages/api-gateway/src/marketplace-entries/official/cost-meter.json +1 -1
  203. package/packages/api-gateway/src/marketplace-entries/official/dependency-checker.json +1 -1
  204. package/packages/api-gateway/src/marketplace-entries/official/docker-sandbox.json +1 -1
  205. package/packages/api-gateway/src/marketplace-entries/official/fail-logger.json +1 -1
  206. package/packages/api-gateway/src/marketplace-entries/official/genui.json +1 -1
  207. package/packages/api-gateway/src/marketplace-entries/official/git-time-capsule.json +1 -1
  208. package/packages/api-gateway/src/marketplace-entries/official/graph-memory.json +1 -1
  209. package/packages/api-gateway/src/marketplace-entries/official/history-compressor.json +1 -1
  210. package/packages/api-gateway/src/marketplace-entries/official/hol-guard.json +3 -3
  211. package/packages/api-gateway/src/marketplace-entries/official/i18n-pair.json +1 -1
  212. package/packages/api-gateway/src/marketplace-entries/official/image-compressor.json +1 -1
  213. package/packages/api-gateway/src/marketplace-entries/official/llm-verifier.json +1 -1
  214. package/packages/api-gateway/src/marketplace-entries/official/mcp-client.json +1 -1
  215. package/packages/api-gateway/src/marketplace-entries/official/mcp-panel.json +1 -1
  216. package/packages/api-gateway/src/marketplace-entries/official/memory.json +1 -1
  217. package/packages/api-gateway/src/marketplace-entries/official/mirage-bridge.json +1 -1
  218. package/packages/api-gateway/src/marketplace-entries/official/mock-server.json +1 -1
  219. package/packages/api-gateway/src/marketplace-entries/official/modlens.json +1 -1
  220. package/packages/api-gateway/src/marketplace-entries/official/module-search.json +1 -1
  221. package/packages/api-gateway/src/marketplace-entries/official/obsidian-sync.json +1 -1
  222. package/packages/api-gateway/src/marketplace-entries/official/openpets.json +1 -1
  223. package/packages/api-gateway/src/marketplace-entries/official/plan-execute.json +1 -1
  224. package/packages/api-gateway/src/marketplace-entries/official/plugin-check.json +1 -1
  225. package/packages/api-gateway/src/marketplace-entries/official/plugin-dev.json +1 -1
  226. package/packages/api-gateway/src/marketplace-entries/official/plugin-finder.json +1 -1
  227. package/packages/api-gateway/src/marketplace-entries/official/plugin-radar.json +1 -1
  228. package/packages/api-gateway/src/marketplace-entries/official/plugin-stars.json +1 -1
  229. package/packages/api-gateway/src/marketplace-entries/official/prompt-guard.json +1 -1
  230. package/packages/api-gateway/src/marketplace-entries/official/prompt-library.json +1 -1
  231. package/packages/api-gateway/src/marketplace-entries/official/readme-gen.json +1 -1
  232. package/packages/api-gateway/src/marketplace-entries/official/recall-unread.json +1 -1
  233. package/packages/api-gateway/src/marketplace-entries/official/reverse-skill.json +1 -1
  234. package/packages/api-gateway/src/marketplace-entries/official/reviewer-bot.json +1 -1
  235. package/packages/api-gateway/src/marketplace-entries/official/runtime-doctor.json +1 -1
  236. package/packages/api-gateway/src/marketplace-entries/official/secure-audit.json +1 -1
  237. package/packages/api-gateway/src/marketplace-entries/official/session-bookmarks.json +1 -1
  238. package/packages/api-gateway/src/marketplace-entries/official/session-bridge.json +1 -1
  239. package/packages/api-gateway/src/marketplace-entries/official/session-compare.json +1 -1
  240. package/packages/api-gateway/src/marketplace-entries/official/session-export.json +1 -1
  241. package/packages/api-gateway/src/marketplace-entries/official/session-insights.json +1 -1
  242. package/packages/api-gateway/src/marketplace-entries/official/session-search.json +1 -1
  243. package/packages/api-gateway/src/marketplace-entries/official/skill-catalog.json +1 -1
  244. package/packages/api-gateway/src/marketplace-entries/official/skill-guard.json +1 -1
  245. package/packages/api-gateway/src/marketplace-entries/official/sql-lens.json +1 -1
  246. package/packages/api-gateway/src/marketplace-entries/official/synapse.json +1 -1
  247. package/packages/api-gateway/src/marketplace-entries/official/tab-manager.json +1 -1
  248. package/packages/api-gateway/src/marketplace-entries/official/taskboard.json +1 -1
  249. package/packages/api-gateway/src/marketplace-entries/official/telemetry-blocker.json +1 -1
  250. package/packages/api-gateway/src/marketplace-entries/official/test-harness.json +1 -1
  251. package/packages/api-gateway/src/marketplace-entries/official/theme-studio.json +1 -1
  252. package/packages/api-gateway/src/marketplace-entries/official/token-guard.json +1 -1
  253. package/packages/api-gateway/src/marketplace-entries/official/turn-rewind.json +1 -1
  254. package/packages/api-gateway/src/marketplace-entries/official/undo-savepoint.json +1 -1
  255. package/packages/api-gateway/src/marketplace-entries/official/vision-toolkit.json +1 -1
  256. package/packages/api-gateway/src/marketplace-entries/official/web-research.json +1 -1
  257. package/packages/api-gateway/src/marketplace-entries/official/workspace-navigator.json +1 -1
  258. package/packages/api-gateway/src/marketplace-entries/official/workspace-search.json +1 -1
  259. package/packages/api-gateway/src/marketplace-entries/official/yaml-validator.json +1 -1
  260. package/packages/api-gateway/test/index.test.ts +363 -1
  261. package/packages/api-gateway/test/marketplace-schema.test.ts +139 -0
  262. package/packages/api-gateway/test/release-contract.test.ts +77 -0
  263. package/packages/api-gateway/test/release-package.test.ts +1 -1
  264. package/packages/api-gateway/test/release-version.test.ts +6 -4
  265. package/packages/bundle-web-app/dist/index.d.ts +3 -0
  266. package/packages/bundle-web-app/dist/index.d.ts.map +1 -1
  267. package/packages/bundle-web-app/dist/index.js +9 -5
  268. package/packages/bundle-web-app/dist/index.js.map +1 -1
  269. package/packages/bundle-web-app/package.json +1 -1
  270. package/packages/bundle-web-app/src/index.ts +12 -5
  271. package/packages/bundle-web-app/test/index.test.ts +33 -2
  272. package/packages/cli/dist/node-stdio.d.ts.map +1 -1
  273. package/packages/cli/dist/node-stdio.js +3 -1
  274. package/packages/cli/dist/node-stdio.js.map +1 -1
  275. package/packages/cli/dist/relaunch.d.ts.map +1 -1
  276. package/packages/cli/dist/relaunch.js +6 -1
  277. package/packages/cli/dist/relaunch.js.map +1 -1
  278. package/packages/cli/package.json +1 -1
  279. package/packages/cli/src/node-stdio.ts +6 -3
  280. package/packages/cli/src/relaunch.ts +5 -1
  281. package/packages/cli/test/node-stdio.test.ts +43 -0
  282. package/packages/cli/test/relaunch.test.ts +35 -0
  283. package/packages/host-webserver/dist/index.d.ts.map +1 -1
  284. package/packages/host-webserver/dist/index.js +52 -3
  285. package/packages/host-webserver/dist/index.js.map +1 -1
  286. package/packages/host-webserver/package.json +1 -1
  287. package/packages/host-webserver/src/index.ts +57 -3
  288. package/packages/host-webserver/test/index.test.ts +129 -1
  289. package/apps/web/dist/assets/index-w0KQgv8x.js +0 -22
@@ -33,15 +33,64 @@ function normalizePath(path: string): string {
33
33
  return path;
34
34
  }
35
35
 
36
+ function sendError(response: ServerResponse, status: number, message: string): void {
37
+ response.writeHead(status, { "content-type": "application/json; charset=utf-8" });
38
+ response.end(JSON.stringify({ error: message }));
39
+ }
40
+
36
41
  function notFound(response: ServerResponse): void {
37
- response.writeHead(404, { "content-type": "application/json; charset=utf-8" });
38
- response.end(JSON.stringify({ error: "Not found" }));
42
+ sendError(response, 404, "Not found");
39
43
  }
40
44
 
41
45
  function hostForUrl(host: string): string {
42
46
  return host.includes(":") && !host.startsWith("[") ? "[" + host + "]" : host;
43
47
  }
44
48
 
49
+ const LOOPBACK_HOSTNAMES = new Set(["127.0.0.1", "localhost", "[::1]"]);
50
+ const WILDCARD_HOSTS = new Set(["", "0.0.0.0", "::", "[::]"]);
51
+
52
+ interface Authority {
53
+ readonly hostname: string;
54
+ readonly port: number;
55
+ }
56
+
57
+ // Parses an http authority (Host header value, or an Origin with its "http://" prefix removed) into its lowercase hostname (IPv6 stays bracketed, as WHATWG URL reports it) and effective port. Returns undefined for anything that is not a bare authority.
58
+ function parseHttpAuthority(value: string): Authority | undefined {
59
+ let url: URL;
60
+ try {
61
+ url = new URL("http://" + value);
62
+ } catch {
63
+ return undefined;
64
+ }
65
+ if (url.username !== "" || url.password !== "" || url.pathname !== "/" || url.search !== "" || url.hash !== "" || url.hostname === "") return undefined;
66
+ if (value.endsWith("/") || value.includes("?") || value.includes("#")) return undefined;
67
+ return { hostname: url.hostname, port: url.port === "" ? 80 : Number(url.port) };
68
+ }
69
+
70
+ // Browsers send the Origin header on every cross-origin request and on all non-GET/HEAD requests, so requiring it to match the (already validated) Host header blocks cross-site requests from pages the user visits. Requests without an Origin header (same-origin navigations, EventSource, curl, Node fetch) pass. The Host check defeats DNS rebinding: a page on attacker.example that resolves to 127.0.0.1 arrives with Host: attacker.example, which is neither loopback nor the configured bind host.
71
+ function rejectForeignRequest(request: IncomingMessage, response: ServerResponse, configuredHost: string, boundPort: number): boolean {
72
+ const hostHeader = request.headers.host;
73
+ const authority = hostHeader === undefined ? undefined : parseHttpAuthority(hostHeader);
74
+ if (authority === undefined) {
75
+ sendError(response, 400, "Invalid Host header");
76
+ return true;
77
+ }
78
+ const hostnameAllowed =
79
+ WILDCARD_HOSTS.has(configuredHost) || LOOPBACK_HOSTNAMES.has(authority.hostname) || authority.hostname === hostForUrl(configuredHost).toLowerCase();
80
+ if (!hostnameAllowed || authority.port !== boundPort) {
81
+ sendError(response, 400, "Host header does not match the web server address");
82
+ return true;
83
+ }
84
+ const origin = request.headers.origin;
85
+ if (origin === undefined) return false;
86
+ const originAuthority = origin.startsWith("http://") ? parseHttpAuthority(origin.slice("http://".length)) : undefined;
87
+ if (originAuthority === undefined || originAuthority.hostname !== authority.hostname || originAuthority.port !== authority.port) {
88
+ sendError(response, 403, "Cross-origin requests are not allowed");
89
+ return true;
90
+ }
91
+ return false;
92
+ }
93
+
45
94
  export default {
46
95
  name: "pi-webserver",
47
96
  async apply(context: Context, config: WebServerConfig) {
@@ -49,14 +98,18 @@ export default {
49
98
  const port = config.port ?? DEFAULT_WEB_SERVER_PORT;
50
99
  const routes = new Map<string, WebRoute["handler"]>();
51
100
  let fallback: WebRoute["handler"] | undefined;
101
+ // Assigned once listen() completes; tests bind port 0 so the configured port is not the one clients address.
102
+ let boundPort = 0;
52
103
  const server = createServer((request, response) => {
104
+ if (rejectForeignRequest(request, response, host, boundPort)) return;
53
105
  const path = new URL(request.url ?? "/", "http://" + hostForUrl(host)).pathname;
54
106
  const handler = routes.get(path) ?? fallback;
55
107
  if (handler === undefined) {
56
108
  notFound(response);
57
109
  return;
58
110
  }
59
- void Promise.resolve(handler(request, response)).catch((error: unknown) => {
111
+ // Invoke inside an async function so a synchronous throw is routed into the same 500 path as an async rejection instead of escaping the request listener as an uncaught exception.
112
+ void (async () => handler(request, response))().catch((error: unknown) => {
60
113
  if (response.headersSent) {
61
114
  response.destroy(error instanceof Error ? error : new Error(String(error)));
62
115
  return;
@@ -74,6 +127,7 @@ export default {
74
127
  });
75
128
  const address = server.address();
76
129
  if (address === null || typeof address === "string") throw new Error("Web server did not expose a TCP address");
130
+ boundPort = address.port;
77
131
  const service: WebServer = {
78
132
  host,
79
133
  port: address.port,
@@ -1,6 +1,7 @@
1
1
  import { Context } from "@deepseek-ai/cordis";
2
+ import { request as httpRequest } from "node:http";
2
3
  import { afterEach, describe, expect, test } from "vitest";
3
- import webServerPlugin, { DEFAULT_WEB_SERVER_PORT } from "../src/index.js";
4
+ import webServerPlugin, { DEFAULT_WEB_SERVER_PORT, type WebServer } from "../src/index.js";
4
5
 
5
6
  const contexts: Context[] = [];
6
7
 
@@ -8,6 +9,42 @@ afterEach(async () => {
8
9
  await Promise.all(contexts.splice(0).map(async (context) => context.fiber.dispose()));
9
10
  });
10
11
 
12
+ async function startServer(config: { host?: string; port: number }): Promise<WebServer> {
13
+ const context = new Context();
14
+ contexts.push(context);
15
+ await context.plugin(webServerPlugin, config);
16
+ return context.webServer;
17
+ }
18
+
19
+ // Node's fetch strips a caller-supplied Host header, so raw node:http is needed to emulate a DNS-rebinding request.
20
+ function rawRequest(server: WebServer, headers: Record<string, string>, method = "GET"): Promise<{ status: number; body: string }> {
21
+ return new Promise((resolve, reject) => {
22
+ const request = httpRequest({ host: "127.0.0.1", port: server.port, path: "/health", method, headers }, (response) => {
23
+ let body = "";
24
+ response.setEncoding("utf8");
25
+ response.on("data", (chunk: string) => {
26
+ body += chunk;
27
+ });
28
+ response.on("end", () => resolve({ status: response.statusCode ?? 0, body }));
29
+ });
30
+ request.on("error", reject);
31
+ request.end();
32
+ });
33
+ }
34
+
35
+ function registerHealth(server: WebServer): { calls: number } {
36
+ const state = { calls: 0 };
37
+ server.register({
38
+ path: "/health",
39
+ handler(_request, response) {
40
+ state.calls += 1;
41
+ response.writeHead(200, { "content-type": "text/plain; charset=utf-8" });
42
+ response.end("ok");
43
+ },
44
+ });
45
+ return state;
46
+ }
47
+
11
48
  describe("web server plugin", () => {
12
49
  test("uses the memorable Pi default port", () => {
13
50
  expect(DEFAULT_WEB_SERVER_PORT).toBe(3141);
@@ -47,4 +84,95 @@ describe("web server plugin", () => {
47
84
  expect(() => context.webServer.register({ path: "health", handler() {} })).toThrow(/absolute/);
48
85
  expect(() => context.webServer.register({ path: "/health/", handler() {} })).toThrow(/trailing slash/);
49
86
  });
87
+
88
+ test("turns a synchronous handler throw into a 500 response and keeps serving", async () => {
89
+ const server = await startServer({ host: "127.0.0.1", port: 0 });
90
+ server.register({
91
+ path: "/sync-throw",
92
+ handler() {
93
+ throw new Error("boom-sync");
94
+ },
95
+ });
96
+ server.register({
97
+ path: "/async-throw",
98
+ handler() {
99
+ return Promise.reject(new Error("boom-async"));
100
+ },
101
+ });
102
+ registerHealth(server);
103
+
104
+ await expect(
105
+ fetch(server.url + "/sync-throw").then(async (response) => ({ status: response.status, body: (await response.json()) as unknown })),
106
+ ).resolves.toEqual({
107
+ status: 500,
108
+ body: { error: "boom-sync" },
109
+ });
110
+ await expect(
111
+ fetch(server.url + "/async-throw").then(async (response) => ({ status: response.status, body: (await response.json()) as unknown })),
112
+ ).resolves.toEqual({
113
+ status: 500,
114
+ body: { error: "boom-async" },
115
+ });
116
+ await expect(fetch(server.url + "/health")).resolves.toMatchObject({ status: 200 });
117
+ });
118
+
119
+ test("rejects cross-origin requests with 403 before any handler or fallback runs", async () => {
120
+ const server = await startServer({ host: "127.0.0.1", port: 0 });
121
+ const health = registerHealth(server);
122
+ let fallbackCalls = 0;
123
+ server.registerFallback((_request, response) => {
124
+ fallbackCalls += 1;
125
+ response.end("fallback");
126
+ });
127
+
128
+ const crossOrigin = await fetch(server.url + "/health", { method: "POST", headers: { origin: "https://evil.example" }, body: "{}" });
129
+ expect(crossOrigin.status).toBe(403);
130
+ await expect(crossOrigin.json()).resolves.toEqual({ error: "Cross-origin requests are not allowed" });
131
+ await expect(fetch(server.url + "/anything", { method: "POST", headers: { origin: "https://evil.example" }, body: "{}" })).resolves.toMatchObject({
132
+ status: 403,
133
+ });
134
+ await expect(fetch(server.url + "/health", { headers: { origin: "null" } })).resolves.toMatchObject({ status: 403 });
135
+ await expect(fetch(server.url + "/health", { headers: { origin: "http://127.0.0.1:" + (server.port + 1) } })).resolves.toMatchObject({ status: 403 });
136
+ await expect(fetch(server.url + "/health", { headers: { origin: "https://127.0.0.1:" + server.port } })).resolves.toMatchObject({ status: 403 });
137
+ expect(health.calls).toBe(0);
138
+ expect(fallbackCalls).toBe(0);
139
+
140
+ await expect(fetch(server.url + "/health", { method: "POST", headers: { origin: server.url }, body: "{}" })).resolves.toMatchObject({ status: 200 });
141
+ expect(health.calls).toBe(1);
142
+ });
143
+
144
+ test("rejects requests whose Host header does not name the bound server", async () => {
145
+ const server = await startServer({ host: "127.0.0.1", port: 0 });
146
+ const health = registerHealth(server);
147
+
148
+ await expect(rawRequest(server, { host: "evil.example:" + server.port })).resolves.toEqual({
149
+ status: 400,
150
+ body: JSON.stringify({ error: "Host header does not match the web server address" }),
151
+ });
152
+ await expect(rawRequest(server, { host: "127.0.0.1:" + (server.port + 1) })).resolves.toMatchObject({ status: 400 });
153
+ await expect(rawRequest(server, { host: "127.0.0.1" })).resolves.toMatchObject({ status: 400 });
154
+ await expect(rawRequest(server, { host: "user@127.0.0.1:" + server.port })).resolves.toMatchObject({ status: 400 });
155
+ expect(health.calls).toBe(0);
156
+
157
+ await expect(rawRequest(server, { host: "localhost:" + server.port, origin: "http://localhost:" + server.port }, "POST")).resolves.toMatchObject({
158
+ status: 200,
159
+ });
160
+ await expect(rawRequest(server, { host: "LOCALHOST:" + server.port })).resolves.toMatchObject({ status: 200 });
161
+ await expect(rawRequest(server, { host: "[::1]:" + server.port })).resolves.toMatchObject({ status: 200 });
162
+ await expect(rawRequest(server, { host: "localhost:" + server.port, origin: "http://127.0.0.1:" + server.port })).resolves.toMatchObject({ status: 403 });
163
+ expect(health.calls).toBe(3);
164
+ });
165
+
166
+ test("accepts the configured non-loopback host and any hostname on a wildcard bind", async () => {
167
+ const wildcard = await startServer({ host: "0.0.0.0", port: 0 });
168
+ registerHealth(wildcard);
169
+ await expect(rawRequest(wildcard, { host: "workstation.lan:" + wildcard.port })).resolves.toMatchObject({ status: 200 });
170
+ await expect(rawRequest(wildcard, { host: "workstation.lan:" + (wildcard.port + 1) })).resolves.toMatchObject({ status: 400 });
171
+
172
+ const ipv6 = await startServer({ host: "::1", port: 0 });
173
+ registerHealth(ipv6);
174
+ expect(ipv6.url).toBe("http://[::1]:" + ipv6.port);
175
+ await expect(fetch(ipv6.url + "/health")).resolves.toMatchObject({ status: 200 });
176
+ await expect(fetch(ipv6.url + "/health", { headers: { origin: ipv6.url } })).resolves.toMatchObject({ status: 200 });
177
+ });
50
178
  });