@entelligentsia/forgecli 0.7.10 → 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (385) hide show
  1. package/CHANGELOG.md +127 -0
  2. package/dist/CHANGELOG-forge-plugin.md +70 -0
  3. package/dist/CHANGELOG-pi.md +63 -0
  4. package/dist/bin/argv.d.ts +2 -2
  5. package/dist/bin/argv.js +27 -0
  6. package/dist/bin/argv.js.map +1 -1
  7. package/dist/bin/config.d.ts +69 -0
  8. package/dist/bin/config.js +315 -0
  9. package/dist/bin/config.js.map +1 -0
  10. package/dist/bin/doctor.d.ts +1 -0
  11. package/dist/bin/doctor.js +12 -0
  12. package/dist/bin/doctor.js.map +1 -1
  13. package/dist/bin/env-defaults.d.ts +1 -0
  14. package/dist/bin/env-defaults.js +13 -0
  15. package/dist/bin/env-defaults.js.map +1 -0
  16. package/dist/bin/forge.js +16 -0
  17. package/dist/bin/forge.js.map +1 -1
  18. package/dist/bin/update-cli.d.ts +9 -0
  19. package/dist/bin/update-cli.js +120 -0
  20. package/dist/bin/update-cli.js.map +1 -0
  21. package/dist/extensions/forgecli/config-command.d.ts +8 -0
  22. package/dist/extensions/forgecli/config-command.js +66 -0
  23. package/dist/extensions/forgecli/config-command.js.map +1 -0
  24. package/dist/extensions/forgecli/config-layer.d.ts +38 -0
  25. package/dist/extensions/forgecli/config-layer.js +68 -0
  26. package/dist/extensions/forgecli/config-layer.js.map +1 -0
  27. package/dist/extensions/forgecli/config-tui/component.d.ts +35 -0
  28. package/dist/extensions/forgecli/config-tui/component.js +236 -0
  29. package/dist/extensions/forgecli/config-tui/component.js.map +1 -0
  30. package/dist/extensions/forgecli/config-tui/handler.d.ts +40 -0
  31. package/dist/extensions/forgecli/config-tui/handler.js +240 -0
  32. package/dist/extensions/forgecli/config-tui/handler.js.map +1 -0
  33. package/dist/extensions/forgecli/config-tui/index.d.ts +5 -0
  34. package/dist/extensions/forgecli/config-tui/index.js +5 -0
  35. package/dist/extensions/forgecli/config-tui/index.js.map +1 -0
  36. package/dist/extensions/forgecli/config-tui/keys.d.ts +26 -0
  37. package/dist/extensions/forgecli/config-tui/keys.js +33 -0
  38. package/dist/extensions/forgecli/config-tui/keys.js.map +1 -0
  39. package/dist/extensions/forgecli/config-tui/plugin-config-reader.d.ts +23 -0
  40. package/dist/extensions/forgecli/config-tui/plugin-config-reader.js +58 -0
  41. package/dist/extensions/forgecli/config-tui/plugin-config-reader.js.map +1 -0
  42. package/dist/extensions/forgecli/config-tui/screens/advanced-menu.d.ts +7 -0
  43. package/dist/extensions/forgecli/config-tui/screens/advanced-menu.js +83 -0
  44. package/dist/extensions/forgecli/config-tui/screens/advanced-menu.js.map +1 -0
  45. package/dist/extensions/forgecli/config-tui/screens/confirm-quit.d.ts +11 -0
  46. package/dist/extensions/forgecli/config-tui/screens/confirm-quit.js +54 -0
  47. package/dist/extensions/forgecli/config-tui/screens/confirm-quit.js.map +1 -0
  48. package/dist/extensions/forgecli/config-tui/screens/override-editor.d.ts +11 -0
  49. package/dist/extensions/forgecli/config-tui/screens/override-editor.js +233 -0
  50. package/dist/extensions/forgecli/config-tui/screens/override-editor.js.map +1 -0
  51. package/dist/extensions/forgecli/config-tui/screens/overrides-list-phases.d.ts +7 -0
  52. package/dist/extensions/forgecli/config-tui/screens/overrides-list-phases.js +91 -0
  53. package/dist/extensions/forgecli/config-tui/screens/overrides-list-phases.js.map +1 -0
  54. package/dist/extensions/forgecli/config-tui/screens/overrides-list.d.ts +7 -0
  55. package/dist/extensions/forgecli/config-tui/screens/overrides-list.js +71 -0
  56. package/dist/extensions/forgecli/config-tui/screens/overrides-list.js.map +1 -0
  57. package/dist/extensions/forgecli/config-tui/screens/persona-editor.d.ts +10 -0
  58. package/dist/extensions/forgecli/config-tui/screens/persona-editor.js +182 -0
  59. package/dist/extensions/forgecli/config-tui/screens/persona-editor.js.map +1 -0
  60. package/dist/extensions/forgecli/config-tui/screens/persona-picker.d.ts +7 -0
  61. package/dist/extensions/forgecli/config-tui/screens/persona-picker.js +76 -0
  62. package/dist/extensions/forgecli/config-tui/screens/persona-picker.js.map +1 -0
  63. package/dist/extensions/forgecli/config-tui/screens/personas-list.d.ts +7 -0
  64. package/dist/extensions/forgecli/config-tui/screens/personas-list.js +98 -0
  65. package/dist/extensions/forgecli/config-tui/screens/personas-list.js.map +1 -0
  66. package/dist/extensions/forgecli/config-tui/screens/shared.d.ts +29 -0
  67. package/dist/extensions/forgecli/config-tui/screens/shared.js +100 -0
  68. package/dist/extensions/forgecli/config-tui/screens/shared.js.map +1 -0
  69. package/dist/extensions/forgecli/config-tui/screens/show-resolved.d.ts +23 -0
  70. package/dist/extensions/forgecli/config-tui/screens/show-resolved.js +128 -0
  71. package/dist/extensions/forgecli/config-tui/screens/show-resolved.js.map +1 -0
  72. package/dist/extensions/forgecli/config-tui/screens/tier-menu.d.ts +7 -0
  73. package/dist/extensions/forgecli/config-tui/screens/tier-menu.js +135 -0
  74. package/dist/extensions/forgecli/config-tui/screens/tier-menu.js.map +1 -0
  75. package/dist/extensions/forgecli/config-tui/screens/tier-picker.d.ts +9 -0
  76. package/dist/extensions/forgecli/config-tui/screens/tier-picker.js +122 -0
  77. package/dist/extensions/forgecli/config-tui/screens/tier-picker.js.map +1 -0
  78. package/dist/extensions/forgecli/config-tui/screens/types.d.ts +24 -0
  79. package/dist/extensions/forgecli/config-tui/screens/types.js +5 -0
  80. package/dist/extensions/forgecli/config-tui/screens/types.js.map +1 -0
  81. package/dist/extensions/forgecli/config-tui/screens.d.ts +24 -0
  82. package/dist/extensions/forgecli/config-tui/screens.js +78 -0
  83. package/dist/extensions/forgecli/config-tui/screens.js.map +1 -0
  84. package/dist/extensions/forgecli/config-tui/state/buffer.d.ts +11 -0
  85. package/dist/extensions/forgecli/config-tui/state/buffer.js +91 -0
  86. package/dist/extensions/forgecli/config-tui/state/buffer.js.map +1 -0
  87. package/dist/extensions/forgecli/config-tui/state/constants.d.ts +4 -0
  88. package/dist/extensions/forgecli/config-tui/state/constants.js +14 -0
  89. package/dist/extensions/forgecli/config-tui/state/constants.js.map +1 -0
  90. package/dist/extensions/forgecli/config-tui/state/index.d.ts +6 -0
  91. package/dist/extensions/forgecli/config-tui/state/index.js +9 -0
  92. package/dist/extensions/forgecli/config-tui/state/index.js.map +1 -0
  93. package/dist/extensions/forgecli/config-tui/state/init.d.ts +2 -0
  94. package/dist/extensions/forgecli/config-tui/state/init.js +30 -0
  95. package/dist/extensions/forgecli/config-tui/state/init.js.map +1 -0
  96. package/dist/extensions/forgecli/config-tui/state/model.d.ts +192 -0
  97. package/dist/extensions/forgecli/config-tui/state/model.js +4 -0
  98. package/dist/extensions/forgecli/config-tui/state/model.js.map +1 -0
  99. package/dist/extensions/forgecli/config-tui/state/reducer.d.ts +2 -0
  100. package/dist/extensions/forgecli/config-tui/state/reducer.js +212 -0
  101. package/dist/extensions/forgecli/config-tui/state/reducer.js.map +1 -0
  102. package/dist/extensions/forgecli/config-tui/state/selectors.d.ts +91 -0
  103. package/dist/extensions/forgecli/config-tui/state/selectors.js +231 -0
  104. package/dist/extensions/forgecli/config-tui/state/selectors.js.map +1 -0
  105. package/dist/extensions/forgecli/config-tui/state.d.ts +6 -0
  106. package/dist/extensions/forgecli/config-tui/state.js +11 -0
  107. package/dist/extensions/forgecli/config-tui/state.js.map +1 -0
  108. package/dist/extensions/forgecli/config-tui/theme.d.ts +37 -0
  109. package/dist/extensions/forgecli/config-tui/theme.js +88 -0
  110. package/dist/extensions/forgecli/config-tui/theme.js.map +1 -0
  111. package/dist/extensions/forgecli/config-tui/tier-meta.d.ts +28 -0
  112. package/dist/extensions/forgecli/config-tui/tier-meta.js +69 -0
  113. package/dist/extensions/forgecli/config-tui/tier-meta.js.map +1 -0
  114. package/dist/extensions/forgecli/config-writer.d.ts +16 -0
  115. package/dist/extensions/forgecli/config-writer.js +63 -0
  116. package/dist/extensions/forgecli/config-writer.js.map +1 -0
  117. package/dist/extensions/forgecli/fix-bug.js +85 -1
  118. package/dist/extensions/forgecli/fix-bug.js.map +1 -1
  119. package/dist/extensions/forgecli/forge-cli-schema.json +54 -0
  120. package/dist/extensions/forgecli/forge-commands.js +3 -8
  121. package/dist/extensions/forgecli/forge-commands.js.map +1 -1
  122. package/dist/extensions/forgecli/forge-subagent.d.ts +13 -0
  123. package/dist/extensions/forgecli/forge-subagent.js +19 -0
  124. package/dist/extensions/forgecli/forge-subagent.js.map +1 -1
  125. package/dist/extensions/forgecli/index.js +19 -3
  126. package/dist/extensions/forgecli/index.js.map +1 -1
  127. package/dist/extensions/forgecli/input-router.d.ts +33 -0
  128. package/dist/extensions/forgecli/input-router.js +133 -0
  129. package/dist/extensions/forgecli/input-router.js.map +1 -0
  130. package/dist/extensions/forgecli/model-resolver.d.ts +32 -0
  131. package/dist/extensions/forgecli/model-resolver.js +65 -0
  132. package/dist/extensions/forgecli/model-resolver.js.map +1 -0
  133. package/dist/extensions/forgecli/model-validator.d.ts +29 -0
  134. package/dist/extensions/forgecli/model-validator.js +107 -0
  135. package/dist/extensions/forgecli/model-validator.js.map +1 -0
  136. package/dist/extensions/forgecli/run-sprint.js +59 -0
  137. package/dist/extensions/forgecli/run-sprint.js.map +1 -1
  138. package/dist/extensions/forgecli/run-task.js +93 -1
  139. package/dist/extensions/forgecli/run-task.js.map +1 -1
  140. package/dist/extensions/forgecli/thread-switcher.js +5 -2
  141. package/dist/extensions/forgecli/thread-switcher.js.map +1 -1
  142. package/dist/extensions/forgecli/update-check.js +1 -1
  143. package/dist/extensions/forgecli/update-check.js.map +1 -1
  144. package/dist/extensions/forgecli/whats-new-widget.d.ts +5 -5
  145. package/dist/extensions/forgecli/whats-new-widget.js +16 -13
  146. package/dist/extensions/forgecli/whats-new-widget.js.map +1 -1
  147. package/dist/extensions/forgecli/whats-new.js +6 -5
  148. package/dist/extensions/forgecli/whats-new.js.map +1 -1
  149. package/node_modules/@earendil-works/pi-agent-core/package.json +3 -3
  150. package/node_modules/@earendil-works/pi-ai/dist/models.generated.d.ts +27 -98
  151. package/node_modules/@earendil-works/pi-ai/dist/models.generated.d.ts.map +1 -1
  152. package/node_modules/@earendil-works/pi-ai/dist/models.generated.js +62 -132
  153. package/node_modules/@earendil-works/pi-ai/dist/models.generated.js.map +1 -1
  154. package/node_modules/@earendil-works/pi-ai/dist/providers/amazon-bedrock.d.ts.map +1 -1
  155. package/node_modules/@earendil-works/pi-ai/dist/providers/amazon-bedrock.js +25 -15
  156. package/node_modules/@earendil-works/pi-ai/dist/providers/amazon-bedrock.js.map +1 -1
  157. package/node_modules/@earendil-works/pi-ai/dist/providers/anthropic.d.ts.map +1 -1
  158. package/node_modules/@earendil-works/pi-ai/dist/providers/anthropic.js +1 -0
  159. package/node_modules/@earendil-works/pi-ai/dist/providers/anthropic.js.map +1 -1
  160. package/node_modules/@earendil-works/pi-ai/dist/providers/azure-openai-responses.d.ts.map +1 -1
  161. package/node_modules/@earendil-works/pi-ai/dist/providers/azure-openai-responses.js +17 -1
  162. package/node_modules/@earendil-works/pi-ai/dist/providers/azure-openai-responses.js.map +1 -1
  163. package/node_modules/@earendil-works/pi-ai/dist/providers/openai-completions.d.ts.map +1 -1
  164. package/node_modules/@earendil-works/pi-ai/dist/providers/openai-completions.js +8 -2
  165. package/node_modules/@earendil-works/pi-ai/dist/providers/openai-completions.js.map +1 -1
  166. package/node_modules/@earendil-works/pi-ai/dist/providers/openai-responses.d.ts.map +1 -1
  167. package/node_modules/@earendil-works/pi-ai/dist/providers/openai-responses.js +17 -1
  168. package/node_modules/@earendil-works/pi-ai/dist/providers/openai-responses.js.map +1 -1
  169. package/node_modules/@earendil-works/pi-ai/dist/providers/simple-options.d.ts.map +1 -1
  170. package/node_modules/@earendil-works/pi-ai/dist/providers/simple-options.js +8 -1
  171. package/node_modules/@earendil-works/pi-ai/dist/providers/simple-options.js.map +1 -1
  172. package/node_modules/@earendil-works/pi-ai/package.json +2 -2
  173. package/node_modules/@earendil-works/pi-coding-agent/CHANGELOG.md +63 -0
  174. package/node_modules/@earendil-works/pi-coding-agent/README.md +1 -1
  175. package/node_modules/@earendil-works/pi-coding-agent/dist/cli/config-selector.d.ts.map +1 -1
  176. package/node_modules/@earendil-works/pi-coding-agent/dist/cli/config-selector.js +1 -1
  177. package/node_modules/@earendil-works/pi-coding-agent/dist/cli/config-selector.js.map +1 -1
  178. package/node_modules/@earendil-works/pi-coding-agent/dist/cli.d.ts.map +1 -1
  179. package/node_modules/@earendil-works/pi-coding-agent/dist/cli.js +6 -10
  180. package/node_modules/@earendil-works/pi-coding-agent/dist/cli.js.map +1 -1
  181. package/node_modules/@earendil-works/pi-coding-agent/dist/config.d.ts.map +1 -1
  182. package/node_modules/@earendil-works/pi-coding-agent/dist/config.js +12 -3
  183. package/node_modules/@earendil-works/pi-coding-agent/dist/config.js.map +1 -1
  184. package/node_modules/@earendil-works/pi-coding-agent/dist/core/agent-session.d.ts +1 -0
  185. package/node_modules/@earendil-works/pi-coding-agent/dist/core/agent-session.d.ts.map +1 -1
  186. package/node_modules/@earendil-works/pi-coding-agent/dist/core/agent-session.js +30 -15
  187. package/node_modules/@earendil-works/pi-coding-agent/dist/core/agent-session.js.map +1 -1
  188. package/node_modules/@earendil-works/pi-coding-agent/dist/core/compaction/compaction.d.ts +3 -3
  189. package/node_modules/@earendil-works/pi-coding-agent/dist/core/compaction/compaction.d.ts.map +1 -1
  190. package/node_modules/@earendil-works/pi-coding-agent/dist/core/compaction/compaction.js +23 -13
  191. package/node_modules/@earendil-works/pi-coding-agent/dist/core/compaction/compaction.js.map +1 -1
  192. package/node_modules/@earendil-works/pi-coding-agent/dist/core/package-manager.d.ts +4 -0
  193. package/node_modules/@earendil-works/pi-coding-agent/dist/core/package-manager.d.ts.map +1 -1
  194. package/node_modules/@earendil-works/pi-coding-agent/dist/core/package-manager.js +58 -38
  195. package/node_modules/@earendil-works/pi-coding-agent/dist/core/package-manager.js.map +1 -1
  196. package/node_modules/@earendil-works/pi-coding-agent/dist/core/slash-commands.d.ts.map +1 -1
  197. package/node_modules/@earendil-works/pi-coding-agent/dist/core/slash-commands.js +0 -1
  198. package/node_modules/@earendil-works/pi-coding-agent/dist/core/slash-commands.js.map +1 -1
  199. package/node_modules/@earendil-works/pi-coding-agent/dist/core/system-prompt.d.ts.map +1 -1
  200. package/node_modules/@earendil-works/pi-coding-agent/dist/core/system-prompt.js +3 -2
  201. package/node_modules/@earendil-works/pi-coding-agent/dist/core/system-prompt.js.map +1 -1
  202. package/node_modules/@earendil-works/pi-coding-agent/dist/modes/interactive/components/config-selector.d.ts +2 -2
  203. package/node_modules/@earendil-works/pi-coding-agent/dist/modes/interactive/components/config-selector.d.ts.map +1 -1
  204. package/node_modules/@earendil-works/pi-coding-agent/dist/modes/interactive/components/config-selector.js +7 -4
  205. package/node_modules/@earendil-works/pi-coding-agent/dist/modes/interactive/components/config-selector.js.map +1 -1
  206. package/node_modules/@earendil-works/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  207. package/node_modules/@earendil-works/pi-coding-agent/dist/modes/interactive/interactive-mode.js +6 -2
  208. package/node_modules/@earendil-works/pi-coding-agent/dist/modes/interactive/interactive-mode.js.map +1 -1
  209. package/node_modules/@earendil-works/pi-coding-agent/dist/package-manager-cli.d.ts.map +1 -1
  210. package/node_modules/@earendil-works/pi-coding-agent/dist/package-manager-cli.js +3 -4
  211. package/node_modules/@earendil-works/pi-coding-agent/dist/package-manager-cli.js.map +1 -1
  212. package/node_modules/@earendil-works/pi-coding-agent/dist/utils/changelog.d.ts.map +1 -1
  213. package/node_modules/@earendil-works/pi-coding-agent/dist/utils/changelog.js +2 -2
  214. package/node_modules/@earendil-works/pi-coding-agent/dist/utils/changelog.js.map +1 -1
  215. package/node_modules/@earendil-works/pi-coding-agent/dist/utils/child-process.d.ts +7 -1
  216. package/node_modules/@earendil-works/pi-coding-agent/dist/utils/child-process.d.ts.map +1 -1
  217. package/node_modules/@earendil-works/pi-coding-agent/dist/utils/child-process.js +60 -7
  218. package/node_modules/@earendil-works/pi-coding-agent/dist/utils/child-process.js.map +1 -1
  219. package/node_modules/@earendil-works/pi-coding-agent/docs/packages.md +2 -2
  220. package/node_modules/@earendil-works/pi-coding-agent/docs/settings.md +1 -3
  221. package/node_modules/@earendil-works/pi-coding-agent/examples/extensions/custom-provider-anthropic/package.json +1 -1
  222. package/node_modules/@earendil-works/pi-coding-agent/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
  223. package/node_modules/@earendil-works/pi-coding-agent/examples/extensions/sandbox/package.json +1 -1
  224. package/node_modules/@earendil-works/pi-coding-agent/examples/extensions/with-deps/package.json +1 -1
  225. package/node_modules/@earendil-works/pi-coding-agent/package.json +6 -6
  226. package/node_modules/@earendil-works/pi-tui/package.json +2 -2
  227. package/node_modules/@protobufjs/fetch/CHANGELOG.md +8 -0
  228. package/node_modules/@protobufjs/fetch/index.d.ts +7 -7
  229. package/node_modules/@protobufjs/fetch/index.js +4 -7
  230. package/node_modules/@protobufjs/fetch/package.json +7 -5
  231. package/node_modules/@protobufjs/fetch/tests/data/file.txt +1 -0
  232. package/node_modules/@protobufjs/fetch/tests/index.js +150 -8
  233. package/node_modules/@protobufjs/fetch/util/fs.js +11 -0
  234. package/node_modules/@protobufjs/inquire/CHANGELOG.md +8 -0
  235. package/node_modules/@protobufjs/inquire/index.d.ts +1 -0
  236. package/node_modules/@protobufjs/inquire/index.js +1 -0
  237. package/node_modules/@protobufjs/inquire/package.json +1 -1
  238. package/node_modules/protobufjs/dist/light/protobuf.js +187 -153
  239. package/node_modules/protobufjs/dist/light/protobuf.js.map +1 -1
  240. package/node_modules/protobufjs/dist/light/protobuf.min.js +3 -3
  241. package/node_modules/protobufjs/dist/light/protobuf.min.js.map +1 -1
  242. package/node_modules/protobufjs/dist/minimal/protobuf.js +14 -5
  243. package/node_modules/protobufjs/dist/minimal/protobuf.js.map +1 -1
  244. package/node_modules/protobufjs/dist/minimal/protobuf.min.js +3 -3
  245. package/node_modules/protobufjs/dist/minimal/protobuf.min.js.map +1 -1
  246. package/node_modules/protobufjs/dist/protobuf.js +207 -173
  247. package/node_modules/protobufjs/dist/protobuf.js.map +1 -1
  248. package/node_modules/protobufjs/dist/protobuf.min.js +3 -3
  249. package/node_modules/protobufjs/dist/protobuf.min.js.map +1 -1
  250. package/node_modules/protobufjs/package.json +6 -3
  251. package/node_modules/protobufjs/src/util/fs.js +11 -0
  252. package/node_modules/protobufjs/src/util/minimal.js +10 -2
  253. package/node_modules/protobufjs/src/util.js +1 -1
  254. package/node_modules/undici/README.md +14 -5
  255. package/node_modules/undici/docs/docs/api/Client.md +4 -2
  256. package/node_modules/undici/docs/docs/api/Dispatcher.md +62 -27
  257. package/node_modules/undici/docs/docs/api/GlobalInstallation.md +7 -5
  258. package/node_modules/undici/docs/docs/api/H2CClient.md +1 -1
  259. package/node_modules/undici/docs/docs/api/RedirectHandler.md +14 -9
  260. package/node_modules/undici/docs/docs/api/RetryAgent.md +0 -1
  261. package/node_modules/undici/docs/docs/api/RetryHandler.md +12 -14
  262. package/node_modules/undici/docs/docs/api/SnapshotAgent.md +23 -0
  263. package/node_modules/undici/docs/docs/best-practices/migrating-from-v7-to-v8.md +231 -0
  264. package/node_modules/undici/index.js +4 -2
  265. package/node_modules/undici/lib/api/api-connect.js +13 -11
  266. package/node_modules/undici/lib/api/api-pipeline.js +26 -13
  267. package/node_modules/undici/lib/api/api-request.js +45 -21
  268. package/node_modules/undici/lib/api/api-stream.js +81 -20
  269. package/node_modules/undici/lib/api/api-upgrade.js +21 -11
  270. package/node_modules/undici/lib/api/readable.js +3 -2
  271. package/node_modules/undici/lib/cache/memory-cache-store.js +1 -1
  272. package/node_modules/undici/lib/cache/sqlite-cache-store.js +6 -4
  273. package/node_modules/undici/lib/core/connect.js +17 -1
  274. package/node_modules/undici/lib/core/constants.js +1 -24
  275. package/node_modules/undici/lib/core/errors.js +2 -2
  276. package/node_modules/undici/lib/core/request.js +115 -18
  277. package/node_modules/undici/lib/core/socks5-client.js +24 -9
  278. package/node_modules/undici/lib/core/socks5-utils.js +32 -23
  279. package/node_modules/undici/lib/core/symbols.js +1 -0
  280. package/node_modules/undici/lib/core/util.js +70 -43
  281. package/node_modules/undici/lib/dispatcher/agent.js +47 -33
  282. package/node_modules/undici/lib/dispatcher/balanced-pool.js +21 -26
  283. package/node_modules/undici/lib/dispatcher/client-h1.js +98 -39
  284. package/node_modules/undici/lib/dispatcher/client-h2.js +603 -272
  285. package/node_modules/undici/lib/dispatcher/client.js +12 -5
  286. package/node_modules/undici/lib/dispatcher/dispatcher-base.js +24 -5
  287. package/node_modules/undici/lib/dispatcher/dispatcher.js +0 -4
  288. package/node_modules/undici/lib/dispatcher/dispatcher1-wrapper.js +107 -0
  289. package/node_modules/undici/lib/dispatcher/h2c-client.js +5 -5
  290. package/node_modules/undici/lib/dispatcher/pool-base.js +28 -10
  291. package/node_modules/undici/lib/dispatcher/pool.js +31 -6
  292. package/node_modules/undici/lib/dispatcher/proxy-agent.js +38 -13
  293. package/node_modules/undici/lib/dispatcher/round-robin-pool.js +31 -9
  294. package/node_modules/undici/lib/dispatcher/socks5-proxy-agent.js +95 -80
  295. package/node_modules/undici/lib/global.js +13 -1
  296. package/node_modules/undici/lib/handler/cache-handler.js +16 -8
  297. package/node_modules/undici/lib/handler/decorator-handler.js +1 -2
  298. package/node_modules/undici/lib/handler/redirect-handler.js +5 -51
  299. package/node_modules/undici/lib/handler/retry-handler.js +15 -2
  300. package/node_modules/undici/lib/interceptor/cache.js +30 -17
  301. package/node_modules/undici/lib/interceptor/decompress.js +28 -2
  302. package/node_modules/undici/lib/interceptor/dns.js +1 -1
  303. package/node_modules/undici/lib/interceptor/redirect.js +3 -3
  304. package/node_modules/undici/lib/llhttp/llhttp-wasm.js +1 -1
  305. package/node_modules/undici/lib/llhttp/llhttp_simd-wasm.js +1 -1
  306. package/node_modules/undici/lib/mock/mock-agent.js +8 -8
  307. package/node_modules/undici/lib/mock/mock-call-history.js +15 -15
  308. package/node_modules/undici/lib/mock/mock-utils.js +37 -22
  309. package/node_modules/undici/lib/mock/snapshot-agent.js +16 -6
  310. package/node_modules/undici/lib/mock/snapshot-recorder.js +38 -3
  311. package/node_modules/undici/lib/util/cache.js +8 -7
  312. package/node_modules/undici/lib/util/runtime-features.js +3 -34
  313. package/node_modules/undici/lib/web/cache/cache.js +6 -8
  314. package/node_modules/undici/lib/web/eventsource/eventsource-stream.js +245 -150
  315. package/node_modules/undici/lib/web/fetch/body.js +3 -9
  316. package/node_modules/undici/lib/web/fetch/formdata-parser.js +17 -6
  317. package/node_modules/undici/lib/web/fetch/formdata.js +21 -2
  318. package/node_modules/undici/lib/web/fetch/index.js +214 -221
  319. package/node_modules/undici/lib/web/webidl/index.js +7 -9
  320. package/node_modules/undici/lib/web/websocket/frame.js +1 -7
  321. package/node_modules/undici/lib/web/websocket/permessage-deflate.js +13 -31
  322. package/node_modules/undici/lib/web/websocket/receiver.js +62 -22
  323. package/node_modules/undici/lib/web/websocket/stream/websocketstream.js +11 -17
  324. package/node_modules/undici/lib/web/websocket/websocket.js +6 -1
  325. package/node_modules/undici/package.json +9 -9
  326. package/node_modules/undici/types/agent.d.ts +0 -2
  327. package/node_modules/undici/types/client.d.ts +25 -19
  328. package/node_modules/undici/types/dispatcher.d.ts +7 -27
  329. package/node_modules/undici/types/dispatcher1-wrapper.d.ts +7 -0
  330. package/node_modules/undici/types/formdata.d.ts +0 -6
  331. package/node_modules/undici/types/h2c-client.d.ts +6 -6
  332. package/node_modules/undici/types/header.d.ts +5 -0
  333. package/node_modules/undici/types/index.d.ts +3 -1
  334. package/node_modules/undici/types/interceptors.d.ts +1 -1
  335. package/node_modules/undici/types/pool.d.ts +0 -2
  336. package/node_modules/undici/types/proxy-agent.d.ts +2 -2
  337. package/node_modules/undici/types/round-robin-pool.d.ts +0 -2
  338. package/node_modules/undici/types/snapshot-agent.d.ts +4 -0
  339. package/node_modules/undici/types/socks5-proxy-agent.d.ts +2 -2
  340. package/node_modules/undici/types/webidl.d.ts +0 -1
  341. package/package.json +16 -9
  342. package/dist/extensions/forgecli/review-command.d.ts +0 -2
  343. package/dist/extensions/forgecli/review-command.js +0 -184
  344. package/dist/extensions/forgecli/review-command.js.map +0 -1
  345. package/dist/forge-payload/.tools/banners.cjs +0 -435
  346. package/dist/forge-payload/.tools/build-context-pack.cjs +0 -290
  347. package/dist/forge-payload/.tools/build-init-context.cjs +0 -322
  348. package/dist/forge-payload/.tools/build-overlay.cjs +0 -326
  349. package/dist/forge-payload/.tools/build-persona-pack.cjs +0 -226
  350. package/dist/forge-payload/.tools/collate.cjs +0 -1041
  351. package/dist/forge-payload/.tools/generation-manifest.cjs +0 -311
  352. package/dist/forge-payload/.tools/lib/forge-root.cjs +0 -59
  353. package/dist/forge-payload/.tools/lib/paths.cjs +0 -29
  354. package/dist/forge-payload/.tools/lib/pricing.cjs +0 -165
  355. package/dist/forge-payload/.tools/lib/project-root.cjs +0 -32
  356. package/dist/forge-payload/.tools/lib/result.js +0 -40
  357. package/dist/forge-payload/.tools/lib/store-facade.cjs +0 -162
  358. package/dist/forge-payload/.tools/lib/store-nlp.cjs +0 -250
  359. package/dist/forge-payload/.tools/lib/store-query-exec.cjs +0 -272
  360. package/dist/forge-payload/.tools/lib/validate.js +0 -141
  361. package/dist/forge-payload/.tools/manage-config.cjs +0 -340
  362. package/dist/forge-payload/.tools/manage-versions.cjs +0 -365
  363. package/dist/forge-payload/.tools/package.json +0 -3
  364. package/dist/forge-payload/.tools/parse-gates.cjs +0 -151
  365. package/dist/forge-payload/.tools/parse-verdict.cjs +0 -67
  366. package/dist/forge-payload/.tools/preflight-gate.cjs +0 -350
  367. package/dist/forge-payload/.tools/prompts/sprint-plan-prompt.md +0 -70
  368. package/dist/forge-payload/.tools/schemas/task-list.schema.json +0 -53
  369. package/dist/forge-payload/.tools/seed-store.cjs +0 -237
  370. package/dist/forge-payload/.tools/store-cli.cjs +0 -1226
  371. package/dist/forge-payload/.tools/store-query.cjs +0 -319
  372. package/dist/forge-payload/.tools/store.cjs +0 -315
  373. package/dist/forge-payload/.tools/substitute-placeholders.cjs +0 -625
  374. package/dist/forge-payload/.tools/validate-store.cjs +0 -593
  375. package/node_modules/@earendil-works/pi-coding-agent/examples/extensions/custom-provider-anthropic/package-lock.json +0 -24
  376. package/node_modules/@earendil-works/pi-coding-agent/examples/extensions/sandbox/package-lock.json +0 -92
  377. package/node_modules/@earendil-works/pi-coding-agent/examples/extensions/with-deps/package-lock.json +0 -31
  378. package/node_modules/undici/lib/handler/unwrap-handler.js +0 -100
  379. package/node_modules/undici/lib/handler/wrap-handler.js +0 -105
  380. package/node_modules/undici/lib/llhttp/.gitkeep +0 -0
  381. package/node_modules/undici/lib/util/promise.js +0 -28
  382. package/skills/refresh-kb-links/SKILL.md +0 -217
  383. package/skills/store-custodian/SKILL.md +0 -163
  384. package/skills/store-query-grammar/SKILL.md +0 -145
  385. package/skills/store-query-nlp/SKILL.md +0 -110
@@ -1,7 +1,6 @@
1
1
  'use strict'
2
2
 
3
3
  const assert = require('node:assert')
4
- const { finished } = require('node:stream')
5
4
  const { AsyncResource } = require('node:async_hooks')
6
5
  const { InvalidArgumentError, InvalidReturnValueError } = require('../core/errors')
7
6
  const util = require('../core/util')
@@ -9,6 +8,54 @@ const { addSignal, removeSignal } = require('./abort-signal')
9
8
 
10
9
  function noop () {}
11
10
 
11
+ function getWritableError (stream) {
12
+ return stream.errored ?? stream.writableErrored ?? stream._writableState?.errored
13
+ }
14
+
15
+ function createPrematureCloseError () {
16
+ const err = new Error('Premature close')
17
+ err.code = 'ERR_STREAM_PREMATURE_CLOSE'
18
+ return err
19
+ }
20
+
21
+ function trackWritableLifecycle (stream, callback) {
22
+ let done = false
23
+
24
+ const cleanup = () => {
25
+ stream.removeListener('close', onClose)
26
+ stream.removeListener('error', onError)
27
+ stream.removeListener('finish', onFinish)
28
+ }
29
+
30
+ const finish = (err, fromErrorEvent = false) => {
31
+ if (done) {
32
+ return
33
+ }
34
+
35
+ done = true
36
+ cleanup()
37
+ callback(err, fromErrorEvent)
38
+ }
39
+
40
+ const onClose = () => {
41
+ const err = getWritableError(stream)
42
+ finish(err ?? (!stream.writableFinished ? createPrematureCloseError() : undefined))
43
+ }
44
+
45
+ const onError = (err) => finish(err, true)
46
+ const onFinish = () => finish()
47
+
48
+ stream.on('close', onClose)
49
+ stream.on('error', onError)
50
+ stream.on('finish', onFinish)
51
+
52
+ if (stream.closed) {
53
+ process.nextTick(onClose)
54
+ } else if (stream.writableFinished) {
55
+ process.nextTick(onFinish)
56
+ }
57
+ }
58
+
12
59
  class StreamHandler extends AsyncResource {
13
60
  constructor (opts, factory, callback) {
14
61
  if (!opts || typeof opts !== 'object') {
@@ -53,39 +100,44 @@ class StreamHandler extends AsyncResource {
53
100
  this.res = null
54
101
  this.abort = null
55
102
  this.context = null
103
+ this.controller = null
56
104
  this.trailers = null
57
105
  this.body = body
58
106
  this.onInfo = onInfo || null
59
107
 
60
108
  if (util.isStream(body)) {
61
109
  body.on('error', (err) => {
62
- this.onError(err)
110
+ this.onResponseError(this.controller, err)
63
111
  })
64
112
  }
65
113
 
66
114
  addSignal(this, signal)
67
115
  }
68
116
 
69
- onConnect (abort, context) {
117
+ onRequestStart (controller, context) {
70
118
  if (this.reason) {
71
- abort(this.reason)
119
+ controller.abort(this.reason)
72
120
  return
73
121
  }
74
122
 
75
123
  assert(this.callback)
76
124
 
77
- this.abort = abort
125
+ this.controller = controller
126
+ this.abort = (reason) => controller.abort(reason)
78
127
  this.context = context
79
128
  }
80
129
 
81
- onHeaders (statusCode, rawHeaders, resume, statusMessage) {
130
+ onResponseStart (controller, statusCode, headers, _statusMessage) {
82
131
  const { factory, opaque, context, responseHeaders } = this
83
132
 
84
- const headers = responseHeaders === 'raw' ? util.parseRawHeaders(rawHeaders) : util.parseHeaders(rawHeaders)
133
+ const rawHeaders = controller?.rawHeaders
134
+ const responseHeaderData = responseHeaders === 'raw'
135
+ ? util.parseRawHeaders(rawHeaders)
136
+ : headers
85
137
 
86
138
  if (statusCode < 200) {
87
139
  if (this.onInfo) {
88
- this.onInfo({ statusCode, headers })
140
+ this.onInfo({ statusCode, headers: responseHeaderData })
89
141
  }
90
142
  return
91
143
  }
@@ -98,7 +150,7 @@ class StreamHandler extends AsyncResource {
98
150
 
99
151
  const res = this.runInAsyncScope(factory, null, {
100
152
  statusCode,
101
- headers,
153
+ headers: responseHeaderData,
102
154
  opaque,
103
155
  context
104
156
  })
@@ -112,24 +164,23 @@ class StreamHandler extends AsyncResource {
112
164
  throw new InvalidReturnValueError('expected Writable')
113
165
  }
114
166
 
115
- // TODO: Avoid finished. It registers an unnecessary amount of listeners.
116
- finished(res, { readable: false }, (err) => {
167
+ trackWritableLifecycle(res, (err, fromErrorEvent) => {
117
168
  const { callback, res, opaque, trailers, abort } = this
118
169
 
119
170
  this.res = null
120
171
  if (err || !res?.readable) {
121
- util.destroy(res, err)
172
+ util.destroy(res, fromErrorEvent ? undefined : err)
122
173
  }
123
174
 
124
175
  this.callback = null
125
176
  this.runInAsyncScope(callback, null, err || null, { opaque, trailers })
126
177
 
127
178
  if (err) {
128
- abort()
179
+ abort(err)
129
180
  }
130
181
  })
131
182
 
132
- res.on('drain', resume)
183
+ res.on('drain', () => controller.resume())
133
184
 
134
185
  this.res = res
135
186
 
@@ -137,16 +188,24 @@ class StreamHandler extends AsyncResource {
137
188
  ? res.writableNeedDrain
138
189
  : res._writableState?.needDrain
139
190
 
140
- return needDrain !== true
191
+ if (needDrain === true) {
192
+ controller.pause()
193
+ }
141
194
  }
142
195
 
143
- onData (chunk) {
196
+ onResponseData (controller, chunk) {
144
197
  const { res } = this
145
198
 
146
- return res ? res.write(chunk) : true
199
+ if (!res) {
200
+ return
201
+ }
202
+
203
+ if (res.write(chunk) === false) {
204
+ controller.pause()
205
+ }
147
206
  }
148
207
 
149
- onComplete (trailers) {
208
+ onResponseEnd (_controller, trailers) {
150
209
  const { res } = this
151
210
 
152
211
  removeSignal(this)
@@ -155,12 +214,14 @@ class StreamHandler extends AsyncResource {
155
214
  return
156
215
  }
157
216
 
158
- this.trailers = util.parseHeaders(trailers)
217
+ if (trailers && typeof trailers === 'object') {
218
+ this.trailers = trailers
219
+ }
159
220
 
160
221
  res.end()
161
222
  }
162
223
 
163
- onError (err) {
224
+ onResponseError (_controller, err) {
164
225
  const { res, callback, opaque, body } = this
165
226
 
166
227
  removeSignal(this)
@@ -34,40 +34,51 @@ class UpgradeHandler extends AsyncResource {
34
34
  addSignal(this, signal)
35
35
  }
36
36
 
37
- onConnect (abort, context) {
37
+ onRequestStart (controller, context) {
38
38
  if (this.reason) {
39
- abort(this.reason)
39
+ controller.abort(this.reason)
40
40
  return
41
41
  }
42
42
 
43
43
  assert(this.callback)
44
44
 
45
- this.abort = abort
46
- this.context = null
45
+ this.abort = (reason) => controller.abort(reason)
46
+ this.context = context
47
47
  }
48
48
 
49
- onHeaders () {
49
+ onResponseStart () {
50
50
  throw new SocketError('bad upgrade', null)
51
51
  }
52
52
 
53
- onUpgrade (statusCode, rawHeaders, socket) {
54
- assert(socket[kHTTP2Stream] === true ? statusCode === 200 : statusCode === 101)
53
+ onRequestUpgrade (controller, statusCode, headers, socket) {
54
+ const expectedStatusCode = socket[kHTTP2Stream] === true ? 200 : 101
55
+
56
+ if (statusCode !== expectedStatusCode) {
57
+ const socketInfo = socket[kHTTP2Stream] === true ? null : util.getSocketInfo(socket)
58
+ controller.abort(new SocketError('bad upgrade', socketInfo))
59
+ return
60
+ }
55
61
 
56
62
  const { callback, opaque, context } = this
57
63
 
58
64
  removeSignal(this)
59
65
 
60
66
  this.callback = null
61
- const headers = this.responseHeaders === 'raw' ? util.parseRawHeaders(rawHeaders) : util.parseHeaders(rawHeaders)
67
+
68
+ const rawHeaders = controller?.rawHeaders
69
+ const responseHeaders = this.responseHeaders === 'raw'
70
+ ? util.parseRawHeaders(rawHeaders)
71
+ : headers
72
+
62
73
  this.runInAsyncScope(callback, null, null, {
63
- headers,
74
+ headers: responseHeaders,
64
75
  socket,
65
76
  opaque,
66
77
  context
67
78
  })
68
79
  }
69
80
 
70
- onError (err) {
81
+ onResponseError (_controller, err) {
71
82
  const { callback, opaque } = this
72
83
 
73
84
  removeSignal(this)
@@ -97,7 +108,6 @@ function upgrade (opts, callback) {
97
108
  method: opts.method || 'GET',
98
109
  upgrade: opts.protocol || 'Websocket'
99
110
  }
100
-
101
111
  this.dispatch(upgradeOpts, upgradeHandler)
102
112
  } catch (err) {
103
113
  if (typeof callback !== 'function') {
@@ -1,6 +1,7 @@
1
1
  'use strict'
2
2
 
3
3
  const assert = require('node:assert')
4
+ const { addAbortListener } = require('node:events')
4
5
  const { Readable } = require('node:stream')
5
6
  const { RequestAbortedError, NotSupportedError, InvalidArgumentError, AbortError } = require('../core/errors')
6
7
  const util = require('../core/util')
@@ -293,10 +294,10 @@ class BodyReadable extends Readable {
293
294
  const onAbort = () => {
294
295
  this.destroy(signal.reason ?? new AbortError())
295
296
  }
296
- signal.addEventListener('abort', onAbort)
297
+ const abortListener = addAbortListener(signal, onAbort)
297
298
  this
298
299
  .on('close', function () {
299
- signal.removeEventListener('abort', onAbort)
300
+ abortListener[Symbol.dispose]()
300
301
  if (signal.aborted) {
301
302
  reject(signal.reason ?? new AbortError())
302
303
  } else {
@@ -138,7 +138,7 @@ class MemoryCacheStore extends EventEmitter {
138
138
 
139
139
  entry.size += chunk.byteLength
140
140
 
141
- if (entry.size >= store.#maxEntrySize) {
141
+ if (entry.size > store.#maxEntrySize) {
142
142
  this.destroy()
143
143
  } else {
144
144
  entry.body.push(chunk)
@@ -173,6 +173,7 @@ module.exports = class SqliteCacheStore {
173
173
  headers = ?,
174
174
  etag = ?,
175
175
  cacheControlDirectives = ?,
176
+ vary = ?,
176
177
  cachedAt = ?,
177
178
  staleAt = ?
178
179
  WHERE
@@ -216,7 +217,7 @@ module.exports = class SqliteCacheStore {
216
217
  SELECT
217
218
  id
218
219
  FROM cacheInterceptorV${VERSION}
219
- ORDER BY cachedAt DESC
220
+ ORDER BY cachedAt ASC
220
221
  LIMIT ?
221
222
  )
222
223
  `)
@@ -278,12 +279,12 @@ module.exports = class SqliteCacheStore {
278
279
  value.headers ? JSON.stringify(value.headers) : null,
279
280
  value.etag ? value.etag : null,
280
281
  value.cacheControlDirectives ? JSON.stringify(value.cacheControlDirectives) : null,
282
+ value.vary ? JSON.stringify(value.vary) : null,
281
283
  value.cachedAt,
282
284
  value.staleAt,
283
285
  existingValue.id
284
286
  )
285
287
  } else {
286
- this.#prune()
287
288
  // New response, let's insert it
288
289
  this.#insertValueQuery.run(
289
290
  url,
@@ -299,6 +300,7 @@ module.exports = class SqliteCacheStore {
299
300
  value.cachedAt,
300
301
  value.staleAt
301
302
  )
303
+ this.#prune()
302
304
  }
303
305
  }
304
306
 
@@ -323,7 +325,7 @@ module.exports = class SqliteCacheStore {
323
325
  write (chunk, encoding, callback) {
324
326
  size += chunk.byteLength
325
327
 
326
- if (size < store.#maxEntrySize) {
328
+ if (size <= store.#maxEntrySize) {
327
329
  body.push(chunk)
328
330
  } else {
329
331
  this.destroy()
@@ -409,7 +411,7 @@ module.exports = class SqliteCacheStore {
409
411
  const now = Date.now()
410
412
  for (const value of values) {
411
413
  if (now >= value.deleteAt && !canBeExpired) {
412
- return undefined
414
+ continue
413
415
  }
414
416
 
415
417
  let matches = true
@@ -38,6 +38,22 @@ const SessionCache = class WeakSessionCache {
38
38
  return
39
39
  }
40
40
 
41
+ if (this._sessionCache.has(sessionKey)) {
42
+ this._sessionCache.delete(sessionKey)
43
+ } else if (this._sessionCache.size >= this._maxCachedSessions) {
44
+ for (const [key, ref] of this._sessionCache) {
45
+ if (ref.deref() === undefined) {
46
+ this._sessionCache.delete(key)
47
+ return
48
+ }
49
+ }
50
+
51
+ const oldest = this._sessionCache.keys().next()
52
+ if (!oldest.done) {
53
+ this._sessionCache.delete(oldest.value)
54
+ }
55
+ }
56
+
41
57
  this._sessionCache.set(sessionKey, new WeakRef(session))
42
58
  this._sessionRegistry.register(session, sessionKey)
43
59
  }
@@ -51,7 +67,7 @@ function buildConnector ({ allowH2, useH2c, maxCachedSessions, socketPath, timeo
51
67
  const options = { path: socketPath, ...opts }
52
68
  const sessionCache = new SessionCache(maxCachedSessions == null ? 100 : maxCachedSessions)
53
69
  timeout = timeout == null ? 10e3 : timeout
54
- allowH2 = allowH2 != null ? allowH2 : false
70
+ allowH2 = allowH2 != null ? allowH2 : true
55
71
  return function connect ({ hostname, host, protocol, port, servername, localAddress, httpSocket }, callback) {
56
72
  let socket
57
73
  if (protocol === 'https:') {
@@ -107,28 +107,6 @@ const headerNameLowerCasedRecord = {}
107
107
  // Note: object prototypes should not be able to be referenced. e.g. `Object#hasOwnProperty`.
108
108
  Object.setPrototypeOf(headerNameLowerCasedRecord, null)
109
109
 
110
- /**
111
- * @type {Record<Lowercase<typeof wellknownHeaderNames[number]>, Buffer>}
112
- */
113
- const wellknownHeaderNameBuffers = {}
114
-
115
- // Note: object prototypes should not be able to be referenced. e.g. `Object#hasOwnProperty`.
116
- Object.setPrototypeOf(wellknownHeaderNameBuffers, null)
117
-
118
- /**
119
- * @param {string} header Lowercased header
120
- * @returns {Buffer}
121
- */
122
- function getHeaderNameAsBuffer (header) {
123
- let buffer = wellknownHeaderNameBuffers[header]
124
-
125
- if (buffer === undefined) {
126
- buffer = Buffer.from(header)
127
- }
128
-
129
- return buffer
130
- }
131
-
132
110
  for (let i = 0; i < wellknownHeaderNames.length; ++i) {
133
111
  const key = wellknownHeaderNames[i]
134
112
  const lowerCasedKey = key.toLowerCase()
@@ -138,6 +116,5 @@ for (let i = 0; i < wellknownHeaderNames.length; ++i) {
138
116
 
139
117
  module.exports = {
140
118
  wellknownHeaderNames,
141
- headerNameLowerCasedRecord,
142
- getHeaderNameAsBuffer
119
+ headerNameLowerCasedRecord
143
120
  }
@@ -163,8 +163,8 @@ class RequestAbortedError extends AbortError {
163
163
 
164
164
  const kInformationalError = Symbol.for('undici.error.UND_ERR_INFO')
165
165
  class InformationalError extends UndiciError {
166
- constructor (message) {
167
- super(message)
166
+ constructor (message, options) {
167
+ super(message, options)
168
168
  this.name = 'InformationalError'
169
169
  this.message = message || 'Request information'
170
170
  this.code = 'UND_ERR_INFO'
@@ -16,6 +16,7 @@ const {
16
16
  hasSafeIterator,
17
17
  isBlobLike,
18
18
  serializePathWithQuery,
19
+ parseHeaders,
19
20
  assertRequestHandler,
20
21
  getServerName,
21
22
  normalizedMethodRecords,
@@ -27,7 +28,71 @@ const { headerNameLowerCasedRecord } = require('./constants')
27
28
  // Verifies that a given path is valid does not contain control chars \x00 to \x20
28
29
  const invalidPathRegex = /[^\u0021-\u00ff]/
29
30
 
31
+ function isValidContentLengthHeaderValue (val) {
32
+ if (typeof val !== 'string' || val.length === 0) {
33
+ return false
34
+ }
35
+
36
+ for (let i = 0; i < val.length; i++) {
37
+ const charCode = val.charCodeAt(i)
38
+ if (charCode < 48 || charCode > 57) {
39
+ return false
40
+ }
41
+ }
42
+
43
+ return true
44
+ }
45
+
30
46
  const kHandler = Symbol('handler')
47
+ const kController = Symbol('controller')
48
+ const kResume = Symbol('resume')
49
+
50
+ class RequestController {
51
+ #paused = false
52
+ #reason = null
53
+ #aborted = false
54
+ #abort
55
+
56
+ [kResume] = null
57
+
58
+ rawHeaders = null
59
+ rawTrailers = null
60
+
61
+ constructor (abort) {
62
+ this.#abort = abort
63
+ }
64
+
65
+ pause () {
66
+ this.#paused = true
67
+ }
68
+
69
+ resume () {
70
+ if (this.#paused) {
71
+ this.#paused = false
72
+ this[kResume]?.()
73
+ }
74
+ }
75
+
76
+ abort (reason) {
77
+ if (!this.#aborted) {
78
+ this.#aborted = true
79
+ this.#reason = reason
80
+ this.#abort(reason)
81
+ }
82
+ }
83
+
84
+ get aborted () {
85
+ return this.#aborted
86
+ }
87
+
88
+ get reason () {
89
+ return this.#reason
90
+ }
91
+
92
+ get paused () {
93
+ return this.#paused
94
+ }
95
+ }
31
96
 
32
97
  class Request {
33
98
  constructor (origin, {
@@ -241,23 +306,26 @@ class Request {
241
306
  }
242
307
  }
243
308
 
244
- onConnect (abort) {
309
+ onRequestStart (abort, context) {
245
310
  assert(!this.aborted)
246
311
  assert(!this.completed)
247
312
 
313
+ this[kController] = new RequestController(abort)
314
+
248
315
  if (this.error) {
249
- abort(this.error)
250
- } else {
251
- this.abort = abort
252
- return this[kHandler].onConnect(abort)
316
+ this[kController].abort(this.error)
317
+ return
253
318
  }
319
+
320
+ this.abort = abort
321
+ return this[kHandler].onRequestStart(this[kController], context)
254
322
  }
255
323
 
256
324
  onResponseStarted () {
257
325
  return this[kHandler].onResponseStarted?.()
258
326
  }
259
327
 
260
- onHeaders (statusCode, headers, resume, statusText) {
328
+ onResponseStart (statusCode, headers, resume, statusText) {
261
329
  assert(!this.aborted)
262
330
  assert(!this.completed)
263
331
 
@@ -265,36 +333,56 @@ class Request {
265
333
  channels.headers.publish({ request: this, response: { statusCode, headers, statusText } })
266
334
  }
267
335
 
336
+ const controller = this[kController]
337
+ if (controller) {
338
+ controller[kResume] = resume
339
+ controller.rawHeaders = headers
340
+ }
341
+
342
+ const parsedHeaders = Array.isArray(headers) ? parseHeaders(headers) : headers
343
+
268
344
  try {
269
- return this[kHandler].onHeaders(statusCode, headers, resume, statusText)
345
+ this[kHandler].onResponseStart?.(controller, statusCode, parsedHeaders, statusText)
346
+ return !controller?.paused
270
347
  } catch (err) {
271
348
  this.abort(err)
349
+ return false
272
350
  }
273
351
  }
274
352
 
275
- onData (chunk) {
353
+ onResponseData (chunk) {
276
354
  assert(!this.aborted)
277
355
  assert(!this.completed)
278
356
 
279
357
  if (channels.bodyChunkReceived.hasSubscribers) {
280
358
  channels.bodyChunkReceived.publish({ request: this, chunk })
281
359
  }
360
+
361
+ const controller = this[kController]
282
362
  try {
283
- return this[kHandler].onData(chunk)
363
+ this[kHandler].onResponseData?.(controller, chunk)
364
+ return !controller?.paused
284
365
  } catch (err) {
285
366
  this.abort(err)
286
367
  return false
287
368
  }
288
369
  }
289
370
 
290
- onUpgrade (statusCode, headers, socket) {
371
+ onRequestUpgrade (statusCode, headers, socket) {
291
372
  assert(!this.aborted)
292
373
  assert(!this.completed)
293
374
 
294
- return this[kHandler].onUpgrade(statusCode, headers, socket)
375
+ const controller = this[kController]
376
+ if (controller) {
377
+ controller.rawHeaders = headers
378
+ }
379
+
380
+ const parsedHeaders = Array.isArray(headers) ? parseHeaders(headers) : headers
381
+
382
+ return this[kHandler].onRequestUpgrade?.(controller, statusCode, parsedHeaders, socket)
295
383
  }
296
384
 
297
- onComplete (trailers) {
385
+ onResponseEnd (trailers) {
298
386
  this.onFinally()
299
387
 
300
388
  assert(!this.aborted)
@@ -305,15 +393,22 @@ class Request {
305
393
  channels.trailers.publish({ request: this, trailers })
306
394
  }
307
395
 
396
+ const controller = this[kController]
397
+ if (controller) {
398
+ controller.rawTrailers = trailers
399
+ }
400
+
401
+ const parsedTrailers = Array.isArray(trailers) ? parseHeaders(trailers) : trailers
402
+
308
403
  try {
309
- return this[kHandler].onComplete(trailers)
404
+ return this[kHandler].onResponseEnd?.(controller, parsedTrailers)
310
405
  } catch (err) {
311
406
  // TODO (fix): This might be a bad idea?
312
- this.onError(err)
407
+ this.onResponseError(err)
313
408
  }
314
409
  }
315
410
 
316
- onError (error) {
411
+ onResponseError (error) {
317
412
  this.onFinally()
318
413
 
319
414
  if (channels.error.hasSubscribers) {
@@ -325,7 +420,9 @@ class Request {
325
420
  }
326
421
  this.aborted = true
327
422
 
328
- return this[kHandler].onError(error)
423
+ const controller = this[kController]
424
+
425
+ return this[kHandler].onResponseError?.(controller, error)
329
426
  }
330
427
 
331
428
  onFinally () {
@@ -402,10 +499,10 @@ function processHeader (request, key, val) {
402
499
  if (request.contentLength !== null) {
403
500
  throw new InvalidArgumentError('duplicate content-length header')
404
501
  }
405
- request.contentLength = parseInt(val, 10)
406
- if (!Number.isFinite(request.contentLength)) {
502
+ if (!isValidContentLengthHeaderValue(val)) {
407
503
  throw new InvalidArgumentError('invalid content-length header')
408
504
  }
505
+ request.contentLength = parseInt(val, 10)
409
506
  } else if (request.contentType === null && headerName === 'content-type') {
410
507
  request.contentType = val
411
508
  request.headers.push(key, val)