@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,12 +1,11 @@
1
1
  'use strict'
2
2
 
3
- const net = require('node:net')
4
3
  const { URL } = require('node:url')
5
4
 
6
5
  let tls // include tls conditionally since it is not always available
7
6
  const DispatcherBase = require('./dispatcher-base')
8
7
  const { InvalidArgumentError } = require('../core/errors')
9
- const { Socks5Client } = require('../core/socks5-client')
8
+ const { Socks5Client, STATES } = require('../core/socks5-client')
10
9
  const { kDispatch, kClose, kDestroy } = require('../core/symbols')
11
10
  const Pool = require('./pool')
12
11
  const buildConnector = require('../core/connect')
@@ -17,7 +16,8 @@ const debug = debuglog('undici:socks5-proxy')
17
16
  const kProxyUrl = Symbol('proxy url')
18
17
  const kProxyHeaders = Symbol('proxy headers')
19
18
  const kProxyAuth = Symbol('proxy auth')
20
- const kPool = Symbol('pool')
19
+ const kProxyProtocol = Symbol('proxy protocol')
20
+ const kPools = Symbol('pools')
21
21
  const kConnector = Symbol('connector')
22
22
 
23
23
  // Static flag to ensure warning is only emitted once per process
@@ -52,6 +52,7 @@ class Socks5ProxyAgent extends DispatcherBase {
52
52
 
53
53
  this[kProxyUrl] = url
54
54
  this[kProxyHeaders] = options.headers || {}
55
+ this[kProxyProtocol] = options.proxyTls ? 'https:' : 'http:'
55
56
 
56
57
  // Extract auth from URL or options
57
58
  this[kProxyAuth] = {
@@ -65,8 +66,8 @@ class Socks5ProxyAgent extends DispatcherBase {
65
66
  servername: options.proxyTls?.servername || url.hostname
66
67
  })
67
68
 
68
- // Pool for the actual HTTP connections (with SOCKS5 tunnel connect function)
69
- this[kPool] = null
69
+ // Pools for the actual HTTP connections (with SOCKS5 tunnel connect function), keyed by origin
70
+ this[kPools] = new Map()
70
71
  }
71
72
 
72
73
  /**
@@ -79,26 +80,23 @@ class Socks5ProxyAgent extends DispatcherBase {
79
80
  debug('creating SOCKS5 connection to', proxyHost, proxyPort)
80
81
 
81
82
  // Connect to the SOCKS5 proxy
82
- const socket = await new Promise((resolve, reject) => {
83
- const onConnect = () => {
84
- socket.removeListener('error', onError)
85
- resolve(socket)
86
- }
87
-
88
- const onError = (err) => {
89
- socket.removeListener('connect', onConnect)
90
- reject(err)
83
+ const socketReady = Promise.withResolvers()
84
+
85
+ this[kConnector]({
86
+ hostname: proxyHost,
87
+ host: proxyHost,
88
+ port: proxyPort,
89
+ protocol: this[kProxyProtocol]
90
+ }, (err, socket) => {
91
+ if (err) {
92
+ socketReady.reject(err)
93
+ } else {
94
+ socketReady.resolve(socket)
91
95
  }
92
-
93
- const socket = net.connect({
94
- host: proxyHost,
95
- port: proxyPort
96
- })
97
-
98
- socket.once('connect', onConnect)
99
- socket.once('error', onError)
100
96
  })
101
97
 
98
+ const socket = await socketReady.promise
99
+
102
100
  // Create SOCKS5 client
103
101
  const socks5Client = new Socks5Client(socket, this[kProxyAuth])
104
102
 
@@ -112,58 +110,62 @@ class Socks5ProxyAgent extends DispatcherBase {
112
110
  await socks5Client.handshake()
113
111
 
114
112
  // Wait for authentication (if required)
115
- await new Promise((resolve, reject) => {
116
- const timeout = setTimeout(() => {
117
- reject(new Error('SOCKS5 authentication timeout'))
118
- }, 5000)
119
-
120
- const onAuthenticated = () => {
121
- clearTimeout(timeout)
122
- socks5Client.removeListener('error', onError)
123
- resolve()
124
- }
113
+ const authenticationReady = Promise.withResolvers()
125
114
 
126
- const onError = (err) => {
127
- clearTimeout(timeout)
128
- socks5Client.removeListener('authenticated', onAuthenticated)
129
- reject(err)
130
- }
115
+ const authenticationTimeout = setTimeout(() => {
116
+ authenticationReady.reject(new Error('SOCKS5 authentication timeout'))
117
+ }, 5000)
131
118
 
132
- // Check if already authenticated (for NO_AUTH method)
133
- if (socks5Client.state === 'authenticated') {
134
- clearTimeout(timeout)
135
- resolve()
136
- } else {
137
- socks5Client.once('authenticated', onAuthenticated)
138
- socks5Client.once('error', onError)
139
- }
140
- })
119
+ const onAuthenticated = () => {
120
+ clearTimeout(authenticationTimeout)
121
+ socks5Client.removeListener('error', onAuthenticationError)
122
+ authenticationReady.resolve()
123
+ }
124
+
125
+ const onAuthenticationError = (err) => {
126
+ clearTimeout(authenticationTimeout)
127
+ socks5Client.removeListener('authenticated', onAuthenticated)
128
+ authenticationReady.reject(err)
129
+ }
130
+
131
+ // Check if already authenticated (for NO_AUTH method)
132
+ if (socks5Client.state === STATES.AUTHENTICATED) {
133
+ clearTimeout(authenticationTimeout)
134
+ authenticationReady.resolve()
135
+ } else {
136
+ socks5Client.once('authenticated', onAuthenticated)
137
+ socks5Client.once('error', onAuthenticationError)
138
+ }
139
+
140
+ await authenticationReady.promise
141
141
 
142
142
  // Send CONNECT command
143
143
  await socks5Client.connect(targetHost, targetPort)
144
144
 
145
145
  // Wait for connection
146
- await new Promise((resolve, reject) => {
147
- const timeout = setTimeout(() => {
148
- reject(new Error('SOCKS5 connection timeout'))
149
- }, 5000)
150
-
151
- const onConnected = (info) => {
152
- debug('SOCKS5 tunnel established to', targetHost, targetPort, 'via', info)
153
- clearTimeout(timeout)
154
- socks5Client.removeListener('error', onError)
155
- resolve()
156
- }
146
+ const connectionReady = Promise.withResolvers()
157
147
 
158
- const onError = (err) => {
159
- clearTimeout(timeout)
160
- socks5Client.removeListener('connected', onConnected)
161
- reject(err)
162
- }
148
+ const connectionTimeout = setTimeout(() => {
149
+ connectionReady.reject(new Error('SOCKS5 connection timeout'))
150
+ }, 5000)
163
151
 
164
- socks5Client.once('connected', onConnected)
165
- socks5Client.once('error', onError)
166
- })
152
+ const onConnected = (info) => {
153
+ debug('SOCKS5 tunnel established to', targetHost, targetPort, 'via', info)
154
+ clearTimeout(connectionTimeout)
155
+ socks5Client.removeListener('error', onConnectionError)
156
+ connectionReady.resolve()
157
+ }
158
+
159
+ const onConnectionError = (err) => {
160
+ clearTimeout(connectionTimeout)
161
+ socks5Client.removeListener('connected', onConnected)
162
+ connectionReady.reject(err)
163
+ }
164
+
165
+ socks5Client.once('connected', onConnected)
166
+ socks5Client.once('error', onConnectionError)
167
+
168
+ await connectionReady.promise
167
169
 
168
170
  return socket
169
171
  }
@@ -171,15 +173,17 @@ class Socks5ProxyAgent extends DispatcherBase {
171
173
  /**
172
174
  * Dispatch a request through the SOCKS5 proxy
173
175
  */
174
- async [kDispatch] (opts, handler) {
176
+ [kDispatch] (opts, handler) {
175
177
  const { origin } = opts
176
178
 
177
179
  debug('dispatching request to', origin, 'via SOCKS5')
178
180
 
179
181
  try {
180
- // Create Pool with custom connect function if we don't have one yet
181
- if (!this[kPool] || this[kPool].destroyed || this[kPool].closed) {
182
- this[kPool] = new Pool(origin, {
182
+ const originKey = String(origin)
183
+ let pool = this[kPools].get(originKey)
184
+ // Create a Pool per origin so requests are not routed to the wrong host
185
+ if (!pool || pool.destroyed || pool.closed) {
186
+ pool = new Pool(origin, {
183
187
  pipelining: opts.pipelining,
184
188
  connections: opts.connections,
185
189
  connect: async (connectOpts, callback) => {
@@ -206,10 +210,10 @@ class Socks5ProxyAgent extends DispatcherBase {
206
210
  ...connectOpts.tls || {}
207
211
  })
208
212
 
209
- await new Promise((resolve, reject) => {
210
- finalSocket.once('secureConnect', resolve)
211
- finalSocket.once('error', reject)
212
- })
213
+ const tlsReady = Promise.withResolvers()
214
+ finalSocket.once('secureConnect', tlsReady.resolve)
215
+ finalSocket.once('error', tlsReady.reject)
216
+ await tlsReady.promise
213
217
  }
214
218
 
215
219
  callback(null, finalSocket)
@@ -219,14 +223,19 @@ class Socks5ProxyAgent extends DispatcherBase {
219
223
  }
220
224
  }
221
225
  })
226
+ this[kPools].set(originKey, pool)
222
227
  }
223
228
 
224
- // Dispatch the request through the pool
225
- return this[kPool][kDispatch](opts, handler)
229
+ // Dispatch the request through the per-origin pool
230
+ return pool[kDispatch](opts, handler)
226
231
  } catch (err) {
227
232
  debug('dispatch error:', err)
228
- if (typeof handler.onError === 'function') {
233
+ if (typeof handler.onResponseError === 'function') {
234
+ handler.onResponseError(null, err)
235
+ return false
236
+ } else if (typeof handler.onError === 'function') {
229
237
  handler.onError(err)
238
+ return false
230
239
  } else {
231
240
  throw err
232
241
  }
@@ -234,15 +243,21 @@ class Socks5ProxyAgent extends DispatcherBase {
234
243
  }
235
244
 
236
245
  async [kClose] () {
237
- if (this[kPool]) {
238
- await this[kPool].close()
246
+ const closePromises = []
247
+ for (const pool of this[kPools].values()) {
248
+ closePromises.push(pool.close())
239
249
  }
250
+ this[kPools].clear()
251
+ await Promise.all(closePromises)
240
252
  }
241
253
 
242
254
  async [kDestroy] (err) {
243
- if (this[kPool]) {
244
- await this[kPool].destroy(err)
255
+ const destroyPromises = []
256
+ for (const pool of this[kPools].values()) {
257
+ destroyPromises.push(pool.destroy(err))
245
258
  }
259
+ this[kPools].clear()
260
+ await Promise.all(destroyPromises)
246
261
  }
247
262
  }
248
263
 
@@ -2,9 +2,11 @@
2
2
 
3
3
  // We include a version number for the Dispatcher API. In case of breaking changes,
4
4
  // this version number must be increased to avoid conflicts.
5
- const globalDispatcher = Symbol.for('undici.globalDispatcher.1')
5
+ const globalDispatcher = Symbol.for('undici.globalDispatcher.2')
6
+ const legacyGlobalDispatcher = Symbol.for('undici.globalDispatcher.1')
6
7
  const { InvalidArgumentError } = require('./core/errors')
7
8
  const Agent = require('./dispatcher/agent')
9
+ const Dispatcher1Wrapper = require('./dispatcher/dispatcher1-wrapper')
8
10
 
9
11
  if (getGlobalDispatcher() === undefined) {
10
12
  setGlobalDispatcher(new Agent())
@@ -14,12 +16,22 @@ function setGlobalDispatcher (agent) {
14
16
  if (!agent || typeof agent.dispatch !== 'function') {
15
17
  throw new InvalidArgumentError('Argument agent must implement Agent')
16
18
  }
19
+
17
20
  Object.defineProperty(globalThis, globalDispatcher, {
18
21
  value: agent,
19
22
  writable: true,
20
23
  enumerable: false,
21
24
  configurable: false
22
25
  })
26
+
27
+ const legacyAgent = agent instanceof Dispatcher1Wrapper ? agent : new Dispatcher1Wrapper(agent)
28
+
29
+ Object.defineProperty(globalThis, legacyGlobalDispatcher, {
30
+ value: legacyAgent,
31
+ writable: true,
32
+ enumerable: false,
33
+ configurable: false
34
+ })
23
35
  }
24
36
 
25
37
  function getGlobalDispatcher () {
@@ -173,7 +173,8 @@ class CacheHandler {
173
173
  }
174
174
  }
175
175
 
176
- const deleteAt = determineDeleteAt(baseTime, cacheControlDirectives, absoluteStaleAt)
176
+ const cachedAt = resAge ? now - resAge : now
177
+ const deleteAt = determineDeleteAt(baseTime, cachedAt, cacheControlDirectives, absoluteStaleAt)
177
178
  const strippedHeaders = stripNecessaryHeaders(resHeaders, cacheControlDirectives)
178
179
 
179
180
  /**
@@ -185,7 +186,7 @@ class CacheHandler {
185
186
  headers: strippedHeaders,
186
187
  vary: varyDirectives,
187
188
  cacheControlDirectives,
188
- cachedAt: resAge ? now - resAge : now,
189
+ cachedAt,
189
190
  staleAt: absoluteStaleAt,
190
191
  deleteAt
191
192
  }
@@ -478,18 +479,19 @@ function determineStaleAt (cacheType, now, age, resHeaders, responseDate, cacheC
478
479
 
479
480
  if (cacheControlDirectives.immutable) {
480
481
  // https://www.rfc-editor.org/rfc/rfc8246.html#section-2.2
481
- return 31536000
482
+ return 31536000000
482
483
  }
483
484
 
484
485
  return undefined
485
486
  }
486
487
 
487
488
  /**
488
- * @param {number} now
489
+ * @param {number} baseTime
490
+ * @param {number} cachedAt
489
491
  * @param {import('../../types/cache-interceptor.d.ts').default.CacheControlDirectives} cacheControlDirectives
490
492
  * @param {number} staleAt
491
493
  */
492
- function determineDeleteAt (now, cacheControlDirectives, staleAt) {
494
+ function determineDeleteAt (baseTime, cachedAt, cacheControlDirectives, staleAt) {
493
495
  let staleWhileRevalidate = -Infinity
494
496
  let staleIfError = -Infinity
495
497
  let immutable = -Infinity
@@ -503,15 +505,21 @@ function determineDeleteAt (now, cacheControlDirectives, staleAt) {
503
505
  }
504
506
 
505
507
  if (cacheControlDirectives.immutable && staleWhileRevalidate === -Infinity && staleIfError === -Infinity) {
506
- immutable = now + 31536000000
508
+ immutable = cachedAt + 31536000000
507
509
  }
508
510
 
509
511
  // When no stale directives or immutable flag, add a revalidation buffer
510
512
  // equal to the freshness lifetime so the entry survives past staleAt long
511
513
  // enough to be revalidated instead of silently disappearing.
514
+ //
515
+ // Response Date headers only have second precision, so baseTime can trail the
516
+ // actual cache insertion time by up to ~1s. Pad the buffer by that bounded
517
+ // skew so short-lived entries do not disappear exactly when they should be
518
+ // revalidated.
512
519
  if (staleWhileRevalidate === -Infinity && staleIfError === -Infinity && immutable === -Infinity) {
513
- const freshnessLifetime = staleAt - now
514
- return staleAt + freshnessLifetime
520
+ const freshnessLifetime = staleAt - baseTime
521
+ const datePrecisionPadding = Math.min(Math.max(cachedAt - baseTime, 0), 1000)
522
+ return staleAt + freshnessLifetime + datePrecisionPadding
515
523
  }
516
524
 
517
525
  return Math.max(staleAt, staleWhileRevalidate, staleIfError, immutable)
@@ -1,7 +1,6 @@
1
1
  'use strict'
2
2
 
3
3
  const assert = require('node:assert')
4
- const WrapHandler = require('./wrap-handler')
5
4
 
6
5
  /**
7
6
  * @deprecated
@@ -16,7 +15,7 @@ module.exports = class DecoratorHandler {
16
15
  if (typeof handler !== 'object' || handler === null) {
17
16
  throw new TypeError('handler must be an object')
18
17
  }
19
- this.#handler = WrapHandler.wrap(handler)
18
+ this.#handler = handler
20
19
  }
21
20
 
22
21
  onRequestStart (...args) {
@@ -1,30 +1,13 @@
1
1
  'use strict'
2
2
 
3
3
  const util = require('../core/util')
4
- const { kBodyUsed } = require('../core/symbols')
5
4
  const assert = require('node:assert')
6
5
  const { InvalidArgumentError } = require('../core/errors')
7
- const EE = require('node:events')
8
6
 
9
7
  const redirectableStatusCodes = [300, 301, 302, 303, 307, 308]
10
8
 
11
- const kBody = Symbol('body')
12
-
13
9
  const noop = () => {}
14
10
 
15
- class BodyAsyncIterable {
16
- constructor (body) {
17
- this[kBody] = body
18
- this[kBodyUsed] = false
19
- }
20
-
21
- async * [Symbol.asyncIterator] () {
22
- assert(!this[kBodyUsed], 'disturbed')
23
- this[kBodyUsed] = true
24
- yield * this[kBody]
25
- }
26
- }
27
-
28
11
  class RedirectHandler {
29
12
  static buildDispatch (dispatcher, maxRedirections) {
30
13
  if (maxRedirections != null && (!Number.isInteger(maxRedirections) || maxRedirections < 0)) {
@@ -40,47 +23,18 @@ class RedirectHandler {
40
23
  throw new InvalidArgumentError('maxRedirections must be a positive number')
41
24
  }
42
25
 
26
+ if (opts.throwOnMaxRedirect != null && typeof opts.throwOnMaxRedirect !== 'boolean') {
27
+ throw new InvalidArgumentError('throwOnMaxRedirect must be a boolean')
28
+ }
29
+
43
30
  this.dispatch = dispatch
44
31
  this.location = null
45
32
  const { maxRedirections: _, ...cleanOpts } = opts
46
33
  this.opts = cleanOpts // opts must be a copy, exclude maxRedirections
34
+ this.opts.body = util.wrapRequestBody(this.opts.body)
47
35
  this.maxRedirections = maxRedirections
48
36
  this.handler = handler
49
37
  this.history = []
50
-
51
- if (util.isStream(this.opts.body)) {
52
- // TODO (fix): Provide some way for the user to cache the file to e.g. /tmp
53
- // so that it can be dispatched again?
54
- // TODO (fix): Do we need 100-expect support to provide a way to do this properly?
55
- if (util.bodyLength(this.opts.body) === 0) {
56
- this.opts.body
57
- .on('data', function () {
58
- assert(false)
59
- })
60
- }
61
-
62
- if (typeof this.opts.body.readableDidRead !== 'boolean') {
63
- this.opts.body[kBodyUsed] = false
64
- EE.prototype.on.call(this.opts.body, 'data', function () {
65
- this[kBodyUsed] = true
66
- })
67
- }
68
- } else if (this.opts.body && typeof this.opts.body.pipeTo === 'function') {
69
- // TODO (fix): We can't access ReadableStream internal state
70
- // to determine whether or not it has been disturbed. This is just
71
- // a workaround.
72
- this.opts.body = new BodyAsyncIterable(this.opts.body)
73
- } else if (
74
- this.opts.body &&
75
- typeof this.opts.body !== 'string' &&
76
- !ArrayBuffer.isView(this.opts.body) &&
77
- util.isIterable(this.opts.body) &&
78
- !util.isFormDataLike(this.opts.body)
79
- ) {
80
- // TODO: Should we allow re-using iterable if !this.opts.idempotent
81
- // or through some other flag?
82
- this.opts.body = new BodyAsyncIterable(this.opts.body)
83
- }
84
38
  }
85
39
 
86
40
  onRequestStart (controller, context) {
@@ -3,7 +3,6 @@ const assert = require('node:assert')
3
3
 
4
4
  const { kRetryHandlerDefaultRetry } = require('../core/symbols')
5
5
  const { RequestRetryError } = require('../core/errors')
6
- const WrapHandler = require('./wrap-handler')
7
6
  const {
8
7
  isDisturbed,
9
8
  parseRangeHeader,
@@ -35,7 +34,7 @@ class RetryHandler {
35
34
 
36
35
  this.error = null
37
36
  this.dispatch = dispatch
38
- this.handler = WrapHandler.wrap(handler)
37
+ this.handler = handler
39
38
  this.opts = { ...dispatchOpts, body: wrapRequestBody(opts.body) }
40
39
  this.retryOpts = {
41
40
  throwOnError: throwOnError ?? true,
@@ -69,6 +68,8 @@ class RetryHandler {
69
68
  this.start = 0
70
69
  this.end = null
71
70
  this.etag = null
71
+ this.statusCode = null
72
+ this.headers = null
72
73
  }
73
74
 
74
75
  onResponseStartWithRetry (controller, statusCode, headers, statusMessage, err) {
@@ -184,6 +185,8 @@ class RetryHandler {
184
185
  onResponseStart (controller, statusCode, headers, statusMessage) {
185
186
  this.error = null
186
187
  this.retryCount += 1
188
+ this.statusCode = statusCode
189
+ this.headers = headers
187
190
 
188
191
  if (statusCode >= 300) {
189
192
  const err = new RequestRetryError('Request failed', statusCode, {
@@ -321,6 +324,16 @@ class RetryHandler {
321
324
  }
322
325
 
323
326
  if (!this.error) {
327
+ // Verify that the received body length matches the expected range
328
+ // when we have a finite end position (from Content-Length or Content-Range)
329
+ if (this.end != null && Number.isFinite(this.end)) {
330
+ if (this.start !== this.end + 1) {
331
+ throw new RequestRetryError('Content-Range mismatch', this.statusCode, {
332
+ headers: this.headers,
333
+ data: { count: this.retryCount }
334
+ })
335
+ }
336
+ }
324
337
  this.retryCount = 0
325
338
  return this.handler.onResponseEnd?.(controller, trailers)
326
339
  }
@@ -124,30 +124,39 @@ function handleUncachedResponse (
124
124
  ) {
125
125
  if (reqCacheControl?.['only-if-cached']) {
126
126
  let aborted = false
127
- try {
128
- if (typeof handler.onConnect === 'function') {
129
- handler.onConnect(() => {
130
- aborted = true
131
- })
132
127
 
133
- if (aborted) {
134
- return
135
- }
128
+ const controller = {
129
+ paused: false,
130
+ rawHeaders: [],
131
+ rawTrailers: [],
132
+ pause () {
133
+ this.paused = true
134
+ },
135
+ resume () {
136
+ this.paused = false
137
+ },
138
+ abort: (reason) => {
139
+ aborted = true
140
+ handler.onResponseError?.(controller, reason ?? new AbortError())
136
141
  }
142
+ }
137
143
 
138
- if (typeof handler.onHeaders === 'function') {
139
- handler.onHeaders(504, [], nop, 'Gateway Timeout')
140
- if (aborted) {
141
- return
142
- }
144
+ try {
145
+ handler.onRequestStart?.(controller, null)
146
+
147
+ if (aborted) {
148
+ return
143
149
  }
144
150
 
145
- if (typeof handler.onComplete === 'function') {
146
- handler.onComplete([])
151
+ handler.onResponseStart?.(controller, 504, {}, 'Gateway Timeout')
152
+ if (aborted) {
153
+ return
147
154
  }
155
+
156
+ handler.onResponseEnd?.(controller, {})
148
157
  } catch (err) {
149
- if (typeof handler.onError === 'function') {
150
- handler.onError(err)
158
+ if (typeof handler.onResponseError === 'function') {
159
+ handler.onResponseError(controller, err)
151
160
  }
152
161
  }
153
162
 
@@ -175,6 +184,8 @@ function sendCachedValue (handler, opts, result, age, context, isStale) {
175
184
  assert(!stream.readableDidRead, 'stream should not be readableDidRead')
176
185
 
177
186
  const controller = {
187
+ rawHeaders: [],
188
+ rawTrailers: [],
178
189
  resume () {
179
190
  stream.resume()
180
191
  },
@@ -227,6 +238,8 @@ function sendCachedValue (handler, opts, result, age, context, isStale) {
227
238
  headers.warning = '110 - "response is stale"'
228
239
  }
229
240
 
241
+ controller.rawHeaders = util.toRawHeaders(headers)
242
+
230
243
  handler.onResponseStart?.(controller, result.statusCode, headers, result.statusMessage)
231
244
 
232
245
  if (opts.method === 'HEAD') {
@@ -3,7 +3,6 @@
3
3
  const { createInflate, createGunzip, createBrotliDecompress, createZstdDecompress } = require('node:zlib')
4
4
  const { pipeline } = require('node:stream')
5
5
  const DecoratorHandler = require('../handler/decorator-handler')
6
- const { runtimeFeatures } = require('../util/runtime-features')
7
6
 
8
7
  /** @typedef {import('node:stream').Transform} Transform */
9
8
  /** @typedef {import('node:stream').Transform} Controller */
@@ -17,7 +16,7 @@ const supportedEncodings = {
17
16
  deflate: createInflate,
18
17
  compress: createInflate,
19
18
  'x-compress': createInflate,
20
- ...(runtimeFeatures.has('zstd') ? { zstd: createZstdDecompress } : {})
19
+ zstd: createZstdDecompress
21
20
  }
22
21
 
23
22
  const defaultSkipStatusCodes = /** @type {const} */ ([204, 304])
@@ -181,6 +180,33 @@ class DecompressHandler extends DecoratorHandler {
181
180
  // Remove compression headers since we're decompressing
182
181
  const { 'content-encoding': _, 'content-length': __, ...newHeaders } = headers
183
182
 
183
+ if (controller?.rawHeaders) {
184
+ const rawHeaders = controller.rawHeaders
185
+
186
+ if (Array.isArray(rawHeaders)) {
187
+ const filteredHeaders = []
188
+ for (let i = 0; i < rawHeaders.length; i += 2) {
189
+ const headerName = rawHeaders[i]
190
+ const name = Buffer.isBuffer(headerName) ? headerName.toString('latin1') : `${headerName}`
191
+ const lowerName = name.toLowerCase()
192
+
193
+ if (lowerName === 'content-encoding' || lowerName === 'content-length') {
194
+ continue
195
+ }
196
+
197
+ filteredHeaders.push(rawHeaders[i], rawHeaders[i + 1])
198
+ }
199
+ controller.rawHeaders = filteredHeaders
200
+ } else if (typeof rawHeaders === 'object') {
201
+ for (const name of Object.keys(rawHeaders)) {
202
+ const lowerName = name.toLowerCase()
203
+ if (lowerName === 'content-encoding' || lowerName === 'content-length') {
204
+ delete rawHeaders[name]
205
+ }
206
+ }
207
+ }
208
+ }
209
+
184
210
  if (this.#decompressors.length === 1) {
185
211
  this.#setupSingleDecompressor(controller)
186
212
  } else {
@@ -7,7 +7,7 @@ const maxInt = Math.pow(2, 31) - 1
7
7
 
8
8
  function hasSafeIterator (headers) {
9
9
  const prototype = Object.getPrototypeOf(headers)
10
- const ownIterator = Object.prototype.hasOwnProperty.call(headers, Symbol.iterator)
10
+ const ownIterator = Object.hasOwn(headers, Symbol.iterator)
11
11
  return ownIterator || (prototype != null && prototype !== Object.prototype && typeof headers[Symbol.iterator] === 'function')
12
12
  }
13
13