@wrongstack/cli 0.295.1 → 0.296.2

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 (383) hide show
  1. package/data/providers.json +0 -24
  2. package/dist/acp-A5OSIU2P.js +824 -0
  3. package/dist/acp-A5OSIU2P.js.map +7 -0
  4. package/dist/acp-server-agent.d.ts.map +1 -1
  5. package/dist/arg-parser.d.ts.map +1 -1
  6. package/dist/audit-2ZSFGNIF.js +102 -0
  7. package/dist/audit-2ZSFGNIF.js.map +7 -0
  8. package/dist/auth-CJWQJVRH.js +504 -0
  9. package/dist/auth-CJWQJVRH.js.map +7 -0
  10. package/dist/auth-menu/auth-menu-audit.d.ts +0 -4
  11. package/dist/auth-menu/auth-menu-audit.d.ts.map +1 -1
  12. package/dist/bench-7ZDWSNEF.js +278 -0
  13. package/dist/bench-7ZDWSNEF.js.map +7 -0
  14. package/dist/boot/brain-decision-log.d.ts +7 -5
  15. package/dist/boot/brain-decision-log.d.ts.map +1 -1
  16. package/dist/boot/dispatch-webui.d.ts +4 -8
  17. package/dist/boot/dispatch-webui.d.ts.map +1 -1
  18. package/dist/boot/system-prompt-builder.d.ts +3 -0
  19. package/dist/boot/system-prompt-builder.d.ts.map +1 -1
  20. package/dist/boot/tui-coordinator-callbacks.d.ts +45 -0
  21. package/dist/boot/tui-coordinator-callbacks.d.ts.map +1 -0
  22. package/dist/boot/tui-project-switch.d.ts +2 -3
  23. package/dist/boot/tui-project-switch.d.ts.map +1 -1
  24. package/dist/boot/tui-runtime-state.d.ts +5 -6
  25. package/dist/boot/tui-runtime-state.d.ts.map +1 -1
  26. package/dist/boot/tui-session-resume.d.ts.map +1 -1
  27. package/dist/boot/tui-settings-adapter.d.ts +2 -3
  28. package/dist/boot/tui-settings-adapter.d.ts.map +1 -1
  29. package/dist/boot.d.ts.map +1 -1
  30. package/dist/brain-menu/panel-service.d.ts.map +1 -1
  31. package/dist/chimera-review-task.d.ts +6 -0
  32. package/dist/chimera-review-task.d.ts.map +1 -0
  33. package/dist/chimera-reviewer-policy.d.ts +34 -0
  34. package/dist/chimera-reviewer-policy.d.ts.map +1 -0
  35. package/dist/chronicle-QQEQFSSE.js +256 -0
  36. package/dist/chronicle-QQEQFSSE.js.map +7 -0
  37. package/dist/chunk-5N34EWJR.js +418 -0
  38. package/dist/chunk-5N34EWJR.js.map +7 -0
  39. package/dist/chunk-66T43Q4Y.js +90 -0
  40. package/dist/chunk-66T43Q4Y.js.map +7 -0
  41. package/dist/chunk-7OCVIDC7.js +11 -0
  42. package/dist/chunk-7OCVIDC7.js.map +7 -0
  43. package/dist/chunk-ABXK4VVY.js +84 -0
  44. package/dist/chunk-ABXK4VVY.js.map +7 -0
  45. package/dist/chunk-AXVZMEWG.js +306 -0
  46. package/dist/chunk-AXVZMEWG.js.map +7 -0
  47. package/dist/chunk-AZESNNIC.js +216 -0
  48. package/dist/chunk-AZESNNIC.js.map +7 -0
  49. package/dist/chunk-BGFM3PD7.js +41 -0
  50. package/dist/chunk-BGFM3PD7.js.map +7 -0
  51. package/dist/chunk-DPJZQCVP.js +13 -0
  52. package/dist/chunk-DPJZQCVP.js.map +7 -0
  53. package/dist/chunk-F4PEGAJZ.js +176 -0
  54. package/dist/chunk-F4PEGAJZ.js.map +7 -0
  55. package/dist/chunk-IHBYBYGA.js +443 -0
  56. package/dist/chunk-IHBYBYGA.js.map +7 -0
  57. package/dist/chunk-IN4GXGYW.js +425 -0
  58. package/dist/chunk-IN4GXGYW.js.map +7 -0
  59. package/dist/chunk-JBSQ7ONN.js +1023 -0
  60. package/dist/chunk-JBSQ7ONN.js.map +7 -0
  61. package/dist/chunk-JBTFWWKV.js +1325 -0
  62. package/dist/chunk-JBTFWWKV.js.map +7 -0
  63. package/dist/chunk-JUHRI6OV.js +100 -0
  64. package/dist/chunk-JUHRI6OV.js.map +7 -0
  65. package/dist/chunk-OP47B3IX.js +142 -0
  66. package/dist/chunk-OP47B3IX.js.map +7 -0
  67. package/dist/chunk-PJHET45A.js +158 -0
  68. package/dist/chunk-PJHET45A.js.map +7 -0
  69. package/dist/chunk-Q5GTM25S.js +17 -0
  70. package/dist/chunk-Q5GTM25S.js.map +7 -0
  71. package/dist/chunk-QD544J2B.js +19 -0
  72. package/dist/chunk-QD544J2B.js.map +7 -0
  73. package/dist/chunk-QUNHS6O3.js +258 -0
  74. package/dist/chunk-QUNHS6O3.js.map +7 -0
  75. package/dist/chunk-TADVX644.js +480 -0
  76. package/dist/chunk-TADVX644.js.map +7 -0
  77. package/dist/chunk-TGDHN4LM.js +81 -0
  78. package/dist/chunk-TGDHN4LM.js.map +7 -0
  79. package/dist/chunk-TYO2OVAD.js +50 -0
  80. package/dist/chunk-TYO2OVAD.js.map +7 -0
  81. package/dist/chunk-VCYZ3WZV.js +14 -0
  82. package/dist/chunk-VCYZ3WZV.js.map +7 -0
  83. package/dist/chunk-VJUEZZYB.js +29 -0
  84. package/dist/chunk-VJUEZZYB.js.map +7 -0
  85. package/dist/chunk-WHOIR577.js +1 -0
  86. package/dist/chunk-WHOIR577.js.map +7 -0
  87. package/dist/chunk-WY7KKOUK.js +460 -0
  88. package/dist/chunk-WY7KKOUK.js.map +7 -0
  89. package/dist/chunk-X5DQTPXT.js +3059 -0
  90. package/dist/chunk-X5DQTPXT.js.map +7 -0
  91. package/dist/chunk-XJXDOF63.js +28 -0
  92. package/dist/chunk-XJXDOF63.js.map +7 -0
  93. package/dist/chunk-XWEGWYDU.js +560 -0
  94. package/dist/chunk-XWEGWYDU.js.map +7 -0
  95. package/dist/chunk-YWUPHRGB.js +346 -0
  96. package/dist/chunk-YWUPHRGB.js.map +7 -0
  97. package/dist/chunk-Z7YGASQP.js +313 -0
  98. package/dist/chunk-Z7YGASQP.js.map +7 -0
  99. package/dist/cli-entry-main.d.ts +2 -0
  100. package/dist/cli-entry-main.d.ts.map +1 -0
  101. package/dist/cli-entry-point.d.ts +3 -3
  102. package/dist/cli-entry-point.d.ts.map +1 -1
  103. package/dist/cli-main-6AU6E4XZ.js +29126 -0
  104. package/dist/cli-main-6AU6E4XZ.js.map +7 -0
  105. package/dist/cli-main-helpers.d.ts +21 -0
  106. package/dist/cli-main-helpers.d.ts.map +1 -0
  107. package/dist/cli-main.d.ts +25 -1
  108. package/dist/cli-main.d.ts.map +1 -1
  109. package/dist/context-limit.d.ts +48 -0
  110. package/dist/context-limit.d.ts.map +1 -1
  111. package/dist/diag-doctor-OQ3AA63O.js +170 -0
  112. package/dist/diag-doctor-OQ3AA63O.js.map +7 -0
  113. package/dist/execute-deps.d.ts +10 -12
  114. package/dist/execute-deps.d.ts.map +1 -1
  115. package/dist/execution-V26SE52F.js +4656 -0
  116. package/dist/execution-V26SE52F.js.map +7 -0
  117. package/dist/execution-chimera-ask.d.ts +10 -0
  118. package/dist/execution-chimera-ask.d.ts.map +1 -0
  119. package/dist/execution-chimera-cascade.d.ts +15 -0
  120. package/dist/execution-chimera-cascade.d.ts.map +1 -0
  121. package/dist/execution-cleanup.d.ts +23 -0
  122. package/dist/execution-cleanup.d.ts.map +1 -0
  123. package/dist/execution-kanban-dispatch.d.ts +10 -0
  124. package/dist/execution-kanban-dispatch.d.ts.map +1 -0
  125. package/dist/execution-repl-fleet-callbacks.d.ts +11 -0
  126. package/dist/execution-repl-fleet-callbacks.d.ts.map +1 -0
  127. package/dist/execution-storage-observability.d.ts +3 -0
  128. package/dist/execution-storage-observability.d.ts.map +1 -0
  129. package/dist/execution-tui-next-step-callbacks.d.ts +20 -0
  130. package/dist/execution-tui-next-step-callbacks.d.ts.map +1 -0
  131. package/dist/execution.d.ts +2 -139
  132. package/dist/execution.d.ts.map +1 -1
  133. package/dist/export-TPORYVRZ.js +64 -0
  134. package/dist/export-TPORYVRZ.js.map +7 -0
  135. package/dist/fleet/host-acp-runner-cache.d.ts +9 -0
  136. package/dist/fleet/host-acp-runner-cache.d.ts.map +1 -0
  137. package/dist/fleet/host-acp.d.ts +3 -0
  138. package/dist/fleet/host-acp.d.ts.map +1 -0
  139. package/dist/fleet/host-concurrency.d.ts +2 -0
  140. package/dist/fleet/host-concurrency.d.ts.map +1 -0
  141. package/dist/fleet/host-context.d.ts +5 -0
  142. package/dist/fleet/host-context.d.ts.map +1 -0
  143. package/dist/fleet/host-director-builder.d.ts +24 -0
  144. package/dist/fleet/host-director-builder.d.ts.map +1 -0
  145. package/dist/fleet/host-director-event-bridges.d.ts +37 -0
  146. package/dist/fleet/host-director-event-bridges.d.ts.map +1 -0
  147. package/dist/fleet/host-director-services.d.ts +20 -0
  148. package/dist/fleet/host-director-services.d.ts.map +1 -0
  149. package/dist/fleet/host-event-bridge.d.ts +17 -0
  150. package/dist/fleet/host-event-bridge.d.ts.map +1 -0
  151. package/dist/fleet/host-helpers.d.ts +22 -0
  152. package/dist/fleet/host-helpers.d.ts.map +1 -0
  153. package/dist/fleet/host-learning-tracker.d.ts +11 -0
  154. package/dist/fleet/host-learning-tracker.d.ts.map +1 -0
  155. package/dist/fleet/host-learning.d.ts +4 -0
  156. package/dist/fleet/host-learning.d.ts.map +1 -0
  157. package/dist/fleet/host-lifecycle-events.d.ts +4 -0
  158. package/dist/fleet/host-lifecycle-events.d.ts.map +1 -0
  159. package/dist/fleet/host-paths.d.ts +3 -0
  160. package/dist/fleet/host-paths.d.ts.map +1 -0
  161. package/dist/fleet/host-provider.d.ts +22 -0
  162. package/dist/fleet/host-provider.d.ts.map +1 -0
  163. package/dist/fleet/host-session-writer.d.ts +3 -0
  164. package/dist/fleet/host-session-writer.d.ts.map +1 -0
  165. package/dist/fleet/host-shadow-pass.d.ts +21 -0
  166. package/dist/fleet/host-shadow-pass.d.ts.map +1 -0
  167. package/dist/fleet/host-spawn-types.d.ts +25 -0
  168. package/dist/fleet/host-spawn-types.d.ts.map +1 -0
  169. package/dist/fleet/host-status.d.ts +48 -0
  170. package/dist/fleet/host-status.d.ts.map +1 -0
  171. package/dist/fleet/host-subagent-factory.d.ts +16 -0
  172. package/dist/fleet/host-subagent-factory.d.ts.map +1 -0
  173. package/dist/fleet/host-supervisor.d.ts +16 -0
  174. package/dist/fleet/host-supervisor.d.ts.map +1 -0
  175. package/dist/fleet/host-task-result-report.d.ts +11 -0
  176. package/dist/fleet/host-task-result-report.d.ts.map +1 -0
  177. package/dist/fleet/host-types.d.ts +89 -0
  178. package/dist/fleet/host-types.d.ts.map +1 -0
  179. package/dist/fleet/host.d.ts +10 -357
  180. package/dist/fleet/host.d.ts.map +1 -1
  181. package/dist/hq-BECGICEZ.js +547 -0
  182. package/dist/hq-BECGICEZ.js.map +7 -0
  183. package/dist/hq-command-controller.d.ts +2 -2
  184. package/dist/hq-command-controller.d.ts.map +1 -1
  185. package/dist/hq-server/project-root.d.ts +5 -0
  186. package/dist/hq-server/project-root.d.ts.map +1 -0
  187. package/dist/hq-server/routes/auth-handlers.d.ts +32 -0
  188. package/dist/hq-server/routes/auth-handlers.d.ts.map +1 -0
  189. package/dist/hq-server/routes/session-handlers.d.ts +8 -0
  190. package/dist/hq-server/routes/session-handlers.d.ts.map +1 -0
  191. package/dist/hq-server/routes.d.ts +2 -2
  192. package/dist/hq-server/routes.d.ts.map +1 -1
  193. package/dist/hq-server-FJOVOERO.js +39 -0
  194. package/dist/hq-server-FJOVOERO.js.map +7 -0
  195. package/dist/hq-server.d.ts.map +1 -1
  196. package/dist/hq-ttl-U2FAYFAT.js +8 -0
  197. package/dist/hq-ttl-U2FAYFAT.js.map +7 -0
  198. package/dist/hq-tunnel-YZLRONPV.js +111 -0
  199. package/dist/hq-tunnel-YZLRONPV.js.map +7 -0
  200. package/dist/index.d.ts +2 -1
  201. package/dist/index.d.ts.map +1 -1
  202. package/dist/index.js +2503 -53026
  203. package/dist/index.js.map +4 -4
  204. package/dist/init-E2NDDOHI.js +27 -0
  205. package/dist/init-E2NDDOHI.js.map +7 -0
  206. package/dist/kanban-dispatch-route.d.ts +14 -0
  207. package/dist/kanban-dispatch-route.d.ts.map +1 -0
  208. package/dist/kanban-hq-sync.d.ts +2 -0
  209. package/dist/kanban-hq-sync.d.ts.map +1 -1
  210. package/dist/kanban-run-mirror-EKVNGXWW.js +12 -0
  211. package/dist/kanban-run-mirror-EKVNGXWW.js.map +7 -0
  212. package/dist/live-settings-input.d.ts +69 -0
  213. package/dist/live-settings-input.d.ts.map +1 -0
  214. package/dist/mailbox-serve-2UWHEN3M.js +302 -0
  215. package/dist/mailbox-serve-2UWHEN3M.js.map +7 -0
  216. package/dist/mcp-CYLPUEHC.js +413 -0
  217. package/dist/mcp-CYLPUEHC.js.map +7 -0
  218. package/dist/modeldiag-HENYJ4N7.js +1290 -0
  219. package/dist/modeldiag-HENYJ4N7.js.map +7 -0
  220. package/dist/permissions-FNYLZIL4.js +115 -0
  221. package/dist/permissions-FNYLZIL4.js.map +7 -0
  222. package/dist/picker-key-state.d.ts +7 -0
  223. package/dist/picker-key-state.d.ts.map +1 -0
  224. package/dist/picker-model-picker.d.ts +6 -0
  225. package/dist/picker-model-picker.d.ts.map +1 -0
  226. package/dist/picker-ui.d.ts +17 -0
  227. package/dist/picker-ui.d.ts.map +1 -0
  228. package/dist/picker.d.ts +4 -37
  229. package/dist/picker.d.ts.map +1 -1
  230. package/dist/plugin-usage-OU6X6LM3.js +40 -0
  231. package/dist/plugin-usage-OU6X6LM3.js.map +7 -0
  232. package/dist/plugins-4LJ5IUBI.js +24 -0
  233. package/dist/plugins-4LJ5IUBI.js.map +7 -0
  234. package/dist/pre-launch.d.ts +0 -1
  235. package/dist/pre-launch.d.ts.map +1 -1
  236. package/dist/project-BLQ3ALVL.js +76 -0
  237. package/dist/project-BLQ3ALVL.js.map +7 -0
  238. package/dist/project-manifest-GE25PW4S.js +18 -0
  239. package/dist/project-manifest-GE25PW4S.js.map +7 -0
  240. package/dist/project-picker-BOCWHBXP.js +17 -0
  241. package/dist/project-picker-BOCWHBXP.js.map +7 -0
  242. package/dist/projects-XE76NFNZ.js +38 -0
  243. package/dist/projects-XE76NFNZ.js.map +7 -0
  244. package/dist/provider-helpers.d.ts +22 -6
  245. package/dist/provider-helpers.d.ts.map +1 -1
  246. package/dist/providers-models-GDELBHZK.js +589 -0
  247. package/dist/providers-models-GDELBHZK.js.map +7 -0
  248. package/dist/quick-VIO2BEHS.js +10 -0
  249. package/dist/quick-VIO2BEHS.js.map +7 -0
  250. package/dist/repl-auto-proceed.d.ts +19 -0
  251. package/dist/repl-auto-proceed.d.ts.map +1 -0
  252. package/dist/repl-client-registration.d.ts +7 -0
  253. package/dist/repl-client-registration.d.ts.map +1 -0
  254. package/dist/repl-input.d.ts +11 -0
  255. package/dist/repl-input.d.ts.map +1 -0
  256. package/dist/repl-options.d.ts +54 -0
  257. package/dist/repl-options.d.ts.map +1 -0
  258. package/dist/repl-rendering.d.ts +4 -0
  259. package/dist/repl-rendering.d.ts.map +1 -0
  260. package/dist/repl-suggestions.d.ts +21 -0
  261. package/dist/repl-suggestions.d.ts.map +1 -0
  262. package/dist/repl.d.ts +3 -162
  263. package/dist/repl.d.ts.map +1 -1
  264. package/dist/replay-KCTXNMZQ.js +75 -0
  265. package/dist/replay-KCTXNMZQ.js.map +7 -0
  266. package/dist/rewind-EJMVFVLS.js +185 -0
  267. package/dist/rewind-EJMVFVLS.js.map +7 -0
  268. package/dist/sdd-runtime-IKPROVV2.js +54 -0
  269. package/dist/sdd-runtime-IKPROVV2.js.map +7 -0
  270. package/dist/services/sdd/project-context.d.ts +1 -1
  271. package/dist/services/sdd/project-context.d.ts.map +1 -1
  272. package/dist/services/statusline-config.d.ts +1 -1
  273. package/dist/services/statusline-config.d.ts.map +1 -1
  274. package/dist/session-event-wiring.d.ts +2 -2
  275. package/dist/session-event-wiring.d.ts.map +1 -1
  276. package/dist/sessions-config-NLCMK3BY.js +409 -0
  277. package/dist/sessions-config-NLCMK3BY.js.map +7 -0
  278. package/dist/settings-menu.d.ts +3 -18
  279. package/dist/settings-menu.d.ts.map +1 -1
  280. package/dist/simpleui-dist-JIFGUJO7.js +93 -0
  281. package/dist/simpleui-dist-JIFGUJO7.js.map +7 -0
  282. package/dist/slash-commands/brain.d.ts.map +1 -1
  283. package/dist/slash-commands/clear.d.ts.map +1 -1
  284. package/dist/slash-commands/fallback.d.ts.map +1 -1
  285. package/dist/slash-commands/kanban-agent-helpers.d.ts +18 -0
  286. package/dist/slash-commands/kanban-agent-helpers.d.ts.map +1 -0
  287. package/dist/slash-commands/kanban-format.d.ts +16 -0
  288. package/dist/slash-commands/kanban-format.d.ts.map +1 -0
  289. package/dist/slash-commands/kanban-help.d.ts +2 -0
  290. package/dist/slash-commands/kanban-help.d.ts.map +1 -0
  291. package/dist/slash-commands/kanban.d.ts.map +1 -1
  292. package/dist/slash-commands/mailbox-demo.d.ts.map +1 -1
  293. package/dist/slash-commands/mailbox.d.ts +2 -1
  294. package/dist/slash-commands/mailbox.d.ts.map +1 -1
  295. package/dist/slash-commands/memory-compact.d.ts +5 -0
  296. package/dist/slash-commands/memory-compact.d.ts.map +1 -0
  297. package/dist/slash-commands/memory-flags.d.ts +36 -0
  298. package/dist/slash-commands/memory-flags.d.ts.map +1 -0
  299. package/dist/slash-commands/memory-formatters.d.ts +16 -0
  300. package/dist/slash-commands/memory-formatters.d.ts.map +1 -0
  301. package/dist/slash-commands/memory.d.ts.map +1 -1
  302. package/dist/slash-commands/mouse.d.ts +2 -2
  303. package/dist/slash-commands/review.d.ts.map +1 -1
  304. package/dist/slash-commands/sdd-command-helpers.d.ts +23 -0
  305. package/dist/slash-commands/sdd-command-helpers.d.ts.map +1 -0
  306. package/dist/slash-commands/sdd-format.d.ts +32 -0
  307. package/dist/slash-commands/sdd-format.d.ts.map +1 -0
  308. package/dist/slash-commands/sdd.d.ts.map +1 -1
  309. package/dist/subcommands/handlers/chronicle.d.ts.map +1 -1
  310. package/dist/subcommands/handlers/mailbox-serve.d.ts.map +1 -1
  311. package/dist/subcommands/handlers/model-smoke-test.d.ts +51 -0
  312. package/dist/subcommands/handlers/model-smoke-test.d.ts.map +1 -0
  313. package/dist/subcommands/handlers/modeldiag-profiles.d.ts +64 -0
  314. package/dist/subcommands/handlers/modeldiag-profiles.d.ts.map +1 -0
  315. package/dist/subcommands/handlers/modeldiag.d.ts.map +1 -1
  316. package/dist/subcommands/handlers/per-subcommand-deep-help-table.d.ts +3 -0
  317. package/dist/subcommands/handlers/per-subcommand-deep-help-table.d.ts.map +1 -0
  318. package/dist/subcommands/handlers/per-subcommand-help-data.d.ts +3 -0
  319. package/dist/subcommands/handlers/per-subcommand-help-data.d.ts.map +1 -0
  320. package/dist/subcommands/handlers/per-subcommand-help-table.d.ts +36 -0
  321. package/dist/subcommands/handlers/per-subcommand-help-table.d.ts.map +1 -0
  322. package/dist/subcommands/handlers/per-subcommand-help-types.d.ts +18 -0
  323. package/dist/subcommands/handlers/per-subcommand-help-types.d.ts.map +1 -0
  324. package/dist/subcommands/handlers/per-subcommand-help.d.ts +2 -80
  325. package/dist/subcommands/handlers/per-subcommand-help.d.ts.map +1 -1
  326. package/dist/subcommands/handlers/rewind.d.ts.map +1 -1
  327. package/dist/subcommands/index.d.ts +7 -0
  328. package/dist/subcommands/index.d.ts.map +1 -1
  329. package/dist/tools-skills-UNKLOB7M.js +29 -0
  330. package/dist/tools-skills-UNKLOB7M.js.map +7 -0
  331. package/dist/update-YC4TYW2Y.js +16 -0
  332. package/dist/update-YC4TYW2Y.js.map +7 -0
  333. package/dist/update-check-UMYTOH7Z.js +18 -0
  334. package/dist/update-check-UMYTOH7Z.js.map +7 -0
  335. package/dist/version-help-DROHZRW6.js +11 -0
  336. package/dist/version-help-DROHZRW6.js.map +7 -0
  337. package/dist/webui-server/connection-handler.d.ts.map +1 -1
  338. package/dist/webui-server/kanban-host-adapter.d.ts +5 -1
  339. package/dist/webui-server/kanban-host-adapter.d.ts.map +1 -1
  340. package/dist/webui-server/listen-helpers.d.ts +18 -0
  341. package/dist/webui-server/listen-helpers.d.ts.map +1 -0
  342. package/dist/webui-server/node-pty-loader.d.ts +6 -0
  343. package/dist/webui-server/node-pty-loader.d.ts.map +1 -0
  344. package/dist/webui-server-G3TISUIY.js +1459 -0
  345. package/dist/webui-server-G3TISUIY.js.map +7 -0
  346. package/dist/webui-server-options.d.ts +189 -0
  347. package/dist/webui-server-options.d.ts.map +1 -0
  348. package/dist/webui-server.d.ts +2 -178
  349. package/dist/webui-server.d.ts.map +1 -1
  350. package/dist/wiring/brain-and-orchestration.d.ts.map +1 -1
  351. package/dist/wiring/codebase-index.d.ts.map +1 -1
  352. package/dist/wiring/command-host-state.d.ts +4 -4
  353. package/dist/wiring/dep-watcher-bridge.d.ts +23 -0
  354. package/dist/wiring/dep-watcher-bridge.d.ts.map +1 -0
  355. package/dist/wiring/dep-watcher.d.ts.map +1 -1
  356. package/dist/wiring/hq-telemetry.d.ts +2 -2
  357. package/dist/wiring/lifecycle-plugins.d.ts +4 -3
  358. package/dist/wiring/lifecycle-plugins.d.ts.map +1 -1
  359. package/dist/wiring/mailbox-bridge-bootstrap.d.ts +1 -1
  360. package/dist/wiring/management-tools.d.ts +15 -0
  361. package/dist/wiring/management-tools.d.ts.map +1 -0
  362. package/dist/wiring/pipeline.d.ts +2 -1
  363. package/dist/wiring/pipeline.d.ts.map +1 -1
  364. package/dist/wiring/plugins.d.ts +1 -1
  365. package/dist/wiring/plugins.d.ts.map +1 -1
  366. package/dist/wiring/provider-runtime-setup.d.ts +14 -1
  367. package/dist/wiring/provider-runtime-setup.d.ts.map +1 -1
  368. package/dist/wiring/provider.d.ts.map +1 -1
  369. package/dist/wiring/runtime-controller-deps.d.ts +1 -1
  370. package/dist/wiring/runtime-controller-deps.d.ts.map +1 -1
  371. package/dist/wiring/sage.d.ts.map +1 -1
  372. package/dist/wiring/session-registry.d.ts +38 -0
  373. package/dist/wiring/session-registry.d.ts.map +1 -0
  374. package/dist/wiring/session.d.ts +7 -5
  375. package/dist/wiring/session.d.ts.map +1 -1
  376. package/dist/wiring/tools.d.ts.map +1 -1
  377. package/package.json +22 -22
  378. package/dist/cli-recovery-prompt.d.ts +0 -19
  379. package/dist/cli-recovery-prompt.d.ts.map +0 -1
  380. package/dist/first-run-auth-gate.d.ts +0 -20
  381. package/dist/first-run-auth-gate.d.ts.map +0 -1
  382. package/dist/pre-launch/indexing-question.d.ts +0 -28
  383. package/dist/pre-launch/indexing-question.d.ts.map +0 -1
@@ -0,0 +1,1290 @@
1
+ import {
2
+ discoverAndMergeProviders
3
+ } from "./chunk-TGDHN4LM.js";
4
+ import {
5
+ mutateConfigProviders,
6
+ normalizeKeys,
7
+ writeKeysBack
8
+ } from "./chunk-PJHET45A.js";
9
+ import {
10
+ activeProfileConfigPath
11
+ } from "./chunk-DPJZQCVP.js";
12
+ import "./chunk-7OCVIDC7.js";
13
+
14
+ // src/subcommands/handlers/modeldiag.ts
15
+ import * as fs from "node:fs/promises";
16
+ import { color as color2 } from "@wrongstack/core/utils";
17
+ import { toErrorMessage as toErrorMessage2 } from "@wrongstack/core/utils";
18
+ import { makeProviderFromConfig, setOAuthTokenPersister } from "@wrongstack/providers";
19
+
20
+ // src/subcommands/handlers/model-smoke-test.ts
21
+ import { ProviderError } from "@wrongstack/core/types";
22
+ import { toErrorMessage } from "@wrongstack/core/utils";
23
+ var DEFAULT_TIMEOUT_MS = 45e3;
24
+ var DEFAULT_MAX_TOKENS = 32;
25
+ function csv(value) {
26
+ if (typeof value !== "string") return void 0;
27
+ const values = value.split(",").map((part) => part.trim()).filter(Boolean);
28
+ return values.length > 0 ? values : void 0;
29
+ }
30
+ function positiveInteger(value, fallback, label) {
31
+ if (value === void 0) return fallback;
32
+ const parsed = typeof value === "string" ? Number(value) : Number.NaN;
33
+ if (!Number.isSafeInteger(parsed) || parsed <= 0) {
34
+ throw new Error(`${label} must be a positive integer.`);
35
+ }
36
+ return parsed;
37
+ }
38
+ function parseModelSmokeOptions(args, flags = {}) {
39
+ const local = /* @__PURE__ */ new Map();
40
+ for (let i = 0; i < args.length; i++) {
41
+ const arg = args[i];
42
+ if (!arg?.startsWith("--")) continue;
43
+ const eq = arg.indexOf("=");
44
+ if (eq >= 0) {
45
+ local.set(arg.slice(2, eq), arg.slice(eq + 1));
46
+ continue;
47
+ }
48
+ const name = arg.slice(2);
49
+ const next = args[i + 1];
50
+ if (next && !next.startsWith("--")) {
51
+ local.set(name, next);
52
+ i++;
53
+ } else {
54
+ local.set(name, true);
55
+ }
56
+ }
57
+ const get = (name) => local.get(name) ?? flags[name];
58
+ const providerFilter = csv(get("providers") ?? get("provider"));
59
+ const modelFilter = csv(get("models") ?? get("model"));
60
+ return {
61
+ allModels: get("all-models") === true || get("all-models") === "true",
62
+ planOnly: get("plan") === true || get("plan") === "true",
63
+ json: get("json") === true || get("json") === "true",
64
+ timeoutMs: positiveInteger(get("timeout"), DEFAULT_TIMEOUT_MS, "--timeout"),
65
+ maxTokens: positiveInteger(get("max-tokens"), DEFAULT_MAX_TOKENS, "--max-tokens"),
66
+ ...providerFilter ? { providerFilter } : {},
67
+ ...modelFilter ? { modelFilter } : {}
68
+ };
69
+ }
70
+ function pushUnique(target, values) {
71
+ const seen = new Set(target);
72
+ for (const value of values) {
73
+ const normalized = value?.trim();
74
+ if (!normalized || seen.has(normalized)) continue;
75
+ seen.add(normalized);
76
+ target.push(normalized);
77
+ }
78
+ }
79
+ async function catalogModelsFor(providerId, providerConfig, registry) {
80
+ const direct = await registry.getProvider(providerId).catch(() => void 0);
81
+ const inherited = direct ?? (providerConfig?.type && providerConfig.type !== providerId ? await registry.getProvider(providerConfig.type).catch(() => void 0) : void 0);
82
+ return inherited?.models ?? [];
83
+ }
84
+ function supportsTextCompletion(model) {
85
+ const outputs = model?.modalities?.output;
86
+ return !outputs?.length || outputs.includes("text");
87
+ }
88
+ async function buildModelSmokeTargets(config, registry, options) {
89
+ const providerIds = Object.keys(config.providers ?? {});
90
+ if (config.provider && !providerIds.includes(config.provider)) providerIds.push(config.provider);
91
+ const providerFilter = options.providerFilter ? new Set(options.providerFilter.map((id) => id.toLowerCase())) : void 0;
92
+ const modelFilter = options.modelFilter ? new Set(options.modelFilter) : void 0;
93
+ const targets = [];
94
+ for (const providerId of providerIds) {
95
+ if (providerFilter && !providerFilter.has(providerId.toLowerCase())) continue;
96
+ const saved = config.providers?.[providerId];
97
+ const catalogModels = await catalogModelsFor(providerId, saved, registry);
98
+ const catalogById = new Map(catalogModels.map((model) => [model.id, model]));
99
+ const textCatalogModels = catalogModels.filter(supportsTextCompletion);
100
+ const candidates = [];
101
+ if (options.allModels) {
102
+ pushUnique(candidates, saved?.models ?? []);
103
+ pushUnique(candidates, Object.keys(saved?.customModels ?? {}));
104
+ pushUnique(
105
+ candidates,
106
+ textCatalogModels.map((model) => model.id)
107
+ );
108
+ if (providerId === config.provider) pushUnique(candidates, [config.model]);
109
+ pushUnique(candidates, [saved?.model]);
110
+ } else {
111
+ const representative = (providerId === config.provider ? config.model : void 0) ?? saved?.model ?? saved?.models?.find(Boolean) ?? Object.keys(saved?.customModels ?? {})[0] ?? await registry.suggestModel(providerId).catch(() => void 0) ?? textCatalogModels[0]?.id;
112
+ pushUnique(candidates, [representative]);
113
+ }
114
+ for (const modelId of candidates) {
115
+ if (modelFilter && !modelFilter.has(modelId)) continue;
116
+ if (!supportsTextCompletion(catalogById.get(modelId))) continue;
117
+ targets.push({ providerId, modelId });
118
+ }
119
+ }
120
+ return targets;
121
+ }
122
+ function classifyFailure(err) {
123
+ if (err instanceof ProviderError || ProviderError.isProviderError(err)) {
124
+ const providerError = err;
125
+ return {
126
+ error: providerError.describe(),
127
+ errorKind: providerError.kind,
128
+ httpStatus: providerError.status
129
+ };
130
+ }
131
+ const isTimeout = err instanceof Error && (err.name === "TimeoutError" || err.name === "AbortError") || /timed?\s*out/i.test(toErrorMessage(err));
132
+ return {
133
+ error: toErrorMessage(err),
134
+ errorKind: isTimeout ? "timeout" : "unknown"
135
+ };
136
+ }
137
+ async function runModelSmokeTests(params) {
138
+ const results = [];
139
+ let providerId;
140
+ let provider;
141
+ let providerError;
142
+ for (let index = 0; index < params.targets.length; index++) {
143
+ const target = params.targets[index];
144
+ params.onTargetStart?.(target, index, params.targets.length);
145
+ const started = Date.now();
146
+ if (target.providerId !== providerId) {
147
+ providerId = target.providerId;
148
+ provider = void 0;
149
+ providerError = void 0;
150
+ try {
151
+ provider = await params.createProvider(target.providerId);
152
+ } catch (err) {
153
+ providerError = err;
154
+ }
155
+ }
156
+ if (!provider) {
157
+ const failure = classifyFailure(providerError ?? new Error("Provider could not be created."));
158
+ const result = {
159
+ providerId: target.providerId,
160
+ modelId: target.modelId,
161
+ status: "failed",
162
+ latencyMs: Date.now() - started,
163
+ ...failure
164
+ };
165
+ results.push(result);
166
+ params.onTargetComplete?.(result, index, params.targets.length);
167
+ continue;
168
+ }
169
+ try {
170
+ const response = await provider.complete(
171
+ {
172
+ model: target.modelId,
173
+ messages: [
174
+ {
175
+ role: "user",
176
+ content: [{ type: "text", text: "Reply with exactly: OK" }]
177
+ }
178
+ ],
179
+ maxTokens: params.options.maxTokens
180
+ },
181
+ { signal: AbortSignal.timeout(params.options.timeoutMs) }
182
+ );
183
+ const result = {
184
+ providerId: target.providerId,
185
+ modelId: target.modelId,
186
+ status: "passed",
187
+ latencyMs: Date.now() - started,
188
+ stopReason: response.stopReason,
189
+ usage: response.usage
190
+ };
191
+ results.push(result);
192
+ params.onTargetComplete?.(result, index, params.targets.length);
193
+ } catch (err) {
194
+ const result = {
195
+ providerId: target.providerId,
196
+ modelId: target.modelId,
197
+ status: "failed",
198
+ latencyMs: Date.now() - started,
199
+ ...classifyFailure(err)
200
+ };
201
+ results.push(result);
202
+ params.onTargetComplete?.(result, index, params.targets.length);
203
+ }
204
+ }
205
+ return results;
206
+ }
207
+
208
+ // src/subcommands/handlers/modeldiag-profiles.ts
209
+ import { color } from "@wrongstack/core/utils";
210
+ var MODEL_PROFILES = [
211
+ {
212
+ provider: "anthropic",
213
+ pattern: /claude-opus/i,
214
+ family: "Claude Opus",
215
+ strengths: ["reasoning", "planning"],
216
+ bestFor: ["planning", "security", "debugging"],
217
+ costTier: "premium",
218
+ speedTier: "slow"
219
+ },
220
+ {
221
+ provider: "anthropic",
222
+ pattern: /claude-haiku/i,
223
+ family: "Claude Haiku",
224
+ strengths: ["speed"],
225
+ bestFor: ["lightweight", "docs"],
226
+ avoidFor: ["planning"],
227
+ costTier: "budget",
228
+ speedTier: "fast"
229
+ },
230
+ {
231
+ provider: "openai",
232
+ pattern: /gpt-5|o3|o4/i,
233
+ family: "GPT-5/o3/o4",
234
+ strengths: ["reasoning", "coding"],
235
+ bestFor: ["planning", "coding", "debugging"],
236
+ costTier: "premium",
237
+ speedTier: "normal"
238
+ },
239
+ {
240
+ provider: "openai",
241
+ pattern: /gpt-4/i,
242
+ family: "GPT-4",
243
+ strengths: ["coding"],
244
+ bestFor: ["coding", "docs"],
245
+ costTier: "standard",
246
+ speedTier: "fast"
247
+ },
248
+ {
249
+ provider: "openai",
250
+ pattern: /gpt-4o-mini/i,
251
+ family: "GPT-4o Mini",
252
+ strengths: ["speed"],
253
+ bestFor: ["lightweight", "docs"],
254
+ avoidFor: ["planning"],
255
+ costTier: "budget",
256
+ speedTier: "fast"
257
+ },
258
+ {
259
+ provider: "google",
260
+ pattern: /gemini-(?:2\.5|3)/i,
261
+ family: "Gemini 2.5/3",
262
+ strengths: ["context", "coding"],
263
+ bestFor: ["coding", "data"],
264
+ costTier: "standard",
265
+ speedTier: "normal"
266
+ },
267
+ {
268
+ provider: "google",
269
+ pattern: /gemini.*flash/i,
270
+ family: "Gemini Flash",
271
+ strengths: ["speed"],
272
+ bestFor: ["lightweight", "docs"],
273
+ avoidFor: ["planning"],
274
+ costTier: "budget",
275
+ speedTier: "fast"
276
+ },
277
+ {
278
+ provider: "deepseek",
279
+ pattern: /deepseek/i,
280
+ family: "DeepSeek",
281
+ strengths: ["coding", "cost-effective"],
282
+ bestFor: ["coding", "general"],
283
+ costTier: "standard",
284
+ speedTier: "normal"
285
+ }
286
+ ];
287
+ function fmtTokens(n) {
288
+ if (n >= 1e6) return `${(n / 1e6).toFixed(1)}M`;
289
+ if (n >= 1e3) return `${(n / 1e3).toFixed(1)}k`;
290
+ return String(n);
291
+ }
292
+ function fmtMs(ms) {
293
+ if (ms >= 1e3) return `${(ms / 1e3).toFixed(1)}s`;
294
+ return `${ms}ms`;
295
+ }
296
+ function fmtPrice(usdPer1M) {
297
+ if (usdPer1M === void 0) return color.dim("?");
298
+ if (usdPer1M >= 10) return `$${usdPer1M.toFixed(1)}`;
299
+ return `$${usdPer1M.toFixed(2)}`;
300
+ }
301
+ function checkMark(ok) {
302
+ return ok ? color.green("\u2713") : color.red("\u2717");
303
+ }
304
+ function costLabel(tier) {
305
+ switch (tier) {
306
+ case "premium":
307
+ return color.red("$$$");
308
+ case "standard":
309
+ return color.amber("$$");
310
+ case "budget":
311
+ return color.green("$");
312
+ default:
313
+ return color.dim("?");
314
+ }
315
+ }
316
+ function speedLabel(tier) {
317
+ switch (tier) {
318
+ case "fast":
319
+ return color.green("\u26A1");
320
+ case "normal":
321
+ return color.amber("\u2192");
322
+ case "slow":
323
+ return color.red("\u{1F422}");
324
+ default:
325
+ return color.dim("?");
326
+ }
327
+ }
328
+ function scoreBar(score, max) {
329
+ const pct = Math.min(1, Math.max(0, score / max));
330
+ const filled = Math.round(pct * 10);
331
+ const bar = color.green("\u2588".repeat(filled)) + color.dim("\u2591".repeat(10 - filled));
332
+ return `${bar} ${score}/${max}`;
333
+ }
334
+ var ROLE_CATEGORY = {
335
+ "security-scanner": "security",
336
+ "security-reviewer": "security",
337
+ "bug-hunter": "debugging",
338
+ debugger: "debugging",
339
+ tracer: "debugging",
340
+ planner: "planning",
341
+ architect: "planning",
342
+ "refactor-planner": "planning",
343
+ verifier: "testing",
344
+ test: "testing",
345
+ e2e: "testing",
346
+ document: "docs",
347
+ simplifier: "docs",
348
+ "code-reviewer": "review",
349
+ reviewer: "review",
350
+ critic: "review",
351
+ executor: "coding",
352
+ refactor: "refactoring",
353
+ migration: "coding",
354
+ frontend: "frontend",
355
+ backend: "backend",
356
+ api: "backend",
357
+ auth: "backend",
358
+ designer: "frontend",
359
+ analyst: "data",
360
+ data: "data",
361
+ database: "data",
362
+ explore: "planning",
363
+ search: "planning",
364
+ researcher: "planning"
365
+ };
366
+ function findProfile(pid, mid) {
367
+ for (const p of MODEL_PROFILES) {
368
+ if (p.provider === pid && p.pattern.test(mid)) return p;
369
+ }
370
+ return void 0;
371
+ }
372
+ function scoreModel(pid, mid, category, ctxWindow) {
373
+ const profile = findProfile(pid, mid);
374
+ let score = 50;
375
+ if (profile) {
376
+ if (profile.bestFor.includes(category)) score += 35;
377
+ if (profile.avoidFor?.includes(category)) score -= 50;
378
+ if (category === "planning" && profile.costTier === "premium") score += 15;
379
+ if (profile.speedTier === "slow" && category === "planning") score += 10;
380
+ if (profile.costTier === "budget" && category !== "planning" && category !== "security")
381
+ score += 10;
382
+ }
383
+ if (ctxWindow > 2e5) score += 10;
384
+ else if (ctxWindow > 1e5) score += 5;
385
+ else if (ctxWindow > 32e3) score += 2;
386
+ return { score, profile };
387
+ }
388
+ function rankModels(providers, hasKey, category, limit) {
389
+ const candidates = [];
390
+ for (const prov of providers) {
391
+ if (!hasKey(prov.id)) continue;
392
+ for (const m of prov.models ?? []) {
393
+ const ctxWindow = m.capabilities?.contextWindow ?? 0;
394
+ const { score, profile } = scoreModel(prov.id, m.id, category, ctxWindow);
395
+ if (score > 0) {
396
+ candidates.push({
397
+ provider: prov.id,
398
+ model: m.id,
399
+ profile,
400
+ score,
401
+ ctxWindow,
402
+ maxOutput: m.capabilities?.maxOutputTokens ?? 0,
403
+ inputPrice: m.pricing?.input,
404
+ outputPrice: m.pricing?.output
405
+ });
406
+ }
407
+ }
408
+ }
409
+ candidates.sort((a, b) => b.score - a.score);
410
+ return candidates.slice(0, limit);
411
+ }
412
+ var EVAL_TASKS = {
413
+ coding: {
414
+ label: "Code Generation",
415
+ prompt: "Write a TypeScript function parseCSV(input: string): { headers: string[]; rows: string[][] } that handles quoted fields, escaped quotes, and empty lines. Return an error string on malformed input. Keep under 40 lines."
416
+ },
417
+ planning: {
418
+ label: "Architecture Planning",
419
+ prompt: "Design the folder structure and key interfaces for a monorepo CLI tool with slash commands, model routing, subagent spawning, and config persistence. List packages, their responsibilities, and the 5 most important TypeScript interfaces."
420
+ },
421
+ security: {
422
+ label: "Vulnerability Detection",
423
+ prompt: 'Review this code for security issues:\n```ts\napp.get("/api/user", (req, res) => {\n const id = req.query.id;\n const user = db.query("SELECT * FROM users WHERE id = " + id);\n res.json(user);\n});\n\napp.post("/api/run", (req, res) => {\n const { cmd } = req.body;\n exec("echo " + cmd, (err, stdout) => res.send(stdout));\n});\n```\nList every vulnerability, its severity (critical/high/medium), and the exact fix.'
424
+ },
425
+ debugging: {
426
+ label: "Bug Diagnosis",
427
+ prompt: 'This async function has 2 bugs. Find and fix both:\n```ts\nasync function processBatch(items: string[]) {\n const results = [];\n for (const item of items) {\n const result = await fetch("https://api.example.com/" + item);\n results.push(result);\n }\n return results.map(r => r.json());\n}\n```\nExplain what each bug is, why it fails, and write the corrected version.'
428
+ },
429
+ testing: {
430
+ label: "Test Authoring",
431
+ prompt: 'Write vitest test cases for this deepMerge function:\n```ts\nfunction deepMerge(base: Record<string, unknown>, overrides: Record<string, unknown>): Record<string, unknown> {\n const merged = { ...base };\n for (const [key, val] of Object.entries(overrides)) {\n if (val === null) { delete merged[key]; continue; }\n if (typeof val === "object" && !Array.isArray(val) && typeof merged[key] === "object" && !Array.isArray(merged[key])) {\n merged[key] = deepMerge(merged[key] as Record<string, unknown>, val as Record<string, unknown>);\n } else { merged[key] = val; }\n }\n return merged;\n}\n```\nCover: happy path, edge cases, and error conditions.'
432
+ },
433
+ docs: {
434
+ label: "Documentation",
435
+ prompt: "Write TSDoc comments for this RateLimiter interface. Include @param, @returns, @throws, and @example for each method:\n```ts\ninterface RateLimiter {\n tryAcquire(key: string, maxPerWindow: number, windowMs: number): Promise<boolean>;\n getRemaining(key: string): Promise<number>;\n reset(key: string): Promise<void>;\n}\n```"
436
+ },
437
+ review: {
438
+ label: "Code Review",
439
+ prompt: 'Review this PR change:\n```diff\n async function loadConfig(path: string) {\n- const raw = await fs.readFile(path, "utf8");\n- return JSON.parse(raw);\n+ const raw = await fs.readFile(path);\n+ const config = JSON.parse(raw);\n+ process.env.API_KEY = config.apiKey;\n+ return config;\n }\n```\nList issues by severity (blocking / should-fix / nit) and explain your reasoning.'
440
+ },
441
+ refactoring: {
442
+ label: "Refactoring",
443
+ prompt: 'Refactor this nested condition into a cleaner pattern:\n```ts\nfunction getDiscount(user: { type: string; years: number; coupon?: string }): number {\n if (user.type === "premium") {\n if (user.years > 5) {\n if (user.coupon === "BLACKFRIDAY") return 0.5;\n return 0.3;\n }\n return 0.2;\n }\n if (user.type === "standard") {\n if (user.years > 3) return 0.15;\n return 0.1;\n }\n return 0;\n}\n```\nShow your refactored code and explain why your approach is cleaner.'
444
+ }
445
+ };
446
+ var EVAL_CATEGORIES = Object.keys(EVAL_TASKS);
447
+ function roleCat(role) {
448
+ return ROLE_CATEGORY[role] ?? "general";
449
+ }
450
+
451
+ // src/subcommands/handlers/modeldiag.ts
452
+ function createProviderForId(providerId, cfg) {
453
+ const savedCfg = cfg.providers?.[providerId];
454
+ const cfgWithType = Object.assign(
455
+ { type: providerId },
456
+ savedCfg ?? { apiKey: cfg.apiKey, baseUrl: cfg.baseUrl }
457
+ );
458
+ try {
459
+ return makeProviderFromConfig(providerId, cfgWithType);
460
+ } catch {
461
+ return void 0;
462
+ }
463
+ }
464
+ async function rankResponses(provider, leaderModel, taskPrompt, responses) {
465
+ const labelToIdx = /* @__PURE__ */ new Map();
466
+ const responseBlock = responses.map((r, i) => {
467
+ const label = String.fromCharCode(65 + i);
468
+ labelToIdx.set(label, i);
469
+ return `=== Response ${label} ===
470
+ ${r.text.slice(0, 800)}`;
471
+ }).join("\n\n");
472
+ const rankingPrompt = `Rank these responses from BEST (1) to WORST.
473
+
474
+ TASK:
475
+ ${taskPrompt.slice(0, 600)}
476
+
477
+ RESPONSES:
478
+ ${responseBlock}
479
+
480
+ Output ONLY a ranked list, one per line:
481
+ 1. Response X \u2014 brief reason
482
+ 2. Response Y \u2014 brief reason`;
483
+ try {
484
+ const resp = await provider.complete(
485
+ {
486
+ model: leaderModel,
487
+ system: [
488
+ {
489
+ type: "text",
490
+ text: "You are an expert evaluator. Rank responses concisely. Output ONLY the ranked list."
491
+ }
492
+ ],
493
+ messages: [{ role: "user", content: [{ type: "text", text: rankingPrompt }] }],
494
+ maxTokens: 400
495
+ },
496
+ { signal: AbortSignal.timeout(3e4) }
497
+ );
498
+ const text = resp.content[0] && "text" in resp.content[0] ? resp.content[0].text : "";
499
+ const rankings = [];
500
+ for (const line of text.split("\n")) {
501
+ const m = line.match(/^\s*(\d+)[.)]\s*Response\s+([A-Z])/i);
502
+ if (m) {
503
+ const label = m[2]?.toUpperCase();
504
+ const idx = label !== void 0 ? labelToIdx.get(label) : void 0;
505
+ if (idx !== void 0 && !rankings.includes(idx)) {
506
+ rankings.push(idx);
507
+ }
508
+ }
509
+ }
510
+ return rankings.length > 0 ? rankings : responses.map((_, i) => i);
511
+ } catch {
512
+ return responses.map((_, i) => i);
513
+ }
514
+ }
515
+ async function readProviders(cachePath) {
516
+ if (!cachePath) {
517
+ return `${color2.red("Models cache not available")}.`;
518
+ }
519
+ try {
520
+ const raw = await fs.readFile(cachePath, "utf8");
521
+ const parsed = JSON.parse(raw);
522
+ const payload = parsed.payload ?? parsed;
523
+ return Object.entries(payload).map(([id, p]) => ({
524
+ id: p.id ?? id,
525
+ name: p.name ?? id,
526
+ family: p.npm ?? id,
527
+ models: Object.values(p.models ?? {}).map(
528
+ (m) => ({
529
+ id: m.id,
530
+ name: m.name,
531
+ capabilities: {
532
+ contextWindow: m.limit?.context,
533
+ maxOutputTokens: m.limit?.output
534
+ },
535
+ pricing: m.cost
536
+ })
537
+ )
538
+ }));
539
+ } catch {
540
+ return `${color2.amber("Models cache not available")}. Run wstack sync-models.`;
541
+ }
542
+ }
543
+ function checkHasKey(pid, config) {
544
+ if (pid === config.provider && config.provider) return true;
545
+ const pc = config.providers?.[pid];
546
+ if (!pc) return false;
547
+ if (typeof pc.apiKey === "string" && pc.apiKey.length > 0) return true;
548
+ if (Array.isArray(pc.apiKeys) && pc.apiKeys.some((k) => k?.apiKey)) return true;
549
+ return false;
550
+ }
551
+ var modeldiagCmd = async (args, deps) => {
552
+ const sub = args[0]?.toLowerCase() || "full";
553
+ const cacheResult = await readProviders(deps.paths.modelsCache);
554
+ if (typeof cacheResult === "string") {
555
+ deps.renderer.write(`${cacheResult}
556
+ `);
557
+ return cacheResult.includes(color2.red("")) ? 1 : 0;
558
+ }
559
+ const providers = cacheResult;
560
+ const config = deps.config;
561
+ const modelMatrix = config.modelMatrix ?? {};
562
+ function hasKey(pid) {
563
+ return checkHasKey(pid, config);
564
+ }
565
+ function writeLine(line = "") {
566
+ deps.renderer.write(`${line}
567
+ `);
568
+ }
569
+ if (sub === "keys") {
570
+ writeLine(`${color2.bold("API Key Status")}`);
571
+ writeLine();
572
+ for (const prov of providers) {
573
+ const k = hasKey(prov.id);
574
+ writeLine(` ${checkMark(k)} ${color2.bold(prov.id.padEnd(18))} ${color2.dim(prov.name)}`);
575
+ }
576
+ writeLine();
577
+ writeLine(`${color2.dim(`Leader: ${config.provider}/${config.model}`)}`);
578
+ return 0;
579
+ }
580
+ if (sub === "caps") {
581
+ writeLine(`${color2.bold("Model Capabilities")} ${color2.dim("\u2014 matched to known profiles")}`);
582
+ writeLine();
583
+ for (const prov of providers) {
584
+ if (!hasKey(prov.id)) continue;
585
+ writeLine(` ${color2.bold(prov.id)} ${color2.dim(`(${prov.name})`)}`);
586
+ const tiers = {
587
+ premium: [],
588
+ standard: [],
589
+ budget: [],
590
+ unknown: []
591
+ };
592
+ for (const m of prov.models ?? []) {
593
+ const profile = findProfile(prov.id, m.id);
594
+ tiers[profile?.costTier ?? "unknown"]?.push(m);
595
+ }
596
+ for (const tier of ["premium", "standard", "budget", "unknown"]) {
597
+ const tierModels = tiers[tier];
598
+ if (tierModels.length === 0) continue;
599
+ const label = tier === "unknown" ? color2.dim("unmatched") : `${costLabel(tier)} ${tier}`;
600
+ writeLine(` ${label}`);
601
+ for (const m of tierModels) {
602
+ const cap = m.capabilities;
603
+ const ctx = cap?.contextWindow ?? 0;
604
+ const maxOut = cap?.maxOutputTokens ?? 0;
605
+ const profile = findProfile(prov.id, m.id);
606
+ const family = profile ? `${speedLabel(profile.speedTier)} ${color2.green(profile.family)}` : color2.dim("no profile match");
607
+ const pricing = m.pricing ? `${color2.dim("in")}${fmtPrice(m.pricing.input)} ${color2.dim("out")}${fmtPrice(m.pricing.output)}` : color2.dim("pricing ?");
608
+ writeLine(
609
+ ` ${color2.cyan(m.id.padEnd(34))}${ctx > 0 ? `ctx ${fmtTokens(ctx).padEnd(6)}` : color2.dim("ctx ? ")}${maxOut > 0 ? `out ${fmtTokens(maxOut).padEnd(6)}` : " "}${family} ${pricing}`
610
+ );
611
+ }
612
+ }
613
+ writeLine();
614
+ }
615
+ writeLine(
616
+ color2.dim(
617
+ "Prices in USD per 1M tokens (input/output). ctx = context window, out = max output."
618
+ )
619
+ );
620
+ return 0;
621
+ }
622
+ async function renderSuggest() {
623
+ writeLine();
624
+ writeLine(
625
+ `${color2.bold("Agent \u2192 Model Suggestions")} ${color2.amber("(heuristic \u2014 untested)")}`
626
+ );
627
+ writeLine(
628
+ color2.dim(
629
+ 'These are profile-based best guesses. Test them with wstack modeldiag bench <role> "<prompt>".'
630
+ )
631
+ );
632
+ writeLine();
633
+ const keyedProviders = providers.filter((p) => hasKey(p.id));
634
+ if (keyedProviders.length === 0) {
635
+ writeLine(
636
+ ` ${color2.amber("No providers have API keys configured. Add keys with wstack auth.")}`
637
+ );
638
+ } else {
639
+ const roles = [
640
+ "security-scanner",
641
+ "bug-hunter",
642
+ "planner",
643
+ "architect",
644
+ "refactor-planner",
645
+ "verifier",
646
+ "test",
647
+ "document",
648
+ "reviewer",
649
+ "code-reviewer",
650
+ "executor",
651
+ "debugger"
652
+ ];
653
+ for (const role of roles) {
654
+ if (modelMatrix[role]) {
655
+ const entry = modelMatrix[role];
656
+ const p = entry.provider ?? config.provider;
657
+ writeLine(
658
+ ` ${color2.dim(role.padEnd(20))} \u2192 ${color2.cyan(`${p}/${entry.model}`)} ${color2.dim("(user-configured)")}`
659
+ );
660
+ continue;
661
+ }
662
+ const cat = roleCat(role);
663
+ const ranked = rankModels(providers, hasKey, cat, 3);
664
+ if (ranked.length === 0) {
665
+ writeLine(` ${color2.dim(role.padEnd(20))} \u2192 ${color2.dim("no candidates")}`);
666
+ continue;
667
+ }
668
+ const best = ranked[0];
669
+ const family = best.profile ? ` ${color2.dim(`(${best.profile.family})`)}` : "";
670
+ const bar = scoreBar(best.score, 110);
671
+ writeLine(
672
+ ` ${color2.amber(role.padEnd(20))} \u2192 ${color2.cyan(`${best.provider}/${best.model}`)}${family}`
673
+ );
674
+ writeLine(` ${" ".repeat(22)} ${bar} ${color2.dim(cat)}`);
675
+ if (ranked.length > 1 && (ranked[1]?.score ?? Number.NEGATIVE_INFINITY) >= best.score - 15) {
676
+ for (const alt of ranked.slice(1)) {
677
+ const af = alt.profile ? ` (${alt.profile.family})` : "";
678
+ writeLine(
679
+ ` ${" ".repeat(22)} ${color2.dim(`${alt.provider}/${alt.model}${af} score ${alt.score}`)}`
680
+ );
681
+ }
682
+ }
683
+ }
684
+ writeLine();
685
+ writeLine(
686
+ ` ${color2.bold("leader".padEnd(20))} \u2192 ${color2.cyan(`${config.provider}/${config.model}`)}`
687
+ );
688
+ }
689
+ }
690
+ if (sub === "suggest") {
691
+ await renderSuggest();
692
+ writeLine();
693
+ writeLine(color2.dim("Pin a suggestion: wstack setmodel set <role> <provider>/<model>"));
694
+ writeLine(color2.dim('Test candidates: wstack modeldiag bench <role> "<test prompt>"'));
695
+ return 0;
696
+ }
697
+ if (sub === "test") {
698
+ if (args.slice(1).includes("--help") || deps.flags?.["help"] === true) {
699
+ writeLine(`${color2.bold("Usage:")} wstack modeldiag test [options]`);
700
+ writeLine();
701
+ writeLine(" (no flags) Probe one representative model per configured provider");
702
+ writeLine(" --all-models Probe every catalog-visible model sequentially");
703
+ writeLine(" --plan Show targets without making model calls");
704
+ writeLine(" --provider=<id,...> Restrict provider ids");
705
+ writeLine(" --model=<id,...> Restrict model ids");
706
+ writeLine(" --timeout=<ms> Per-model timeout (default 45000)");
707
+ writeLine(" --max-tokens=<n> Output cap for the tiny probe (default 32)");
708
+ writeLine(" --json Emit machine-readable output");
709
+ writeLine(" --yes Confirm a run larger than 50 requests");
710
+ return 0;
711
+ }
712
+ let smokeOptions;
713
+ try {
714
+ smokeOptions = parseModelSmokeOptions(args.slice(1), deps.flags);
715
+ } catch (err) {
716
+ writeLine(`${color2.red("Invalid smoke-test options:")} ${toErrorMessage2(err)}`);
717
+ return 2;
718
+ }
719
+ if ("mergeOverlay" in deps.modelsRegistry) {
720
+ await discoverAndMergeProviders({
721
+ config,
722
+ registry: deps.modelsRegistry,
723
+ cacheDir: deps.paths.cacheDir
724
+ });
725
+ }
726
+ const targets = await buildModelSmokeTargets(config, deps.modelsRegistry, smokeOptions);
727
+ const byProvider = /* @__PURE__ */ new Map();
728
+ for (const target of targets) {
729
+ byProvider.set(target.providerId, (byProvider.get(target.providerId) ?? 0) + 1);
730
+ }
731
+ if (smokeOptions.planOnly) {
732
+ const plan = {
733
+ mode: smokeOptions.allModels ? "all-models" : "representative",
734
+ targetCount: targets.length,
735
+ providers: Object.fromEntries(byProvider),
736
+ targets
737
+ };
738
+ if (smokeOptions.json) {
739
+ writeLine(JSON.stringify(plan, null, 2));
740
+ } else {
741
+ writeLine(`${color2.bold("Provider/Model Smoke Test Plan")}`);
742
+ writeLine();
743
+ for (const [providerId, count] of byProvider) {
744
+ writeLine(` ${color2.cyan(providerId.padEnd(24))} ${count} model(s)`);
745
+ }
746
+ writeLine();
747
+ writeLine(
748
+ color2.dim(
749
+ `${targets.length} request(s) would run sequentially. Remove --plan to execute.`
750
+ )
751
+ );
752
+ }
753
+ return targets.length > 0 ? 0 : 2;
754
+ }
755
+ if (targets.length === 0) {
756
+ const message = "No provider/model targets matched. Check the active profile or remove filters.";
757
+ if (smokeOptions.json) {
758
+ writeLine(JSON.stringify({ results: [], summary: { passed: 0, failed: 0 }, error: message }));
759
+ } else {
760
+ writeLine(color2.amber(message));
761
+ }
762
+ return 2;
763
+ }
764
+ const confirmed = deps.flags?.["yes"] === true || deps.flags?.["yes"] === "true" || args.slice(1).includes("--yes");
765
+ if (targets.length > 50 && !confirmed) {
766
+ const message = `${targets.length} live requests are planned. Review with --plan, then add --yes to run them.`;
767
+ if (smokeOptions.json) {
768
+ writeLine(JSON.stringify({ error: message, targetCount: targets.length }));
769
+ } else {
770
+ writeLine(color2.amber(message));
771
+ }
772
+ return 2;
773
+ }
774
+ if (!smokeOptions.json) {
775
+ writeLine(`${color2.bold("Live Provider/Model Smoke Test")}`);
776
+ writeLine(
777
+ color2.dim(
778
+ `${targets.length} request(s), sequential, ${smokeOptions.timeoutMs}ms timeout, max ${smokeOptions.maxTokens} output tokens.`
779
+ )
780
+ );
781
+ writeLine();
782
+ }
783
+ const resultLines = (result, index, total) => {
784
+ if (smokeOptions.json) return;
785
+ const label = `[${String(index + 1).padStart(String(total).length)}/${total}]`;
786
+ const target = `${result.providerId}/${result.modelId}`;
787
+ if (result.status === "passed") {
788
+ writeLine(
789
+ ` ${color2.green("\u2713")} ${color2.dim(label)} ${color2.cyan(target)} ${color2.dim(
790
+ `${fmtMs(result.latencyMs)} \xB7 in${result.usage.input}/out${result.usage.output} \xB7 ${result.stopReason}`
791
+ )}`
792
+ );
793
+ } else {
794
+ const status = result.httpStatus ? `HTTP ${result.httpStatus} \xB7 ` : "";
795
+ writeLine(
796
+ ` ${color2.red("\u2717")} ${color2.dim(label)} ${color2.red(target)} ${color2.dim(
797
+ `${fmtMs(result.latencyMs)} \xB7 ${status}${result.errorKind}`
798
+ )}`
799
+ );
800
+ writeLine(` ${color2.red(result.error.slice(0, 240))}`);
801
+ }
802
+ };
803
+ let oauthWriteChain = Promise.resolve();
804
+ let oauthWriteScheduled = false;
805
+ const profilePath = activeProfileConfigPath(deps.paths, config);
806
+ setOAuthTokenPersister((providerId, credentials) => {
807
+ oauthWriteScheduled = true;
808
+ oauthWriteChain = oauthWriteChain.then(
809
+ () => mutateConfigProviders(profilePath, deps.vault, (all) => {
810
+ const providerConfig = all[providerId];
811
+ if (!providerConfig) return;
812
+ const keys = normalizeKeys(providerConfig);
813
+ const active = providerConfig.activeKey ? keys.find((key) => key.label === providerConfig.activeKey) : keys[0];
814
+ if (!active) return;
815
+ active.apiKey = credentials.accessToken;
816
+ active.refreshToken = credentials.refreshToken;
817
+ active.expiresAt = new Date(credentials.expiresAt).toISOString();
818
+ if (credentials.accountId) active.accountId = credentials.accountId;
819
+ writeKeysBack(providerConfig, keys);
820
+ })
821
+ );
822
+ });
823
+ let results;
824
+ try {
825
+ results = await runModelSmokeTests({
826
+ targets,
827
+ options: smokeOptions,
828
+ createProvider: async (providerId) => {
829
+ const saved = config.providers?.[providerId];
830
+ const resolved = await deps.modelsRegistry.getProvider(providerId).catch(() => void 0) ?? (saved?.type && saved.type !== providerId ? await deps.modelsRegistry.getProvider(saved.type).catch(() => void 0) : void 0);
831
+ const providerConfig = {
832
+ ...providerId === config.provider ? {
833
+ ...config.apiKey ? { apiKey: config.apiKey } : {},
834
+ ...config.baseUrl ? { baseUrl: config.baseUrl } : {}
835
+ } : {},
836
+ ...saved,
837
+ type: providerId,
838
+ ...saved?.family ?? resolved?.family ? { family: saved?.family ?? resolved?.family } : {},
839
+ ...saved?.baseUrl ?? resolved?.apiBase ? { baseUrl: saved?.baseUrl ?? resolved?.apiBase } : {},
840
+ ...saved?.envVars ?? resolved?.envVars ? { envVars: saved?.envVars ?? resolved?.envVars } : {}
841
+ };
842
+ return makeProviderFromConfig(providerId, providerConfig);
843
+ },
844
+ onTargetComplete: resultLines
845
+ });
846
+ } finally {
847
+ setOAuthTokenPersister(void 0);
848
+ }
849
+ let oauthPersistenceError;
850
+ if (oauthWriteScheduled) {
851
+ try {
852
+ await oauthWriteChain;
853
+ } catch (err) {
854
+ oauthPersistenceError = toErrorMessage2(err);
855
+ }
856
+ }
857
+ const passed = results.filter((result) => result.status === "passed").length;
858
+ const failed = results.length - passed;
859
+ const summary = { passed, failed, total: results.length };
860
+ if (smokeOptions.json) {
861
+ writeLine(
862
+ JSON.stringify(
863
+ {
864
+ results,
865
+ summary,
866
+ ...oauthPersistenceError ? { warning: `OAuth token refresh worked in-memory but could not be saved: ${oauthPersistenceError}` } : {}
867
+ },
868
+ null,
869
+ 2
870
+ )
871
+ );
872
+ } else {
873
+ writeLine();
874
+ writeLine(
875
+ `${color2.bold("Summary:")} ${color2.green(`${passed} passed`)} \xB7 ${failed > 0 ? color2.red(`${failed} failed`) : color2.dim("0 failed")}`
876
+ );
877
+ if (!smokeOptions.allModels) {
878
+ writeLine(
879
+ color2.dim("Use --all-models to test every catalog-visible model sequentially.")
880
+ );
881
+ }
882
+ if (oauthPersistenceError) {
883
+ writeLine(
884
+ color2.amber(
885
+ `OAuth token refresh worked in-memory but could not be saved: ${oauthPersistenceError}`
886
+ )
887
+ );
888
+ }
889
+ }
890
+ return failed === 0 ? 0 : 1;
891
+ }
892
+ if (sub === "bench") {
893
+ const benchArgs = args.slice(1);
894
+ if (benchArgs.length < 2) {
895
+ writeLine(
896
+ `${color2.amber("Usage:")} wstack modeldiag bench <role> "<test prompt>" [--providers=p1,p2]`
897
+ );
898
+ writeLine();
899
+ writeLine(
900
+ color2.dim(
901
+ 'Example: wstack modeldiag bench verify "Write a function that checks if a string is a palindrome"'
902
+ )
903
+ );
904
+ writeLine(
905
+ color2.dim(
906
+ "Tests the top 5 candidate models for the role with your prompt and reports results."
907
+ )
908
+ );
909
+ writeLine(color2.dim("Add --providers=anthropic,google to test across multiple providers."));
910
+ return 0;
911
+ }
912
+ const providersEqIdx = benchArgs.findIndex((a) => a.startsWith("--providers="));
913
+ let providerFilter;
914
+ if (providersEqIdx >= 0) {
915
+ const rawFilter = benchArgs[providersEqIdx]?.replace("--providers=", "").split(",");
916
+ if (rawFilter) {
917
+ providerFilter = rawFilter.map((s) => s.trim()).filter(Boolean);
918
+ benchArgs.splice(providersEqIdx, 1);
919
+ }
920
+ } else {
921
+ const rawFilter = deps.flags?.["providers"] ?? deps.flags?.["provider"];
922
+ if (typeof rawFilter === "string") {
923
+ providerFilter = rawFilter.split(",").map((s) => s.trim()).filter(Boolean);
924
+ }
925
+ }
926
+ const benchRole = benchArgs[0];
927
+ if (!benchRole) {
928
+ writeLine(
929
+ `${color2.amber("No benchmark role specified")}. Usage: wstack diag bench <role> [prompt]`
930
+ );
931
+ return 1;
932
+ }
933
+ const benchPrompt = benchArgs.slice(1).join(" ");
934
+ const cat = roleCat(benchRole);
935
+ const candidates = rankModels(providers, hasKey, cat, 5);
936
+ if (candidates.length === 0) {
937
+ writeLine(
938
+ `${color2.amber("No candidate models found")} for role "${benchRole}" (category: ${cat}).`
939
+ );
940
+ return 0;
941
+ }
942
+ let targetCandidates;
943
+ if (providerFilter && providerFilter.length > 0) {
944
+ targetCandidates = candidates.filter((c) => providerFilter.includes(c.provider));
945
+ if (targetCandidates.length === 0) {
946
+ writeLine(
947
+ `${color2.amber("No candidates match the specified providers")}: ${providerFilter.join(", ")}`
948
+ );
949
+ writeLine(
950
+ `Candidate providers: ${[...new Set(candidates.map((c) => c.provider))].join(", ")}`
951
+ );
952
+ return 0;
953
+ }
954
+ } else {
955
+ targetCandidates = candidates;
956
+ }
957
+ writeLine(
958
+ `${color2.bold("Model Benchmark")} \u2014 ${color2.amber(benchRole)} ${color2.dim(`(category: ${cat})`)}`
959
+ );
960
+ writeLine(
961
+ `${color2.dim("Prompt:")} "${benchPrompt.slice(0, 120)}${benchPrompt.length > 120 ? "\u2026" : ""}"`
962
+ );
963
+ writeLine();
964
+ writeLine(
965
+ ` ${color2.dim("# model".padEnd(52))} ${color2.dim("score".padEnd(12))} ${color2.dim("latency".padEnd(10))} ${color2.dim("tokens".padEnd(14))} ${color2.dim("first line")}`
966
+ );
967
+ writeLine(` ${color2.dim("\u2500".repeat(108))}`);
968
+ const providerInstances = /* @__PURE__ */ new Map();
969
+ for (const pid of [...new Set(targetCandidates.map((c) => c.provider))]) {
970
+ const prov = createProviderForId(pid, config);
971
+ if (prov) providerInstances.set(pid, prov);
972
+ }
973
+ let idx = 0;
974
+ for (const c of targetCandidates.slice(0, 20)) {
975
+ idx++;
976
+ const label = `${idx}`.padStart(2);
977
+ const modelKey = `${c.provider}/${c.model}`;
978
+ const prov = providerInstances.get(c.provider);
979
+ if (!prov) {
980
+ writeLine(
981
+ ` ${label} ${color2.red(modelKey.padEnd(50))} ${scoreBar(c.score, 110).slice(0, 11)} ${color2.red("NO PROVIDER")}`
982
+ );
983
+ continue;
984
+ }
985
+ try {
986
+ const start = Date.now();
987
+ const resp = await prov.complete(
988
+ {
989
+ model: c.model,
990
+ messages: [{ role: "user", content: [{ type: "text", text: benchPrompt }] }],
991
+ maxTokens: 256
992
+ },
993
+ { signal: AbortSignal.timeout(3e4) }
994
+ );
995
+ const latency = Date.now() - start;
996
+ const firstText = resp.content[0] && "text" in resp.content[0] ? resp.content[0].text : "";
997
+ const firstLineClean = firstText.replace(/\n/g, " ").slice(0, 80) || color2.dim("(empty)");
998
+ const provColor = c.provider === config.provider ? color2.green : color2.cyan;
999
+ const usage = resp.usage;
1000
+ writeLine(
1001
+ ` ${label} ${provColor(modelKey.padEnd(50))} ${scoreBar(c.score, 110).slice(0, 11)} ${color2.amber(fmtMs(latency).padEnd(8))} ${color2.dim(`in${usage?.input ?? "?"}/out${usage?.output ?? "?"}`.padEnd(12))} ${firstLineClean}`
1002
+ );
1003
+ } catch (err) {
1004
+ const errMsg = toErrorMessage2(err);
1005
+ writeLine(
1006
+ ` ${label} ${color2.red(modelKey.padEnd(50))} ${scoreBar(c.score, 110).slice(0, 11)} ${color2.red("FAILED")} ${color2.dim(errMsg.slice(0, 40))}`
1007
+ );
1008
+ }
1009
+ }
1010
+ const testedProviders = [...new Set(targetCandidates.map((c) => c.provider))];
1011
+ writeLine();
1012
+ writeLine(
1013
+ color2.dim(
1014
+ `Tested ${idx} model(s) across ${testedProviders.length} provider(s): ${testedProviders.join(", ")}.`
1015
+ )
1016
+ );
1017
+ writeLine(color2.dim("Pin the best: wstack setmodel set <role> <provider>/<model>"));
1018
+ return 0;
1019
+ }
1020
+ if (sub === "eval" || sub === "evall") {
1021
+ const evalArgs = args.slice(1);
1022
+ const providersEq = evalArgs.find((a) => a.startsWith("--providers="));
1023
+ const providersValue = providersEq?.replace("--providers=", "") ?? (typeof deps.flags?.["providers"] === "string" ? deps.flags["providers"] : typeof deps.flags?.["provider"] === "string" ? deps.flags["provider"] : void 0);
1024
+ const providerFilter = providersValue ? providersValue.split(",").map((s) => s.trim()).filter(Boolean) : void 0;
1025
+ const maxEq = evalArgs.find((a) => a.startsWith("--max="));
1026
+ const maxValue = maxEq?.replace("--max=", "") ?? (typeof deps.flags?.["max"] === "string" ? deps.flags["max"] : void 0);
1027
+ const maxModels = maxValue ? Math.max(1, parseInt(maxValue, 10) || 2) : 2;
1028
+ const quick = evalArgs.includes("--quick") || deps.flags?.["quick"] === true || deps.flags?.["quick"] === "true";
1029
+ const modelsPerCat = quick ? 1 : maxModels;
1030
+ const roleFilter = evalArgs.find((a) => !a.startsWith("--"));
1031
+ const targetCategories = roleFilter ? EVAL_CATEGORIES.includes(roleCat(roleFilter)) ? [roleCat(roleFilter)] : [] : EVAL_CATEGORIES;
1032
+ if (targetCategories.length === 0 && roleFilter) {
1033
+ writeLine(
1034
+ `${color2.amber("Unknown role/category")}: "${roleFilter}". Try: ${EVAL_CATEGORIES.join(", ")}`
1035
+ );
1036
+ return 1;
1037
+ }
1038
+ const keyedProviderIds = providers.filter((p) => hasKey(p.id)).map((p) => p.id);
1039
+ let targetProviderIds;
1040
+ if (providerFilter && providerFilter.length > 0) {
1041
+ const unknown = providerFilter.filter((pid) => !keyedProviderIds.includes(pid));
1042
+ targetProviderIds = providerFilter.filter((pid) => keyedProviderIds.includes(pid));
1043
+ if (targetProviderIds.length === 0) {
1044
+ const noKeyMsg = unknown.length > 0 ? `None of the specified providers (${unknown.join(", ")}) have API keys. Add keys with wstack auth.` : "None of the specified providers have API keys configured.";
1045
+ writeLine(`${color2.amber(noKeyMsg)}`);
1046
+ return 0;
1047
+ }
1048
+ } else if (keyedProviderIds.length === 0) {
1049
+ writeLine(`${color2.amber("No providers have API keys. Add keys with wstack auth.")}`);
1050
+ return 0;
1051
+ } else if (keyedProviderIds.length === 1) {
1052
+ targetProviderIds = keyedProviderIds;
1053
+ } else {
1054
+ const providerList = keyedProviderIds.map((pid, i) => {
1055
+ const info = providers.find((p) => p.id === pid);
1056
+ return ` ${color2.cyan(String(i + 1))}) ${color2.bold(pid.padEnd(16))} ${color2.dim(info?.name ?? "")}`;
1057
+ }).join("\n");
1058
+ deps.renderer.write(
1059
+ `
1060
+ ${color2.bold("Select providers to evaluate")}
1061
+
1062
+ ${providerList}
1063
+
1064
+ ${color2.dim('Enter numbers or provider IDs (comma-separated, or "all"):')}
1065
+ `
1066
+ );
1067
+ const input = await deps.reader.readLine(" > ");
1068
+ const selected = input.trim().toLowerCase();
1069
+ if (selected === "" || selected === "all") {
1070
+ targetProviderIds = keyedProviderIds;
1071
+ } else {
1072
+ targetProviderIds = [];
1073
+ for (const part of selected.split(",").map((s) => s.trim())) {
1074
+ const idx = parseInt(part, 10);
1075
+ if (idx >= 1 && idx <= keyedProviderIds.length) {
1076
+ const pid = keyedProviderIds[idx - 1];
1077
+ if (!targetProviderIds.includes(pid)) targetProviderIds.push(pid);
1078
+ } else if (keyedProviderIds.includes(part)) {
1079
+ if (!targetProviderIds.includes(part)) targetProviderIds.push(part);
1080
+ }
1081
+ }
1082
+ }
1083
+ if (targetProviderIds.length === 0) {
1084
+ writeLine(color2.dim("No providers selected."));
1085
+ return 0;
1086
+ }
1087
+ }
1088
+ const leaderModel = config.model ?? "unknown";
1089
+ const unknownProviders = providerFilter ? providerFilter.filter((pid) => !keyedProviderIds.includes(pid)) : [];
1090
+ const warningLine = unknownProviders.length > 0 ? ` ${color2.amber("\u26A0 skipped (no key):")} ${unknownProviders.join(", ")}
1091
+ ` : "";
1092
+ writeLine(`${color2.bold("Model Competency Evaluation")}`);
1093
+ writeLine(
1094
+ color2.dim(
1095
+ `Providers: ${targetProviderIds.join(", ")} | ${targetCategories.length} cats | ${modelsPerCat} model(s)/cat/provider`
1096
+ )
1097
+ );
1098
+ writeLine(warningLine);
1099
+ writeLine(color2.dim(`Leader (ranker): ${config.provider}/${leaderModel}`));
1100
+ writeLine();
1101
+ const collected = /* @__PURE__ */ new Map();
1102
+ let total = 0;
1103
+ let ok = 0;
1104
+ for (const pid of targetProviderIds) {
1105
+ const prov = createProviderForId(pid, config);
1106
+ if (!prov) {
1107
+ writeLine(color2.dim(` \u2298 ${pid}: provider unavailable, skipping`));
1108
+ continue;
1109
+ }
1110
+ for (const cat of targetCategories) {
1111
+ const task = EVAL_TASKS[cat];
1112
+ if (!task) continue;
1113
+ const candidates = rankModels(
1114
+ providers,
1115
+ (providerId) => providerId === pid && hasKey(providerId),
1116
+ cat,
1117
+ modelsPerCat
1118
+ );
1119
+ if (candidates.length === 0) continue;
1120
+ if (!collected.has(cat)) collected.set(cat, /* @__PURE__ */ new Map());
1121
+ for (const c of candidates) {
1122
+ total++;
1123
+ const modelKey = `${pid}/${c.model}`;
1124
+ try {
1125
+ const start = Date.now();
1126
+ const resp = await prov.complete(
1127
+ {
1128
+ model: c.model,
1129
+ system: [{ type: "text", text: "Be thorough and correct." }],
1130
+ messages: [
1131
+ { role: "user", content: [{ type: "text", text: task.prompt }] }
1132
+ ],
1133
+ maxTokens: 1024
1134
+ },
1135
+ { signal: AbortSignal.timeout(45e3) }
1136
+ );
1137
+ const respText = resp.content[0] && "text" in resp.content[0] ? resp.content[0].text : "";
1138
+ const respUsage = resp.usage;
1139
+ collected.get(cat)?.set(modelKey, {
1140
+ model: modelKey,
1141
+ latency: Date.now() - start,
1142
+ tokens: (respUsage?.input ?? 0) + (respUsage?.output ?? 0),
1143
+ text: respText
1144
+ });
1145
+ ok++;
1146
+ } catch {
1147
+ collected.get(cat)?.set(modelKey, {
1148
+ model: modelKey,
1149
+ latency: -1,
1150
+ tokens: 0,
1151
+ text: ""
1152
+ });
1153
+ }
1154
+ }
1155
+ }
1156
+ }
1157
+ writeLine(`${color2.dim(`Phase 1: ${ok}/${total} calls succeeded`)}`);
1158
+ writeLine();
1159
+ if (collected.size === 0) {
1160
+ writeLine(color2.amber("No responses collected. Check provider configuration."));
1161
+ return 0;
1162
+ }
1163
+ const leaderProvider = createProviderForId(config.provider, config);
1164
+ if (leaderProvider) {
1165
+ writeLine(`${color2.bold("Phase 2")} \u2014 ${color2.dim("leader ranks responses")}`);
1166
+ writeLine();
1167
+ }
1168
+ const rankings = /* @__PURE__ */ new Map();
1169
+ for (const [cat, responses] of collected) {
1170
+ const valid = Array.from(responses.values()).filter((r) => r.latency >= 0);
1171
+ if (valid.length < 2) {
1172
+ if (valid.length === 1) {
1173
+ const m = valid[0]?.model;
1174
+ if (m !== void 0) {
1175
+ if (!rankings.has(m)) rankings.set(m, /* @__PURE__ */ new Map());
1176
+ rankings.get(m)?.set(cat, { rank: 1, total: 1 });
1177
+ }
1178
+ }
1179
+ continue;
1180
+ }
1181
+ const task = EVAL_TASKS[cat];
1182
+ if (leaderProvider) {
1183
+ const ranked = await rankResponses(leaderProvider, leaderModel, task.prompt, valid);
1184
+ for (let i = 0; i < valid.length; i++) {
1185
+ const m = valid[ranked[i] ?? i]?.model;
1186
+ if (m === void 0) continue;
1187
+ if (!rankings.has(m)) rankings.set(m, /* @__PURE__ */ new Map());
1188
+ rankings.get(m)?.set(cat, { rank: i + 1, total: valid.length });
1189
+ }
1190
+ } else {
1191
+ for (const r of valid) {
1192
+ if (!rankings.has(r.model)) rankings.set(r.model, /* @__PURE__ */ new Map());
1193
+ rankings.get(r.model)?.set(cat, { rank: 1, total: valid.length });
1194
+ }
1195
+ }
1196
+ }
1197
+ writeLine(`${color2.bold("Competency Report")}`);
1198
+ writeLine();
1199
+ const allModels = [.../* @__PURE__ */ new Set([...rankings.keys()])].sort();
1200
+ const catList = [...collected.keys()];
1201
+ const modelColWidth = Math.max(24, ...allModels.map((m) => m.length)) + 2;
1202
+ const cw = 12;
1203
+ writeLine(
1204
+ ` ${color2.dim("model".padEnd(modelColWidth))}` + catList.map((c) => color2.dim((EVAL_TASKS[c]?.label ?? c).slice(0, cw).padEnd(cw + 2))).join("")
1205
+ );
1206
+ writeLine(` ${color2.dim("\u2500".repeat(modelColWidth + catList.length * (cw + 2)))}`);
1207
+ for (const model of allModels) {
1208
+ const mr = rankings.get(model);
1209
+ const provFromModel = model.split("/")[0] ?? "";
1210
+ const modelColor = provFromModel === config.provider ? color2.cyan : color2.green;
1211
+ let row = ` ${modelColor(model.padEnd(modelColWidth))}`;
1212
+ for (const cat of catList) {
1213
+ const e = mr.get(cat);
1214
+ if (e) {
1215
+ const pct = Math.round((1 - (e.rank - 1) / Math.max(1, e.total - 1)) * 100);
1216
+ const pc = pct >= 80 ? color2.green : pct >= 50 ? color2.amber : color2.red;
1217
+ row += `${pc(`#${e.rank} ${pct}%`.padEnd(cw + 2))}`;
1218
+ } else {
1219
+ row += color2.dim("\u2014".padEnd(cw + 2));
1220
+ }
1221
+ }
1222
+ writeLine(row);
1223
+ }
1224
+ writeLine();
1225
+ writeLine(color2.dim("#1 100% = best in category. \u2014 = not tested."));
1226
+ writeLine();
1227
+ writeLine(color2.dim("Pin: wstack setmodel set <role> <provider>/<model>"));
1228
+ writeLine(
1229
+ color2.dim(
1230
+ "Full: wstack modeldiag eval Providers: wstack modeldiag eval --providers=id1,id2"
1231
+ )
1232
+ );
1233
+ writeLine(
1234
+ color2.dim("Max: wstack modeldiag eval --max=3 Quick: wstack modeldiag eval --quick")
1235
+ );
1236
+ return 0;
1237
+ }
1238
+ writeLine(`${color2.bold("API Key Status")}`);
1239
+ writeLine();
1240
+ for (const prov of providers) {
1241
+ const k = hasKey(prov.id);
1242
+ writeLine(` ${checkMark(k)} ${color2.bold(prov.id.padEnd(18))} ${color2.dim(prov.name)}`);
1243
+ }
1244
+ writeLine();
1245
+ writeLine(`${color2.dim(`Leader: ${config.provider}/${config.model}`)}`);
1246
+ writeLine();
1247
+ writeLine(`${color2.bold("Model Capabilities")} ${color2.dim("\u2014 matched to known profiles")}`);
1248
+ writeLine();
1249
+ for (const prov of providers) {
1250
+ if (!hasKey(prov.id)) continue;
1251
+ writeLine(` ${color2.bold(prov.id)} ${color2.dim(`(${prov.name})`)}`);
1252
+ const tiers = {
1253
+ premium: [],
1254
+ standard: [],
1255
+ budget: [],
1256
+ unknown: []
1257
+ };
1258
+ for (const m of prov.models ?? []) {
1259
+ const profile = findProfile(prov.id, m.id);
1260
+ tiers[profile?.costTier ?? "unknown"]?.push(m);
1261
+ }
1262
+ for (const tier of ["premium", "standard", "budget", "unknown"]) {
1263
+ const tierModels = tiers[tier];
1264
+ if (tierModels.length === 0) continue;
1265
+ const label = tier === "unknown" ? color2.dim("unmatched") : `${costLabel(tier)} ${tier}`;
1266
+ writeLine(` ${label}`);
1267
+ for (const m of tierModels) {
1268
+ const cap = m.capabilities;
1269
+ const ctx = cap?.contextWindow ?? 0;
1270
+ const maxOut = cap?.maxOutputTokens ?? 0;
1271
+ const profile = findProfile(prov.id, m.id);
1272
+ const family = profile ? `${speedLabel(profile.speedTier)} ${color2.green(profile.family)}` : color2.dim("no profile match");
1273
+ const pricing = m.pricing ? `${color2.dim("in")}${fmtPrice(m.pricing.input)} ${color2.dim("out")}${fmtPrice(m.pricing.output)}` : color2.dim("pricing ?");
1274
+ writeLine(
1275
+ ` ${color2.cyan(m.id.padEnd(34))}${ctx > 0 ? `ctx ${fmtTokens(ctx).padEnd(6)}` : color2.dim("ctx ? ")}${maxOut > 0 ? `out ${fmtTokens(maxOut).padEnd(6)}` : " "}${family} ${pricing}`
1276
+ );
1277
+ }
1278
+ }
1279
+ writeLine();
1280
+ }
1281
+ await renderSuggest();
1282
+ writeLine();
1283
+ writeLine(color2.dim("Pin a suggestion: wstack setmodel set <role> <provider>/<model>"));
1284
+ writeLine(color2.dim('Test candidates: wstack modeldiag bench <role> "<test prompt>"'));
1285
+ return 0;
1286
+ };
1287
+ export {
1288
+ modeldiagCmd
1289
+ };
1290
+ //# sourceMappingURL=modeldiag-HENYJ4N7.js.map