@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
@@ -0,0 +1,231 @@
1
+ // Config TUI selectors — read-only derived data from state.
2
+ // Split from state.ts (Phase 1).
3
+ import { TIERS, TIER_PERSONAS, PERSONA_META } from "../tier-meta.js";
4
+ export function getActiveView(state) {
5
+ return state.view[state.view.length - 1];
6
+ }
7
+ export function listResolvedPersonas(state) {
8
+ const out = new Map();
9
+ const projectMap = state.buffer.project["persona-models"] ?? {};
10
+ const globalMap = state.buffer.global["persona-models"] ?? {};
11
+ for (const [persona, entry] of Object.entries(globalMap)) {
12
+ out.set(persona, { persona, provider: entry.provider, model: entry.model, source: "L1" });
13
+ }
14
+ // Project layer wins per-key
15
+ for (const [persona, entry] of Object.entries(projectMap)) {
16
+ out.set(persona, { persona, provider: entry.provider, model: entry.model, source: "L2" });
17
+ }
18
+ return [...out.values()].sort((a, b) => a.persona.localeCompare(b.persona));
19
+ }
20
+ export function listPersonaPickerEntries(state) {
21
+ const assignmentsByName = new Map(listResolvedPersonas(state).map((p) => [p.persona, p]));
22
+ const catalogue = state.personaCatalogue.filter((p) => p !== "default").sort();
23
+ const order = ["default", ...catalogue];
24
+ const seen = new Set(order);
25
+ for (const name of assignmentsByName.keys()) {
26
+ if (!seen.has(name)) {
27
+ order.push(name);
28
+ seen.add(name);
29
+ }
30
+ }
31
+ return order.map((persona) => ({
32
+ persona,
33
+ assignment: assignmentsByName.get(persona),
34
+ inCatalogue: persona === "default" || state.personaCatalogue.includes(persona),
35
+ }));
36
+ }
37
+ export function uniqueProviders(state) {
38
+ const providers = new Set();
39
+ for (const m of state.availableModels)
40
+ providers.add(m.provider);
41
+ for (const p of state.authenticatedProviders)
42
+ providers.add(p);
43
+ return [...providers].sort();
44
+ }
45
+ export function listPipelineOverrideSummaries(state) {
46
+ const names = state.pipelineCatalogue ?? ["default"];
47
+ return names.map((pipeline) => {
48
+ const phases = state.buffer.project.pipelines?.[pipeline]?.phases ?? {};
49
+ const overrideCount = Object.values(phases).filter((p) => p["model-override"] !== undefined).length;
50
+ return { pipeline, overrideCount };
51
+ });
52
+ }
53
+ export function getPhaseOverride(state, pipeline, phaseRole) {
54
+ return state.buffer.project.pipelines?.[pipeline]?.phases?.[phaseRole]?.["model-override"];
55
+ }
56
+ // ── Phase table selector ────────────────────────────────────────────────────
57
+ import { PHASE_PERSONA_TABLE, TIER_LABELS } from "../tier-meta.js";
58
+ import { resolveModelForPhase } from "../../model-resolver.js";
59
+ /** Map a model-resolver source + persona tier + resolved-layer to a
60
+ * human-readable source label per the plan's cascade vocabulary.
61
+ *
62
+ * | Internal | Plain English |
63
+ * |-----------|---------------|
64
+ * | L4-inline / L4-name | "Step override" |
65
+ * | L3 | "Per-persona override (pipeline)" |
66
+ * | L2 | "{Tier} tier (project)" |
67
+ * | L1 | "{Tier} tier (global)" |
68
+ * | default | "Default fallback" |
69
+ * | inherit | "Falls back to pi current" |
70
+ */
71
+ export function sourceToLabel(rawSource, tier, isProject) {
72
+ switch (rawSource) {
73
+ case "L4-inline":
74
+ case "L4-name":
75
+ return "Step override";
76
+ case "L3":
77
+ return "Per-persona override";
78
+ case "L2":
79
+ if (tier)
80
+ return `${TIER_LABELS[tier]} tier (project)`;
81
+ return "Per-persona (project)";
82
+ case "L1":
83
+ if (tier)
84
+ return `${TIER_LABELS[tier]} tier (global)`;
85
+ return "Per-persona (global)";
86
+ case "default":
87
+ return "Default fallback";
88
+ case "inherit":
89
+ return "Falls back to pi current";
90
+ }
91
+ }
92
+ /** Build the phase table for Screen 3.
93
+ * Joins PHASE_PERSONA_TABLE with model resolution results. */
94
+ export function getPhaseTable(state) {
95
+ const pipelineNames = state.pipelineCatalogue ?? ["default"];
96
+ const pipeline = pipelineNames[0] ?? "default";
97
+ return PHASE_PERSONA_TABLE.map((phase) => {
98
+ const result = resolveModelForPhase(pipeline, phase.role, phase.personaNoun, {
99
+ ...state.buffer.global,
100
+ ...state.buffer.project,
101
+ _global: state.buffer.global,
102
+ _project: state.buffer.project,
103
+ });
104
+ const resolved = result.model
105
+ ? `${result.model.provider}:${result.model.model}`
106
+ : "(inherit pi current)";
107
+ const meta = PERSONA_META[phase.personaNoun];
108
+ const isProject = result.source === "L2" || result.source === "L4-inline" || result.source === "L4-name" || result.source === "L3";
109
+ return {
110
+ role: phase.role,
111
+ persona: phase.personaNoun,
112
+ personaEmoji: meta?.emoji ?? "",
113
+ tier: phase.tier,
114
+ resolved,
115
+ rawSource: result.source,
116
+ sourceLabel: sourceToLabel(result.source, phase.tier, isProject),
117
+ };
118
+ });
119
+ }
120
+ // ── Tier selectors ───────────────────────────────────────────────────────────
121
+ /** Determine the effective model for an entire tier.
122
+ * Returns "set" when all personas in the tier resolve to the same model,
123
+ * "mixed" when some are missing or they diverge, "unset" when none are resolved. */
124
+ export function getTierAssignment(state, tier) {
125
+ const personas = TIER_PERSONAS[tier];
126
+ const resolved = listResolvedPersonas(state);
127
+ const resolvedMap = new Map(resolved.map((p) => [p.persona, p]));
128
+ const entries = personas.map((p) => resolvedMap.get(p));
129
+ // All tier personas must be in the resolved map.
130
+ const allPresent = entries.every((e) => e !== undefined);
131
+ if (!allPresent) {
132
+ // If none are resolved → unset; if partial → mixed
133
+ const anyPresent = entries.some((e) => e !== undefined);
134
+ return anyPresent ? { status: "mixed" } : { status: "unset" };
135
+ }
136
+ // All present — check they agree on provider:model
137
+ const first = entries[0];
138
+ const allSame = entries.every((e) => e.provider === first.provider && e.model === first.model);
139
+ if (!allSame)
140
+ return { status: "mixed" };
141
+ const layer = first.source.endsWith("L2") ? "project" : "global";
142
+ return { status: "set", provider: first.provider, model: first.model, layer };
143
+ }
144
+ /** Return all three tier assignments as an array (stable order: heavy, standard, light). */
145
+ export function getAllTierAssignments(state) {
146
+ return TIERS.map((tier) => ({ tier, assignment: getTierAssignment(state, tier) }));
147
+ }
148
+ export function getScopedTierAssignment(state, tier, scope) {
149
+ const personas = TIER_PERSONAS[tier];
150
+ const targetBuffer = state.buffer[scope];
151
+ const otherBuffer = state.buffer[scope === "global" ? "project" : "global"];
152
+ const targetPersonaModels = targetBuffer["persona-models"] ?? {};
153
+ const otherPersonaModels = otherBuffer["persona-models"] ?? {};
154
+ // Check if all personas in this tier have assignments in the target layer
155
+ const targetEntries = personas.map((p) => targetPersonaModels[p]);
156
+ const targetPresent = targetEntries.filter((e) => e !== undefined);
157
+ if (targetPresent.length === personas.length) {
158
+ // All tier personas have assignments in target layer
159
+ const allSame = targetEntries.every((e) => e !== undefined && e.provider === targetEntries[0].provider && e.model === targetEntries[0].model);
160
+ if (allSame) {
161
+ return {
162
+ status: "set",
163
+ provider: targetEntries[0].provider,
164
+ model: targetEntries[0].model,
165
+ layer: scope,
166
+ };
167
+ }
168
+ return { status: "mixed" };
169
+ }
170
+ if (targetPresent.length === 0) {
171
+ // No assignments in target layer
172
+ // Check if any are set in the other layer
173
+ const otherEntries = personas.map((p) => otherPersonaModels[p]);
174
+ const otherPresent = otherEntries.filter((e) => e !== undefined);
175
+ if (otherPresent.length > 0) {
176
+ // Some are set in the other layer — show that
177
+ const allSameOther = otherPresent.every((e) => e.provider === otherPresent[0].provider && e.model === otherPresent[0].model);
178
+ if (allSameOther) {
179
+ return {
180
+ status: "set-in-other-layer",
181
+ provider: otherPresent[0].provider,
182
+ model: otherPresent[0].model,
183
+ otherLayer: scope === "global" ? "project" : "global",
184
+ };
185
+ }
186
+ return { status: "mixed" };
187
+ }
188
+ return { status: "unset" };
189
+ }
190
+ // Partial assignments in target layer
191
+ return { status: "mixed" };
192
+ }
193
+ export function getAllScopedTierAssignments(state, scope) {
194
+ return TIERS.map((tier) => ({ tier, assignment: getScopedTierAssignment(state, tier, scope) }));
195
+ }
196
+ /** Which tier does a persona belong to? Returns undefined for unknown names. */
197
+ export function getTierForPersona(persona) {
198
+ return PERSONA_META[persona]?.tier;
199
+ }
200
+ /** Persona names in a tier. */
201
+ export function getPersonasInTier(tier) {
202
+ return TIER_PERSONAS[tier];
203
+ }
204
+ // ── isEmpty selector (Phase E — replaces state.isEmpty snapshot) ──────────
205
+ /** True when neither global nor project config has any persona-model assignments.
206
+ * Replaces the old `state.isEmpty` snapshot — this is derived from buffer,
207
+ * so it stays correct after mutations. */
208
+ export function isConfigEmpty(state) {
209
+ const g = state.buffer.global;
210
+ const p = state.buffer.project;
211
+ const gEmpty = !g || !g["persona-models"] || Object.keys(g["persona-models"]).length === 0;
212
+ const pEmpty = !p || !p["persona-models"] || Object.keys(p["persona-models"]).length === 0;
213
+ return gEmpty && pEmpty;
214
+ }
215
+ // ── Source label for persona list display ─────────────────────────────────
216
+ /** Human-readable source label for a persona-model assignment.
217
+ * Replaces the old raw L1/L2/default-L1/default-L2 display.
218
+ * Uses tier labels when the persona has a known tier, otherwise falls back
219
+ * to generic "global"/"project" labels. */
220
+ export function personaSourceLabel(persona, source) {
221
+ const tier = PERSONA_META[persona]?.tier;
222
+ const layer = source === "L1" ? "global" : "project";
223
+ if (persona === "default") {
224
+ return `Default fallback (${layer})`;
225
+ }
226
+ if (tier) {
227
+ return `${TIER_LABELS[tier]} tier (${layer})`;
228
+ }
229
+ return `Per-persona (${layer})`;
230
+ }
231
+ //# sourceMappingURL=selectors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"selectors.js","sourceRoot":"","sources":["../../../../../src/extensions/forgecli/config-tui/state/selectors.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ export type { View, ConfigBuffer, AvailableModel, InitOptions, ConfigTuiState, ConfigTuiAction, PhaseOverride, ConfigLayer, ResolvedPersonaEntry, PersonaPickerEntry, PipelineOverrideSummary, TierAssignment, } from "./state/model.js";
2
+ export { CANONICAL_PHASES } from "./state/constants.js";
3
+ export { initialState } from "./state/init.js";
4
+ export { reducer } from "./state/reducer.js";
5
+ export { getActiveView, listResolvedPersonas, listPersonaPickerEntries, uniqueProviders, listPipelineOverrideSummaries, getPhaseOverride, getTierAssignment, getAllTierAssignments, getTierForPersona, getPersonasInTier, getPhaseTable, sourceToLabel, type PhaseTableRow, type ScopedTierAssignment, getScopedTierAssignment, getAllScopedTierAssignments, isConfigEmpty, personaSourceLabel, } from "./state/selectors.js";
6
+ export { writePersonaEntry, deletePersonaEntry, writePhaseOverride, clearPhaseOverride, writeTierAssignment, } from "./state/buffer.js";
@@ -0,0 +1,11 @@
1
+ // Config TUI state model — re-exports from split modules.
2
+ // Phase 1: This file is now a barrel that re-exports everything from state/.
3
+ // The implementation lives in state/model.ts, state/init.ts, state/reducer.ts,
4
+ // state/selectors.ts, state/buffer.ts, and state/constants.js.
5
+ // Phase 3: authError added to InitOptions and ConfigTuiState.
6
+ export { CANONICAL_PHASES } from "./state/constants.js";
7
+ export { initialState } from "./state/init.js";
8
+ export { reducer } from "./state/reducer.js";
9
+ export { getActiveView, listResolvedPersonas, listPersonaPickerEntries, uniqueProviders, listPipelineOverrideSummaries, getPhaseOverride, getTierAssignment, getAllTierAssignments, getTierForPersona, getPersonasInTier, getPhaseTable, sourceToLabel, getScopedTierAssignment, getAllScopedTierAssignments, isConfigEmpty, personaSourceLabel, } from "./state/selectors.js";
10
+ export { writePersonaEntry, deletePersonaEntry, writePhaseOverride, clearPhaseOverride, writeTierAssignment, } from "./state/buffer.js";
11
+ //# sourceMappingURL=state.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"state.js","sourceRoot":"","sources":["../../../../src/extensions/forgecli/config-tui/state.ts"],"names":[],"mappings":"AAAA,0DAA0D;AAC1D,6EAA6E;AAC7E,+EAA+E;AAC/E,+DAA+D;AAC/D,8DAA8D;AAiB9D,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AACxD,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAC/C,OAAO,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAC7C,OAAO,EACL,aAAa,EACb,oBAAoB,EACpB,wBAAwB,EACxB,eAAe,EACf,6BAA6B,EAC7B,gBAAgB,EAChB,iBAAiB,EACjB,qBAAqB,EACrB,iBAAiB,EACjB,iBAAiB,EACjB,aAAa,EACb,aAAa,EAGb,uBAAuB,EACvB,2BAA2B,EAC3B,aAAa,EACb,kBAAkB,GACnB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EACL,iBAAiB,EACjB,kBAAkB,EAClB,kBAAkB,EAClB,kBAAkB,EAClB,mBAAmB,GACpB,MAAM,mBAAmB,CAAC"}
@@ -0,0 +1,37 @@
1
+ import type { Theme } from "@earendil-works/pi-coding-agent";
2
+ export type { Theme };
3
+ /** Horizontal rule spanning the full width, themed as a border. */
4
+ export declare function rule(width: number, theme: Theme): string;
5
+ /** Breadcrumb: "forge config › personas › pick which". */
6
+ export declare function breadcrumb(parts: string[], width: number, theme: Theme): string;
7
+ export declare function cursor(isSelected: boolean, theme: Theme): string;
8
+ export declare function authBadge(ok: boolean, theme: Theme): string;
9
+ export declare function warning(text: string, theme: Theme): string;
10
+ export declare function muted(text: string, theme: Theme): string;
11
+ export declare function dim(text: string, theme: Theme): string;
12
+ export declare function accent(text: string, theme: Theme): string;
13
+ export declare function accentBold(text: string, theme: Theme): string;
14
+ export declare function error(text: string, theme: Theme): string;
15
+ export declare function success(text: string, theme: Theme): string;
16
+ /** Mark an unsaved-change indicator — themed as warning. */
17
+ export declare function dirtyMarker(theme: Theme): string;
18
+ /** Tier badge — displays Heavy / Standard / Light in accent color. */
19
+ export declare function tierBadge(tier: "heavy" | "standard" | "light", theme: Theme): string;
20
+ /**
21
+ * Right-pad a string that may contain ANSI escape codes to a given visible width.
22
+ * Uses visibleWidth so ANSI codes don't inflate the padding.
23
+ * Does NOT truncate — allows over-wide columns. Width-safety truncation
24
+ * is applied at the line level by truncateLines() / safeLines().
25
+ */
26
+ export declare function padRight(text: string, width: number): string;
27
+ /**
28
+ * Truncate a potentially-ANSI string to a visible width, padding with spaces
29
+ * if shorter. This replaces the old padRight for column-aligned output and
30
+ * is safe for themed text.
31
+ */
32
+ export declare function padOrTruncate(text: string, width: number): string;
33
+ /**
34
+ * Truncate every line to the given visible width. Applied as a final safety
35
+ * guard in every screen's render method so no line overflows the terminal.
36
+ */
37
+ export declare function truncateLines(lines: string[], width: number): string[];
@@ -0,0 +1,88 @@
1
+ // Config-TUI theme helpers — wraps pi Theme for consistent styling.
2
+ //
3
+ // Every render function receives a Theme instance and uses these helpers
4
+ // (or calls theme.fg/bg/bg directly) for all visible text. No raw string
5
+ // styling should appear in screen renderers — route everything through
6
+ // here or through theme methods so theme changes propagate globally.
7
+ import { truncateToWidth, visibleWidth } from "@earendil-works/pi-tui";
8
+ // ── Structural helpers ──────────────────────────────────────────────────────
9
+ /** Horizontal rule spanning the full width, themed as a border. */
10
+ export function rule(width, theme) {
11
+ return theme.fg("border", "─".repeat(Math.max(1, width)));
12
+ }
13
+ /** Breadcrumb: "forge config › personas › pick which". */
14
+ export function breadcrumb(parts, width, theme) {
15
+ const raw = parts.join(" › ");
16
+ const truncated = truncateToWidth(raw, width, "");
17
+ return theme.fg("accent", theme.bold(truncated));
18
+ }
19
+ // ── Inline style helpers ────────────────────────────────────────────────────
20
+ export function cursor(isSelected, theme) {
21
+ return isSelected ? theme.fg("accent", "▸") : " ";
22
+ }
23
+ export function authBadge(ok, theme) {
24
+ return ok ? theme.fg("success", "✓") : theme.fg("error", "✗");
25
+ }
26
+ export function warning(text, theme) {
27
+ return theme.fg("warning", text);
28
+ }
29
+ export function muted(text, theme) {
30
+ return theme.fg("muted", text);
31
+ }
32
+ export function dim(text, theme) {
33
+ return theme.fg("dim", text);
34
+ }
35
+ export function accent(text, theme) {
36
+ return theme.fg("accent", text);
37
+ }
38
+ export function accentBold(text, theme) {
39
+ return theme.fg("accent", theme.bold(text));
40
+ }
41
+ export function error(text, theme) {
42
+ return theme.fg("error", text);
43
+ }
44
+ export function success(text, theme) {
45
+ return theme.fg("success", text);
46
+ }
47
+ /** Mark an unsaved-change indicator — themed as warning. */
48
+ export function dirtyMarker(theme) {
49
+ return theme.fg("warning", "* unsaved");
50
+ }
51
+ /** Tier badge — displays Heavy / Standard / Light in accent color. */
52
+ export function tierBadge(tier, theme) {
53
+ const labels = { heavy: "Heavy", standard: "Standard", light: "Light" };
54
+ return theme.fg("accent", labels[tier] ?? tier);
55
+ }
56
+ // ── Padding (ANSI-aware) ────────────────────────────────────────────────────
57
+ /**
58
+ * Right-pad a string that may contain ANSI escape codes to a given visible width.
59
+ * Uses visibleWidth so ANSI codes don't inflate the padding.
60
+ * Does NOT truncate — allows over-wide columns. Width-safety truncation
61
+ * is applied at the line level by truncateLines() / safeLines().
62
+ */
63
+ export function padRight(text, width) {
64
+ const vis = visibleWidth(text);
65
+ if (vis >= width)
66
+ return text;
67
+ return text + " ".repeat(width - vis);
68
+ }
69
+ /**
70
+ * Truncate a potentially-ANSI string to a visible width, padding with spaces
71
+ * if shorter. This replaces the old padRight for column-aligned output and
72
+ * is safe for themed text.
73
+ */
74
+ export function padOrTruncate(text, width) {
75
+ const vis = visibleWidth(text);
76
+ if (vis >= width)
77
+ return truncateToWidth(text, width, "");
78
+ return text + " ".repeat(width - vis);
79
+ }
80
+ // ── Width safety ─────────────────────────────────────────────────────────────
81
+ /**
82
+ * Truncate every line to the given visible width. Applied as a final safety
83
+ * guard in every screen's render method so no line overflows the terminal.
84
+ */
85
+ export function truncateLines(lines, width) {
86
+ return lines.map(line => truncateToWidth(line, width, ""));
87
+ }
88
+ //# sourceMappingURL=theme.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"theme.js","sourceRoot":"","sources":["../../../../src/extensions/forgecli/config-tui/theme.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,28 @@
1
+ export type Tier = "heavy" | "standard" | "light";
2
+ export declare const TIERS: readonly Tier[];
3
+ export interface PersonaMeta {
4
+ name: string;
5
+ emoji: string;
6
+ /** Short user-facing role description shown in parentheses on tier rows. */
7
+ role: string;
8
+ tier: Tier;
9
+ }
10
+ export declare const PERSONA_META: Record<string, PersonaMeta>;
11
+ export declare const TIER_PERSONAS: Record<Tier, readonly string[]>;
12
+ export declare const TIER_LABELS: Record<Tier, string>;
13
+ /** Short sub-copy shown after each tier row in parentheses. */
14
+ export declare const TIER_SUB_LABELS: Record<Tier, string>;
15
+ export declare const PHASE_PERSONA_TABLE: ReadonlyArray<{
16
+ role: string;
17
+ personaNoun: string;
18
+ tier: Tier;
19
+ }>;
20
+ /** Look up which tier a persona belongs to. Returns undefined for unknown names. */
21
+ export declare function getTierForPersona(persona: string): Tier | undefined;
22
+ /** Return persona names in the given tier. */
23
+ export declare function getPersonasInTier(tier: Tier): readonly string[];
24
+ /**
25
+ * Build a one-line emoji summary for the personas in a tier.
26
+ * E.g. "🗻 architect, 🌿 supervisor"
27
+ */
28
+ export declare function tierPersonaLine(tier: Tier): string;
@@ -0,0 +1,69 @@
1
+ // Tier ↔ persona ↔ emoji ↔ role mapping — single source of truth.
2
+ // Phase A: hardcoded tables. Personas are stable; new personas require a
3
+ // one-line change here. Tier strings never enter the config JSON (Plan 16 IL3).
4
+ export const TIERS = ["heavy", "standard", "light"];
5
+ // ── Persona metadata (9 personas) ────────────────────────────────────────────
6
+ export const PERSONA_META = {
7
+ architect: { name: "architect", emoji: "🗻", role: "plan review, sign-off", tier: "heavy" },
8
+ supervisor: { name: "supervisor", emoji: "🌿", role: "code review, approval", tier: "heavy" },
9
+ engineer: { name: "engineer", emoji: "🌱", role: "planning, implementation", tier: "standard" },
10
+ "bug-fixer": { name: "bug-fixer", emoji: "🐛", role: "bug triage, fix", tier: "standard" },
11
+ "qa-engineer": { name: "qa-engineer", emoji: "🍵", role: "validation, testing", tier: "standard" },
12
+ "product-manager": { name: "product-manager", emoji: "📋", role: "sprint intake, stories", tier: "standard" },
13
+ collator: { name: "collator", emoji: "🍃", role: "KB regeneration, writeback", tier: "light" },
14
+ librarian: { name: "librarian", emoji: "📚", role: "indexing, cataloguing", tier: "light" },
15
+ orchestrator: { name: "orchestrator", emoji: "🌊", role: "task flow, coordination", tier: "light" },
16
+ };
17
+ // ── Tier → persona membership ────────────────────────────────────────────────
18
+ export const TIER_PERSONAS = {
19
+ heavy: ["architect", "supervisor"],
20
+ standard: ["engineer", "bug-fixer", "qa-engineer", "product-manager"],
21
+ light: ["collator", "librarian", "orchestrator"],
22
+ };
23
+ // ── Tier display labels (user-facing) ───────────────────────────────────────
24
+ export const TIER_LABELS = {
25
+ heavy: "Heavy",
26
+ standard: "Standard",
27
+ light: "Light",
28
+ };
29
+ /** Short sub-copy shown after each tier row in parentheses. */
30
+ export const TIER_SUB_LABELS = {
31
+ heavy: "review, sign-off",
32
+ standard: "planning, implementation",
33
+ light: "writeback, indexing",
34
+ };
35
+ // ── Phase ↔ persona binding ─────────────────────────────────────────────────
36
+ // Mirrored from state/constants.ts CANONICAL_PHASES. Kept here so tier-meta
37
+ // is self-contained (the config-tui module doesn't import the orchestrator).
38
+ export const PHASE_PERSONA_TABLE = [
39
+ { role: "plan", personaNoun: "engineer", tier: "standard" },
40
+ { role: "review-plan", personaNoun: "supervisor", tier: "heavy" },
41
+ { role: "implement", personaNoun: "engineer", tier: "standard" },
42
+ { role: "review-code", personaNoun: "supervisor", tier: "heavy" },
43
+ { role: "validate", personaNoun: "qa-engineer", tier: "standard" },
44
+ { role: "approve", personaNoun: "architect", tier: "heavy" },
45
+ { role: "writeback", personaNoun: "collator", tier: "light" },
46
+ { role: "commit", personaNoun: "engineer", tier: "standard" },
47
+ ];
48
+ // ── Helpers ──────────────────────────────────────────────────────────────────
49
+ /** Look up which tier a persona belongs to. Returns undefined for unknown names. */
50
+ export function getTierForPersona(persona) {
51
+ return PERSONA_META[persona]?.tier;
52
+ }
53
+ /** Return persona names in the given tier. */
54
+ export function getPersonasInTier(tier) {
55
+ return TIER_PERSONAS[tier];
56
+ }
57
+ /**
58
+ * Build a one-line emoji summary for the personas in a tier.
59
+ * E.g. "🗻 architect, 🌿 supervisor"
60
+ */
61
+ export function tierPersonaLine(tier) {
62
+ return TIER_PERSONAS[tier]
63
+ .map((p) => {
64
+ const meta = PERSONA_META[p];
65
+ return meta ? `${meta.emoji} ${meta.name}` : p;
66
+ })
67
+ .join(", ");
68
+ }
69
+ //# sourceMappingURL=tier-meta.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tier-meta.js","sourceRoot":"","sources":["../../../../src/extensions/forgecli/config-tui/tier-meta.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ import type { PersonaModelsMap, PipelineConfig } from "./config-layer.js";
2
+ export type ConfigLayer = "global" | "project";
3
+ export interface RoutingConfigBuffer {
4
+ "persona-models"?: PersonaModelsMap;
5
+ pipelines?: Record<string, PipelineConfig>;
6
+ }
7
+ export interface WriteOptions {
8
+ layer: ConfigLayer;
9
+ cwd: string;
10
+ buffer: RoutingConfigBuffer;
11
+ }
12
+ export declare function resolveTargetPath(opts: {
13
+ layer: ConfigLayer;
14
+ cwd: string;
15
+ }): string;
16
+ export declare function writeRoutingConfig(opts: WriteOptions): string;
@@ -0,0 +1,63 @@
1
+ // Atomic, schema-validated writer for forge-cli routing config files.
2
+ //
3
+ // Plan 16, Slice 4a. Writes ONLY to:
4
+ // - global layer (L1) → join(getAgentDir(), "forge-cli", "config.json")
5
+ // - project layer (L2/L3/L4) → join(cwd, ".pi", "forge-cli", "config.json")
6
+ //
7
+ // Never writes to .forge/config.json — that's the plugin's pipeline catalogue,
8
+ // read-only from this TUI.
9
+ //
10
+ // Write protocol:
11
+ // 1. Validate buffer against forge-cli-schema.json. Throw on fail.
12
+ // 2. If buffer is empty ({}) and target file exists → unlink. Return target.
13
+ // 3. Otherwise: write to <target>.tmp, fsync, rename atomically to <target>.
14
+ import * as fs from "node:fs";
15
+ import * as path from "node:path";
16
+ import { getAgentDir } from "@earendil-works/pi-coding-agent";
17
+ import { Ajv } from "ajv";
18
+ import schema from "./forge-cli-schema.json" with { type: "json" };
19
+ const ajv = new Ajv({ allErrors: true });
20
+ const validate = ajv.compile(schema);
21
+ export function resolveTargetPath(opts) {
22
+ if (opts.layer === "global") {
23
+ return path.join(getAgentDir(), "forge-cli", "config.json");
24
+ }
25
+ return path.join(opts.cwd, ".pi", "forge-cli", "config.json");
26
+ }
27
+ function isEmpty(buffer) {
28
+ const personaCount = Object.keys(buffer["persona-models"] ?? {}).length;
29
+ const pipelineCount = Object.keys(buffer.pipelines ?? {}).length;
30
+ return personaCount === 0 && pipelineCount === 0;
31
+ }
32
+ export function writeRoutingConfig(opts) {
33
+ const target = resolveTargetPath(opts);
34
+ // Empty buffer → delete file if present.
35
+ if (isEmpty(opts.buffer)) {
36
+ if (fs.existsSync(target)) {
37
+ fs.unlinkSync(target);
38
+ }
39
+ return target;
40
+ }
41
+ // Validate FIRST. Any failure short-circuits before touching the filesystem.
42
+ const ok = validate(opts.buffer);
43
+ if (!ok) {
44
+ const messages = validate.errors?.map((e) => `${e.instancePath || "/"} ${e.message}`).join("; ") ?? "unknown";
45
+ throw new Error(`forge-cli config schema error: ${messages}`);
46
+ }
47
+ // Ensure parent dir exists.
48
+ fs.mkdirSync(path.dirname(target), { recursive: true });
49
+ // Atomic write: temp file + rename. Pretty-print for human-readable diffs.
50
+ const tmpPath = `${target}.tmp`;
51
+ const serialized = `${JSON.stringify(opts.buffer, null, 2)}\n`;
52
+ const fd = fs.openSync(tmpPath, "w");
53
+ try {
54
+ fs.writeSync(fd, serialized);
55
+ fs.fsyncSync(fd);
56
+ }
57
+ finally {
58
+ fs.closeSync(fd);
59
+ }
60
+ fs.renameSync(tmpPath, target);
61
+ return target;
62
+ }
63
+ //# sourceMappingURL=config-writer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config-writer.js","sourceRoot":"","sources":["../../../src/extensions/forgecli/config-writer.ts"],"names":[],"mappings":"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"}