@wrongstack/cli 0.295.1 → 0.296.3
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.
- package/data/providers.json +0 -24
- package/dist/acp-A5OSIU2P.js +824 -0
- package/dist/acp-A5OSIU2P.js.map +7 -0
- package/dist/acp-server-agent.d.ts.map +1 -1
- package/dist/arg-parser.d.ts.map +1 -1
- package/dist/audit-2ZSFGNIF.js +102 -0
- package/dist/audit-2ZSFGNIF.js.map +7 -0
- package/dist/auth-CJWQJVRH.js +504 -0
- package/dist/auth-CJWQJVRH.js.map +7 -0
- package/dist/auth-menu/auth-menu-audit.d.ts +0 -4
- package/dist/auth-menu/auth-menu-audit.d.ts.map +1 -1
- package/dist/bench-7ZDWSNEF.js +278 -0
- package/dist/bench-7ZDWSNEF.js.map +7 -0
- package/dist/boot/brain-decision-log.d.ts +7 -5
- package/dist/boot/brain-decision-log.d.ts.map +1 -1
- package/dist/boot/dispatch-webui.d.ts +5 -8
- package/dist/boot/dispatch-webui.d.ts.map +1 -1
- package/dist/boot/system-prompt-builder.d.ts +3 -0
- package/dist/boot/system-prompt-builder.d.ts.map +1 -1
- package/dist/boot/tui-coordinator-callbacks.d.ts +45 -0
- package/dist/boot/tui-coordinator-callbacks.d.ts.map +1 -0
- package/dist/boot/tui-project-switch.d.ts +2 -3
- package/dist/boot/tui-project-switch.d.ts.map +1 -1
- package/dist/boot/tui-runtime-state.d.ts +5 -6
- package/dist/boot/tui-runtime-state.d.ts.map +1 -1
- package/dist/boot/tui-session-resume.d.ts.map +1 -1
- package/dist/boot/tui-settings-adapter.d.ts +2 -3
- package/dist/boot/tui-settings-adapter.d.ts.map +1 -1
- package/dist/boot.d.ts.map +1 -1
- package/dist/brain-menu/panel-service.d.ts.map +1 -1
- package/dist/chimera-review-task.d.ts +6 -0
- package/dist/chimera-review-task.d.ts.map +1 -0
- package/dist/chimera-reviewer-policy.d.ts +34 -0
- package/dist/chimera-reviewer-policy.d.ts.map +1 -0
- package/dist/chronicle-QQEQFSSE.js +256 -0
- package/dist/chronicle-QQEQFSSE.js.map +7 -0
- package/dist/chunk-5N34EWJR.js +418 -0
- package/dist/chunk-5N34EWJR.js.map +7 -0
- package/dist/chunk-66T43Q4Y.js +90 -0
- package/dist/chunk-66T43Q4Y.js.map +7 -0
- package/dist/chunk-7OCVIDC7.js +11 -0
- package/dist/chunk-7OCVIDC7.js.map +7 -0
- package/dist/chunk-ABXK4VVY.js +84 -0
- package/dist/chunk-ABXK4VVY.js.map +7 -0
- package/dist/chunk-AXVZMEWG.js +306 -0
- package/dist/chunk-AXVZMEWG.js.map +7 -0
- package/dist/chunk-AZESNNIC.js +216 -0
- package/dist/chunk-AZESNNIC.js.map +7 -0
- package/dist/chunk-BGFM3PD7.js +41 -0
- package/dist/chunk-BGFM3PD7.js.map +7 -0
- package/dist/chunk-BQCAJ7FI.js +425 -0
- package/dist/chunk-BQCAJ7FI.js.map +7 -0
- package/dist/chunk-DPJZQCVP.js +13 -0
- package/dist/chunk-DPJZQCVP.js.map +7 -0
- package/dist/chunk-F4PEGAJZ.js +176 -0
- package/dist/chunk-F4PEGAJZ.js.map +7 -0
- package/dist/chunk-IHBYBYGA.js +443 -0
- package/dist/chunk-IHBYBYGA.js.map +7 -0
- package/dist/chunk-JBSQ7ONN.js +1023 -0
- package/dist/chunk-JBSQ7ONN.js.map +7 -0
- package/dist/chunk-JBTFWWKV.js +1325 -0
- package/dist/chunk-JBTFWWKV.js.map +7 -0
- package/dist/chunk-JUHRI6OV.js +100 -0
- package/dist/chunk-JUHRI6OV.js.map +7 -0
- package/dist/chunk-OI7GWJDS.js +3303 -0
- package/dist/chunk-OI7GWJDS.js.map +7 -0
- package/dist/chunk-OP47B3IX.js +142 -0
- package/dist/chunk-OP47B3IX.js.map +7 -0
- package/dist/chunk-PJHET45A.js +158 -0
- package/dist/chunk-PJHET45A.js.map +7 -0
- package/dist/chunk-Q5GTM25S.js +17 -0
- package/dist/chunk-Q5GTM25S.js.map +7 -0
- package/dist/chunk-QD544J2B.js +19 -0
- package/dist/chunk-QD544J2B.js.map +7 -0
- package/dist/chunk-QUNHS6O3.js +258 -0
- package/dist/chunk-QUNHS6O3.js.map +7 -0
- package/dist/chunk-TADVX644.js +480 -0
- package/dist/chunk-TADVX644.js.map +7 -0
- package/dist/chunk-TGDHN4LM.js +81 -0
- package/dist/chunk-TGDHN4LM.js.map +7 -0
- package/dist/chunk-TYO2OVAD.js +50 -0
- package/dist/chunk-TYO2OVAD.js.map +7 -0
- package/dist/chunk-VCYZ3WZV.js +14 -0
- package/dist/chunk-VCYZ3WZV.js.map +7 -0
- package/dist/chunk-VJUEZZYB.js +29 -0
- package/dist/chunk-VJUEZZYB.js.map +7 -0
- package/dist/chunk-WHOIR577.js +1 -0
- package/dist/chunk-WHOIR577.js.map +7 -0
- package/dist/chunk-WY7KKOUK.js +460 -0
- package/dist/chunk-WY7KKOUK.js.map +7 -0
- package/dist/chunk-XJXDOF63.js +28 -0
- package/dist/chunk-XJXDOF63.js.map +7 -0
- package/dist/chunk-XWEGWYDU.js +560 -0
- package/dist/chunk-XWEGWYDU.js.map +7 -0
- package/dist/chunk-YWUPHRGB.js +346 -0
- package/dist/chunk-YWUPHRGB.js.map +7 -0
- package/dist/chunk-Z7YGASQP.js +313 -0
- package/dist/chunk-Z7YGASQP.js.map +7 -0
- package/dist/cli-entry-main.d.ts +2 -0
- package/dist/cli-entry-main.d.ts.map +1 -0
- package/dist/cli-entry-point.d.ts +3 -3
- package/dist/cli-entry-point.d.ts.map +1 -1
- package/dist/cli-main-RTY35OPD.js +29268 -0
- package/dist/cli-main-RTY35OPD.js.map +7 -0
- package/dist/cli-main-helpers.d.ts +21 -0
- package/dist/cli-main-helpers.d.ts.map +1 -0
- package/dist/cli-main.d.ts +25 -1
- package/dist/cli-main.d.ts.map +1 -1
- package/dist/context-limit.d.ts +48 -0
- package/dist/context-limit.d.ts.map +1 -1
- package/dist/diag-doctor-OQ3AA63O.js +170 -0
- package/dist/diag-doctor-OQ3AA63O.js.map +7 -0
- package/dist/execute-deps.d.ts +11 -12
- package/dist/execute-deps.d.ts.map +1 -1
- package/dist/execution-O7I5DYE6.js +4682 -0
- package/dist/execution-O7I5DYE6.js.map +7 -0
- package/dist/execution-chimera-ask.d.ts +10 -0
- package/dist/execution-chimera-ask.d.ts.map +1 -0
- package/dist/execution-chimera-cascade.d.ts +15 -0
- package/dist/execution-chimera-cascade.d.ts.map +1 -0
- package/dist/execution-cleanup.d.ts +23 -0
- package/dist/execution-cleanup.d.ts.map +1 -0
- package/dist/execution-kanban-dispatch.d.ts +10 -0
- package/dist/execution-kanban-dispatch.d.ts.map +1 -0
- package/dist/execution-repl-fleet-callbacks.d.ts +11 -0
- package/dist/execution-repl-fleet-callbacks.d.ts.map +1 -0
- package/dist/execution-storage-observability.d.ts +3 -0
- package/dist/execution-storage-observability.d.ts.map +1 -0
- package/dist/execution-tui-next-step-callbacks.d.ts +20 -0
- package/dist/execution-tui-next-step-callbacks.d.ts.map +1 -0
- package/dist/execution.d.ts +2 -139
- package/dist/execution.d.ts.map +1 -1
- package/dist/export-TPORYVRZ.js +64 -0
- package/dist/export-TPORYVRZ.js.map +7 -0
- package/dist/fleet/host-acp-runner-cache.d.ts +9 -0
- package/dist/fleet/host-acp-runner-cache.d.ts.map +1 -0
- package/dist/fleet/host-acp.d.ts +3 -0
- package/dist/fleet/host-acp.d.ts.map +1 -0
- package/dist/fleet/host-concurrency.d.ts +2 -0
- package/dist/fleet/host-concurrency.d.ts.map +1 -0
- package/dist/fleet/host-context.d.ts +5 -0
- package/dist/fleet/host-context.d.ts.map +1 -0
- package/dist/fleet/host-director-builder.d.ts +24 -0
- package/dist/fleet/host-director-builder.d.ts.map +1 -0
- package/dist/fleet/host-director-event-bridges.d.ts +37 -0
- package/dist/fleet/host-director-event-bridges.d.ts.map +1 -0
- package/dist/fleet/host-director-services.d.ts +20 -0
- package/dist/fleet/host-director-services.d.ts.map +1 -0
- package/dist/fleet/host-event-bridge.d.ts +17 -0
- package/dist/fleet/host-event-bridge.d.ts.map +1 -0
- package/dist/fleet/host-helpers.d.ts +22 -0
- package/dist/fleet/host-helpers.d.ts.map +1 -0
- package/dist/fleet/host-learning-tracker.d.ts +11 -0
- package/dist/fleet/host-learning-tracker.d.ts.map +1 -0
- package/dist/fleet/host-learning.d.ts +4 -0
- package/dist/fleet/host-learning.d.ts.map +1 -0
- package/dist/fleet/host-lifecycle-events.d.ts +4 -0
- package/dist/fleet/host-lifecycle-events.d.ts.map +1 -0
- package/dist/fleet/host-paths.d.ts +3 -0
- package/dist/fleet/host-paths.d.ts.map +1 -0
- package/dist/fleet/host-provider.d.ts +22 -0
- package/dist/fleet/host-provider.d.ts.map +1 -0
- package/dist/fleet/host-session-writer.d.ts +3 -0
- package/dist/fleet/host-session-writer.d.ts.map +1 -0
- package/dist/fleet/host-shadow-pass.d.ts +21 -0
- package/dist/fleet/host-shadow-pass.d.ts.map +1 -0
- package/dist/fleet/host-spawn-types.d.ts +25 -0
- package/dist/fleet/host-spawn-types.d.ts.map +1 -0
- package/dist/fleet/host-status.d.ts +48 -0
- package/dist/fleet/host-status.d.ts.map +1 -0
- package/dist/fleet/host-subagent-factory.d.ts +16 -0
- package/dist/fleet/host-subagent-factory.d.ts.map +1 -0
- package/dist/fleet/host-supervisor.d.ts +16 -0
- package/dist/fleet/host-supervisor.d.ts.map +1 -0
- package/dist/fleet/host-task-result-report.d.ts +11 -0
- package/dist/fleet/host-task-result-report.d.ts.map +1 -0
- package/dist/fleet/host-types.d.ts +89 -0
- package/dist/fleet/host-types.d.ts.map +1 -0
- package/dist/fleet/host.d.ts +10 -357
- package/dist/fleet/host.d.ts.map +1 -1
- package/dist/hq-JUYKUNJX.js +547 -0
- package/dist/hq-JUYKUNJX.js.map +7 -0
- package/dist/hq-command-controller.d.ts +2 -2
- package/dist/hq-command-controller.d.ts.map +1 -1
- package/dist/hq-server/auth.d.ts +15 -4
- package/dist/hq-server/auth.d.ts.map +1 -1
- package/dist/hq-server/project-root.d.ts +5 -0
- package/dist/hq-server/project-root.d.ts.map +1 -0
- package/dist/hq-server/routes/auth-handlers.d.ts +25 -0
- package/dist/hq-server/routes/auth-handlers.d.ts.map +1 -0
- package/dist/hq-server/routes/session-handlers.d.ts +8 -0
- package/dist/hq-server/routes/session-handlers.d.ts.map +1 -0
- package/dist/hq-server/routes.d.ts +8 -6
- package/dist/hq-server/routes.d.ts.map +1 -1
- package/dist/hq-server/snapshot.d.ts +44 -0
- package/dist/hq-server/snapshot.d.ts.map +1 -1
- package/dist/hq-server/types.d.ts +22 -4
- package/dist/hq-server/types.d.ts.map +1 -1
- package/dist/hq-server/utils.d.ts +8 -0
- package/dist/hq-server/utils.d.ts.map +1 -1
- package/dist/hq-server/ws.d.ts +1 -1
- package/dist/hq-server/ws.d.ts.map +1 -1
- package/dist/hq-server-6AQ3BXZA.js +39 -0
- package/dist/hq-server-6AQ3BXZA.js.map +7 -0
- package/dist/hq-server.d.ts +3 -3
- package/dist/hq-server.d.ts.map +1 -1
- package/dist/hq-ttl-U2FAYFAT.js +8 -0
- package/dist/hq-ttl-U2FAYFAT.js.map +7 -0
- package/dist/hq-tunnel-RFKGC4HI.js +114 -0
- package/dist/hq-tunnel-RFKGC4HI.js.map +7 -0
- package/dist/hq-tunnel.d.ts +1 -1
- package/dist/hq-tunnel.d.ts.map +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2503 -53026
- package/dist/index.js.map +4 -4
- package/dist/init-E2NDDOHI.js +27 -0
- package/dist/init-E2NDDOHI.js.map +7 -0
- package/dist/kanban-dispatch-route.d.ts +14 -0
- package/dist/kanban-dispatch-route.d.ts.map +1 -0
- package/dist/kanban-hq-sync.d.ts +2 -0
- package/dist/kanban-hq-sync.d.ts.map +1 -1
- package/dist/kanban-run-mirror-EKVNGXWW.js +12 -0
- package/dist/kanban-run-mirror-EKVNGXWW.js.map +7 -0
- package/dist/live-settings-input.d.ts +69 -0
- package/dist/live-settings-input.d.ts.map +1 -0
- package/dist/mailbox-serve-2UWHEN3M.js +302 -0
- package/dist/mailbox-serve-2UWHEN3M.js.map +7 -0
- package/dist/mcp-CYLPUEHC.js +413 -0
- package/dist/mcp-CYLPUEHC.js.map +7 -0
- package/dist/modeldiag-HENYJ4N7.js +1290 -0
- package/dist/modeldiag-HENYJ4N7.js.map +7 -0
- package/dist/permissions-FNYLZIL4.js +115 -0
- package/dist/permissions-FNYLZIL4.js.map +7 -0
- package/dist/picker-key-state.d.ts +7 -0
- package/dist/picker-key-state.d.ts.map +1 -0
- package/dist/picker-model-picker.d.ts +6 -0
- package/dist/picker-model-picker.d.ts.map +1 -0
- package/dist/picker-ui.d.ts +17 -0
- package/dist/picker-ui.d.ts.map +1 -0
- package/dist/picker.d.ts +4 -37
- package/dist/picker.d.ts.map +1 -1
- package/dist/plugin-usage-OU6X6LM3.js +40 -0
- package/dist/plugin-usage-OU6X6LM3.js.map +7 -0
- package/dist/plugins-4LJ5IUBI.js +24 -0
- package/dist/plugins-4LJ5IUBI.js.map +7 -0
- package/dist/pre-launch.d.ts +0 -1
- package/dist/pre-launch.d.ts.map +1 -1
- package/dist/project-BLQ3ALVL.js +76 -0
- package/dist/project-BLQ3ALVL.js.map +7 -0
- package/dist/project-manifest-GE25PW4S.js +18 -0
- package/dist/project-manifest-GE25PW4S.js.map +7 -0
- package/dist/project-picker-BOCWHBXP.js +17 -0
- package/dist/project-picker-BOCWHBXP.js.map +7 -0
- package/dist/projects-XE76NFNZ.js +38 -0
- package/dist/projects-XE76NFNZ.js.map +7 -0
- package/dist/provider-helpers.d.ts +22 -6
- package/dist/provider-helpers.d.ts.map +1 -1
- package/dist/providers-models-GDELBHZK.js +589 -0
- package/dist/providers-models-GDELBHZK.js.map +7 -0
- package/dist/quick-VIO2BEHS.js +10 -0
- package/dist/quick-VIO2BEHS.js.map +7 -0
- package/dist/repl-auto-proceed.d.ts +19 -0
- package/dist/repl-auto-proceed.d.ts.map +1 -0
- package/dist/repl-client-registration.d.ts +7 -0
- package/dist/repl-client-registration.d.ts.map +1 -0
- package/dist/repl-input.d.ts +11 -0
- package/dist/repl-input.d.ts.map +1 -0
- package/dist/repl-options.d.ts +54 -0
- package/dist/repl-options.d.ts.map +1 -0
- package/dist/repl-rendering.d.ts +4 -0
- package/dist/repl-rendering.d.ts.map +1 -0
- package/dist/repl-suggestions.d.ts +21 -0
- package/dist/repl-suggestions.d.ts.map +1 -0
- package/dist/repl.d.ts +3 -162
- package/dist/repl.d.ts.map +1 -1
- package/dist/replay-KCTXNMZQ.js +75 -0
- package/dist/replay-KCTXNMZQ.js.map +7 -0
- package/dist/rewind-EJMVFVLS.js +185 -0
- package/dist/rewind-EJMVFVLS.js.map +7 -0
- package/dist/sdd-runtime-JG4EEKL6.js +54 -0
- package/dist/sdd-runtime-JG4EEKL6.js.map +7 -0
- package/dist/services/sdd/project-context.d.ts +1 -1
- package/dist/services/sdd/project-context.d.ts.map +1 -1
- package/dist/services/sdd/task-manager.d.ts.map +1 -1
- package/dist/services/statusline-config.d.ts +1 -1
- package/dist/services/statusline-config.d.ts.map +1 -1
- package/dist/session-event-wiring.d.ts +2 -2
- package/dist/session-event-wiring.d.ts.map +1 -1
- package/dist/sessions-config-NLCMK3BY.js +409 -0
- package/dist/sessions-config-NLCMK3BY.js.map +7 -0
- package/dist/settings-menu.d.ts +3 -18
- package/dist/settings-menu.d.ts.map +1 -1
- package/dist/simpleui-dist-JIFGUJO7.js +93 -0
- package/dist/simpleui-dist-JIFGUJO7.js.map +7 -0
- package/dist/slash-commands/brain.d.ts.map +1 -1
- package/dist/slash-commands/clear.d.ts.map +1 -1
- package/dist/slash-commands/fallback.d.ts.map +1 -1
- package/dist/slash-commands/kanban-agent-helpers.d.ts +18 -0
- package/dist/slash-commands/kanban-agent-helpers.d.ts.map +1 -0
- package/dist/slash-commands/kanban-format.d.ts +16 -0
- package/dist/slash-commands/kanban-format.d.ts.map +1 -0
- package/dist/slash-commands/kanban-help.d.ts +2 -0
- package/dist/slash-commands/kanban-help.d.ts.map +1 -0
- package/dist/slash-commands/kanban.d.ts.map +1 -1
- package/dist/slash-commands/mailbox-demo.d.ts.map +1 -1
- package/dist/slash-commands/mailbox.d.ts +2 -1
- package/dist/slash-commands/mailbox.d.ts.map +1 -1
- package/dist/slash-commands/memory-compact.d.ts +5 -0
- package/dist/slash-commands/memory-compact.d.ts.map +1 -0
- package/dist/slash-commands/memory-flags.d.ts +36 -0
- package/dist/slash-commands/memory-flags.d.ts.map +1 -0
- package/dist/slash-commands/memory-formatters.d.ts +16 -0
- package/dist/slash-commands/memory-formatters.d.ts.map +1 -0
- package/dist/slash-commands/memory.d.ts.map +1 -1
- package/dist/slash-commands/mouse.d.ts +2 -2
- package/dist/slash-commands/review.d.ts.map +1 -1
- package/dist/slash-commands/sdd-command-helpers.d.ts +23 -0
- package/dist/slash-commands/sdd-command-helpers.d.ts.map +1 -0
- package/dist/slash-commands/sdd-format.d.ts +32 -0
- package/dist/slash-commands/sdd-format.d.ts.map +1 -0
- package/dist/slash-commands/sdd.d.ts.map +1 -1
- package/dist/slash-commands/settings.d.ts.map +1 -1
- package/dist/subcommands/handlers/chronicle.d.ts.map +1 -1
- package/dist/subcommands/handlers/mailbox-serve.d.ts.map +1 -1
- package/dist/subcommands/handlers/model-smoke-test.d.ts +51 -0
- package/dist/subcommands/handlers/model-smoke-test.d.ts.map +1 -0
- package/dist/subcommands/handlers/modeldiag-profiles.d.ts +64 -0
- package/dist/subcommands/handlers/modeldiag-profiles.d.ts.map +1 -0
- package/dist/subcommands/handlers/modeldiag.d.ts.map +1 -1
- package/dist/subcommands/handlers/per-subcommand-deep-help-table.d.ts +3 -0
- package/dist/subcommands/handlers/per-subcommand-deep-help-table.d.ts.map +1 -0
- package/dist/subcommands/handlers/per-subcommand-help-data.d.ts +3 -0
- package/dist/subcommands/handlers/per-subcommand-help-data.d.ts.map +1 -0
- package/dist/subcommands/handlers/per-subcommand-help-table.d.ts +36 -0
- package/dist/subcommands/handlers/per-subcommand-help-table.d.ts.map +1 -0
- package/dist/subcommands/handlers/per-subcommand-help-types.d.ts +18 -0
- package/dist/subcommands/handlers/per-subcommand-help-types.d.ts.map +1 -0
- package/dist/subcommands/handlers/per-subcommand-help.d.ts +2 -80
- package/dist/subcommands/handlers/per-subcommand-help.d.ts.map +1 -1
- package/dist/subcommands/handlers/rewind.d.ts.map +1 -1
- package/dist/subcommands/index.d.ts +7 -0
- package/dist/subcommands/index.d.ts.map +1 -1
- package/dist/tools-skills-UNKLOB7M.js +29 -0
- package/dist/tools-skills-UNKLOB7M.js.map +7 -0
- package/dist/update-YC4TYW2Y.js +16 -0
- package/dist/update-YC4TYW2Y.js.map +7 -0
- package/dist/update-check-UMYTOH7Z.js +18 -0
- package/dist/update-check-UMYTOH7Z.js.map +7 -0
- package/dist/version-help-DROHZRW6.js +11 -0
- package/dist/version-help-DROHZRW6.js.map +7 -0
- package/dist/webui-server/connection-handler.d.ts.map +1 -1
- package/dist/webui-server/kanban-host-adapter.d.ts +5 -1
- package/dist/webui-server/kanban-host-adapter.d.ts.map +1 -1
- package/dist/webui-server/listen-helpers.d.ts +18 -0
- package/dist/webui-server/listen-helpers.d.ts.map +1 -0
- package/dist/webui-server/node-pty-loader.d.ts +6 -0
- package/dist/webui-server/node-pty-loader.d.ts.map +1 -0
- package/dist/webui-server-ZF5KVGC5.js +1460 -0
- package/dist/webui-server-ZF5KVGC5.js.map +7 -0
- package/dist/webui-server-options.d.ts +191 -0
- package/dist/webui-server-options.d.ts.map +1 -0
- package/dist/webui-server.d.ts +2 -178
- package/dist/webui-server.d.ts.map +1 -1
- package/dist/wiring/brain-and-orchestration.d.ts.map +1 -1
- package/dist/wiring/codebase-index.d.ts.map +1 -1
- package/dist/wiring/command-host-state.d.ts +4 -4
- package/dist/wiring/dep-watcher-bridge.d.ts +23 -0
- package/dist/wiring/dep-watcher-bridge.d.ts.map +1 -0
- package/dist/wiring/dep-watcher.d.ts.map +1 -1
- package/dist/wiring/hq-telemetry.d.ts +2 -2
- package/dist/wiring/lifecycle-plugins.d.ts +4 -3
- package/dist/wiring/lifecycle-plugins.d.ts.map +1 -1
- package/dist/wiring/mailbox-bridge-bootstrap.d.ts +1 -1
- package/dist/wiring/management-tools.d.ts +15 -0
- package/dist/wiring/management-tools.d.ts.map +1 -0
- package/dist/wiring/pipeline.d.ts +2 -1
- package/dist/wiring/pipeline.d.ts.map +1 -1
- package/dist/wiring/plugins.d.ts +1 -1
- package/dist/wiring/plugins.d.ts.map +1 -1
- package/dist/wiring/provider-runtime-setup.d.ts +14 -1
- package/dist/wiring/provider-runtime-setup.d.ts.map +1 -1
- package/dist/wiring/provider.d.ts.map +1 -1
- package/dist/wiring/runtime-controller-deps.d.ts +1 -1
- package/dist/wiring/runtime-controller-deps.d.ts.map +1 -1
- package/dist/wiring/sage.d.ts.map +1 -1
- package/dist/wiring/session-registry.d.ts +38 -0
- package/dist/wiring/session-registry.d.ts.map +1 -0
- package/dist/wiring/session.d.ts +10 -6
- package/dist/wiring/session.d.ts.map +1 -1
- package/dist/wiring/tools.d.ts.map +1 -1
- package/package.json +22 -22
- package/dist/cli-recovery-prompt.d.ts +0 -19
- package/dist/cli-recovery-prompt.d.ts.map +0 -1
- package/dist/first-run-auth-gate.d.ts +0 -20
- package/dist/first-run-auth-gate.d.ts.map +0 -1
- package/dist/pre-launch/indexing-question.d.ts +0 -28
- package/dist/pre-launch/indexing-question.d.ts.map +0 -1
|
@@ -0,0 +1,1023 @@
|
|
|
1
|
+
import {
|
|
2
|
+
hasApiKey,
|
|
3
|
+
isKeylessLocalProvider,
|
|
4
|
+
visibleModelIds
|
|
5
|
+
} from "./chunk-66T43Q4Y.js";
|
|
6
|
+
import {
|
|
7
|
+
appendHistory,
|
|
8
|
+
backupCurrent
|
|
9
|
+
} from "./chunk-YWUPHRGB.js";
|
|
10
|
+
|
|
11
|
+
// src/arg-parser.ts
|
|
12
|
+
var BOOLEAN_FLAGS = /* @__PURE__ */ new Set([
|
|
13
|
+
"yolo",
|
|
14
|
+
"no-yolo",
|
|
15
|
+
"yolo-destructive",
|
|
16
|
+
"confirm-destructive",
|
|
17
|
+
"force-all-yolo",
|
|
18
|
+
"verbose",
|
|
19
|
+
"trace",
|
|
20
|
+
"help",
|
|
21
|
+
"version",
|
|
22
|
+
"yes",
|
|
23
|
+
"no-banner",
|
|
24
|
+
"no-features",
|
|
25
|
+
"tui",
|
|
26
|
+
"no-tui",
|
|
27
|
+
// Legacy no-ops: every surface now starts fresh unless an explicit
|
|
28
|
+
// `--resume <id>` is supplied. Keep parsing these as booleans so old
|
|
29
|
+
// launch scripts do not accidentally consume the next positional token.
|
|
30
|
+
"no-recovery",
|
|
31
|
+
"recover",
|
|
32
|
+
"output-json",
|
|
33
|
+
"prompt",
|
|
34
|
+
"metrics",
|
|
35
|
+
"webui",
|
|
36
|
+
"simpleui",
|
|
37
|
+
"full-auto",
|
|
38
|
+
"desktop",
|
|
39
|
+
"open",
|
|
40
|
+
"webui-require-token",
|
|
41
|
+
"require-token",
|
|
42
|
+
"no-check",
|
|
43
|
+
"no-models-refresh",
|
|
44
|
+
// (removed: 'director' and 'no-director' — Director Mode is always on)
|
|
45
|
+
"no-autonomy",
|
|
46
|
+
"no-hints",
|
|
47
|
+
"hints",
|
|
48
|
+
"no-menu",
|
|
49
|
+
"no-hooks",
|
|
50
|
+
"skip",
|
|
51
|
+
"skip-index",
|
|
52
|
+
"mouse",
|
|
53
|
+
"no-interactive",
|
|
54
|
+
"token-saving-mode",
|
|
55
|
+
"system-lite",
|
|
56
|
+
"system-pro",
|
|
57
|
+
"hq",
|
|
58
|
+
"hq-allow-exec",
|
|
59
|
+
"tunnel",
|
|
60
|
+
// Opt-in to a non-loopback HQ bind with no token/password configured.
|
|
61
|
+
"insecure-open",
|
|
62
|
+
"strict-port",
|
|
63
|
+
"client",
|
|
64
|
+
// `wstack update` booleans. Keeping these here prevents parseArgs from
|
|
65
|
+
// consuming a following positional token as an accidental flag value.
|
|
66
|
+
"check-only",
|
|
67
|
+
"allow-scripts",
|
|
68
|
+
"lifecycle-scripts",
|
|
69
|
+
"npm",
|
|
70
|
+
"pnpm",
|
|
71
|
+
"yarn",
|
|
72
|
+
"bun",
|
|
73
|
+
// `wstack acp` booleans. Without these, parseArgs treats the value after
|
|
74
|
+
// `--fs`/`--echo` as the flag's value and eats a following positional
|
|
75
|
+
// (e.g. the agent list in `acp bench --fs gemini-cli,codex-cli`).
|
|
76
|
+
"echo",
|
|
77
|
+
"fs",
|
|
78
|
+
// `wstack modeldiag test` booleans. Keep a following positional token from
|
|
79
|
+
// being consumed as the value of one of these switches.
|
|
80
|
+
"all-models",
|
|
81
|
+
"plan",
|
|
82
|
+
"json"
|
|
83
|
+
]);
|
|
84
|
+
function parseArgs(argv) {
|
|
85
|
+
const flags = {};
|
|
86
|
+
const positional = [];
|
|
87
|
+
for (let i = 0; i < argv.length; i++) {
|
|
88
|
+
const a = argv[i];
|
|
89
|
+
if (!a) continue;
|
|
90
|
+
if (a === "--") {
|
|
91
|
+
positional.push(...argv.slice(i + 1));
|
|
92
|
+
break;
|
|
93
|
+
}
|
|
94
|
+
if (a.startsWith("--")) {
|
|
95
|
+
const eq = a.indexOf("=");
|
|
96
|
+
if (eq !== -1) {
|
|
97
|
+
flags[a.slice(2, eq)] = a.slice(eq + 1);
|
|
98
|
+
continue;
|
|
99
|
+
}
|
|
100
|
+
const name = a.slice(2);
|
|
101
|
+
if (BOOLEAN_FLAGS.has(name)) {
|
|
102
|
+
flags[name] = true;
|
|
103
|
+
continue;
|
|
104
|
+
}
|
|
105
|
+
if (i + 1 < argv.length && !(argv[i + 1] ?? "").startsWith("-")) {
|
|
106
|
+
flags[name] = argv[++i] ?? "";
|
|
107
|
+
} else {
|
|
108
|
+
flags[name] = true;
|
|
109
|
+
}
|
|
110
|
+
} else if (a.startsWith("-") && a.length === 2) {
|
|
111
|
+
const short = a.slice(1);
|
|
112
|
+
const expand = { v: "verbose", y: "yes" };
|
|
113
|
+
flags[expand[short] ?? short] = true;
|
|
114
|
+
} else {
|
|
115
|
+
positional.push(a);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
normalizeSurfaceAliases(flags, positional);
|
|
119
|
+
return { flags, positional };
|
|
120
|
+
}
|
|
121
|
+
function normalizeSurfaceAliases(flags, positional) {
|
|
122
|
+
if (flags["simpleui"]) flags["webui"] = true;
|
|
123
|
+
const first = positional[0];
|
|
124
|
+
if (first === "simpleui") {
|
|
125
|
+
flags["simpleui"] = true;
|
|
126
|
+
flags["webui"] = true;
|
|
127
|
+
positional.splice(0, 1);
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
130
|
+
if (first === "webui" || first === "desktop") {
|
|
131
|
+
flags[first] = true;
|
|
132
|
+
positional.splice(0, 1);
|
|
133
|
+
return;
|
|
134
|
+
}
|
|
135
|
+
if (first === "hq" && (positional.length === 1 || positional[1] === "serve")) {
|
|
136
|
+
flags["hq"] = true;
|
|
137
|
+
positional.splice(0, positional[1] === "serve" ? 2 : 1);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
function parseAuthFlags(args) {
|
|
141
|
+
const out = { positional: [] };
|
|
142
|
+
for (let i = 0; i < args.length; i++) {
|
|
143
|
+
const a = args[i];
|
|
144
|
+
if (a === "--label") {
|
|
145
|
+
const v = args[++i];
|
|
146
|
+
if (v) out.label = v;
|
|
147
|
+
} else if (a === "--family") {
|
|
148
|
+
const v = args[++i];
|
|
149
|
+
if (v) out.family = v;
|
|
150
|
+
} else if (a === "--base-url") {
|
|
151
|
+
const v = args[++i];
|
|
152
|
+
if (v) out.baseUrl = v;
|
|
153
|
+
} else if (a === "--env") {
|
|
154
|
+
const v = args[++i];
|
|
155
|
+
if (v)
|
|
156
|
+
out.envVars = v.split(",").map((s) => s.trim()).filter(Boolean);
|
|
157
|
+
} else if (a && !a.startsWith("--")) {
|
|
158
|
+
out.positional.push(a);
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
return out;
|
|
162
|
+
}
|
|
163
|
+
function parseSpawnFlags(input) {
|
|
164
|
+
const opts = {};
|
|
165
|
+
let rest = input;
|
|
166
|
+
const consume = (re) => {
|
|
167
|
+
const m = rest.match(re);
|
|
168
|
+
if (m) {
|
|
169
|
+
rest = rest.slice(m[0].length).replace(/^\s+/, "");
|
|
170
|
+
return m;
|
|
171
|
+
}
|
|
172
|
+
return null;
|
|
173
|
+
};
|
|
174
|
+
while (rest.length > 0) {
|
|
175
|
+
let m;
|
|
176
|
+
m = consume(/^--provider=(\S+)\s*/);
|
|
177
|
+
if (m) opts.provider = m[1];
|
|
178
|
+
else {
|
|
179
|
+
m = consume(/^--model=(\S+)\s*/);
|
|
180
|
+
if (m) opts.model = m[1];
|
|
181
|
+
else {
|
|
182
|
+
m = consume(/^--name=("([^"]+)"|(\S+))\s*/);
|
|
183
|
+
if (m) opts.name = m[2] ?? m[3];
|
|
184
|
+
else {
|
|
185
|
+
m = consume(/^--tools=(\S+)\s*/);
|
|
186
|
+
if (m)
|
|
187
|
+
opts.tools = m[1]?.split(",").map((t) => t.trim()).filter(Boolean);
|
|
188
|
+
else {
|
|
189
|
+
m = consume(/^-p\s+(\S+)\s*/);
|
|
190
|
+
if (m) opts.provider = m[1];
|
|
191
|
+
else {
|
|
192
|
+
m = consume(/^-m\s+(\S+)\s*/);
|
|
193
|
+
if (m) opts.model = m[1];
|
|
194
|
+
else {
|
|
195
|
+
m = consume(/^-n\s+("([^"]+)"|(\S+))\s*/);
|
|
196
|
+
if (m) opts.name = m[2] ?? m[3];
|
|
197
|
+
else break;
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
return { description: rest.trim(), opts };
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
// src/auth-menu/local-presets.ts
|
|
209
|
+
import { projectLocalProviderPresets } from "@wrongstack/providers/definitions";
|
|
210
|
+
var LOCAL_LLM_PRESETS = projectLocalProviderPresets();
|
|
211
|
+
|
|
212
|
+
// src/picker.ts
|
|
213
|
+
import os from "node:os";
|
|
214
|
+
import { color as color3, expectDefined as expectDefined2, setOutputLineGuard as setOutputLineGuard2, setRawMode as setRawMode2, stripAnsi as stripAnsi2, writeOut as writeOut2 } from "@wrongstack/core/utils";
|
|
215
|
+
import { toErrorMessage } from "@wrongstack/core/utils";
|
|
216
|
+
|
|
217
|
+
// src/picker-key-state.ts
|
|
218
|
+
function applyPickerKey(state, chunk, matchCount) {
|
|
219
|
+
if (chunk === "\x1B[A") return { ...state, selected: Math.max(0, state.selected - 1) };
|
|
220
|
+
if (chunk === "\x1B[B")
|
|
221
|
+
return { ...state, selected: Math.min(Math.max(0, matchCount - 1), state.selected + 1) };
|
|
222
|
+
if (chunk === "\x1B") return { ...state, query: "", selected: 0, status: "typing" };
|
|
223
|
+
if (chunk.charCodeAt(0) === 27) return state;
|
|
224
|
+
let query = state.query;
|
|
225
|
+
let selected = state.selected;
|
|
226
|
+
const status = "typing";
|
|
227
|
+
for (const ch of chunk) {
|
|
228
|
+
if (ch === "\r" || ch === "\n") {
|
|
229
|
+
return { ...state, status: matchCount > 0 ? "submitted" : "typing" };
|
|
230
|
+
}
|
|
231
|
+
if (ch === "") return { ...state, status: "cancelled" };
|
|
232
|
+
if (ch === "") {
|
|
233
|
+
query = "";
|
|
234
|
+
selected = 0;
|
|
235
|
+
continue;
|
|
236
|
+
}
|
|
237
|
+
if (ch === "\x7F" || ch === "\b") {
|
|
238
|
+
query = query.slice(0, -1);
|
|
239
|
+
selected = 0;
|
|
240
|
+
continue;
|
|
241
|
+
}
|
|
242
|
+
if (ch >= " " && ch !== "\x7F") {
|
|
243
|
+
query += ch;
|
|
244
|
+
selected = 0;
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
return { query, selected, status };
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
// src/picker-model-picker.ts
|
|
251
|
+
import { color as color2, expectDefined, setOutputLineGuard, setRawMode, writeOut } from "@wrongstack/core/utils";
|
|
252
|
+
|
|
253
|
+
// src/picker-ui.ts
|
|
254
|
+
import { color, stripAnsi } from "@wrongstack/core/utils";
|
|
255
|
+
var theme = {
|
|
256
|
+
accent: color.amber,
|
|
257
|
+
chrome: color.gray,
|
|
258
|
+
cursor: (s) => color.amber(color.bold(s)),
|
|
259
|
+
ctx: color.cyan,
|
|
260
|
+
cost: color.green,
|
|
261
|
+
caps: color.magenta
|
|
262
|
+
};
|
|
263
|
+
var BOX = {
|
|
264
|
+
tl: "\u256D",
|
|
265
|
+
tr: "\u256E",
|
|
266
|
+
bl: "\u2570",
|
|
267
|
+
br: "\u256F",
|
|
268
|
+
h: "\u2500",
|
|
269
|
+
v: "\u2502"
|
|
270
|
+
};
|
|
271
|
+
var PICKER_MIN_WIDTH = 74;
|
|
272
|
+
var PICKER_MAX_WIDTH = 100;
|
|
273
|
+
function pickerWidth() {
|
|
274
|
+
const cols = process.stdout.columns;
|
|
275
|
+
if (typeof cols !== "number" || !Number.isFinite(cols) || cols <= 0) {
|
|
276
|
+
return PICKER_MIN_WIDTH;
|
|
277
|
+
}
|
|
278
|
+
return Math.max(PICKER_MIN_WIDTH, Math.min(PICKER_MAX_WIDTH, cols - 2));
|
|
279
|
+
}
|
|
280
|
+
function visibleWidth(s) {
|
|
281
|
+
return stripAnsi(s).length;
|
|
282
|
+
}
|
|
283
|
+
function padVisible(s, width) {
|
|
284
|
+
const w = visibleWidth(s);
|
|
285
|
+
if (w === width) return s;
|
|
286
|
+
if (w < width) return s + " ".repeat(width - w);
|
|
287
|
+
const plain = stripAnsi(s);
|
|
288
|
+
return `${plain.slice(0, Math.max(0, width - 1))}\u2026`;
|
|
289
|
+
}
|
|
290
|
+
function boxTop(title) {
|
|
291
|
+
const width = pickerWidth();
|
|
292
|
+
const label = ` ${title} `;
|
|
293
|
+
const pad = Math.max(0, width - visibleWidth(label) - 1);
|
|
294
|
+
return theme.chrome(
|
|
295
|
+
`${BOX.tl}${BOX.h}${theme.accent(color.bold(label))}${theme.chrome(BOX.h.repeat(pad))}${BOX.tr}`
|
|
296
|
+
);
|
|
297
|
+
}
|
|
298
|
+
function boxBottom() {
|
|
299
|
+
return theme.chrome(`${BOX.bl}${BOX.h.repeat(pickerWidth())}${BOX.br}`);
|
|
300
|
+
}
|
|
301
|
+
function boxRow(content) {
|
|
302
|
+
return `${theme.chrome(BOX.v)} ${padVisible(content, pickerWidth() - 2)} ${theme.chrome(BOX.v)}`;
|
|
303
|
+
}
|
|
304
|
+
function boxDivider() {
|
|
305
|
+
return theme.chrome(`${BOX.v}${BOX.h.repeat(pickerWidth())}${BOX.v}`);
|
|
306
|
+
}
|
|
307
|
+
function keyHints(pairs) {
|
|
308
|
+
return pairs.map(([k, label]) => `${theme.accent(k)} ${color.dim(label)}`).join(color.dim(" \xB7 "));
|
|
309
|
+
}
|
|
310
|
+
var CODEX_PROVIDER_ID = "openai-codex";
|
|
311
|
+
var CODEX_PICKER_HEADER = "Select Model and Effort";
|
|
312
|
+
var CODEX_LEGACY_NOTE = "Access legacy models by running `wstack -m <model_name>` or in your `config.json`.";
|
|
313
|
+
function codexPickerPreamble(provider) {
|
|
314
|
+
if (provider.id !== CODEX_PROVIDER_ID) return "";
|
|
315
|
+
return ` ${color.bold(CODEX_PICKER_HEADER)}
|
|
316
|
+
${color.dim(` ${CODEX_LEGACY_NOTE}`)}
|
|
317
|
+
|
|
318
|
+
`;
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
// src/picker-model-picker.ts
|
|
322
|
+
var LIVE_PICKER_MAX_VISIBLE = 15;
|
|
323
|
+
function filterModels(query, models) {
|
|
324
|
+
const q = query.trim().toLowerCase();
|
|
325
|
+
if (!q) return [...models];
|
|
326
|
+
return models.filter((m) => m.id.toLowerCase().includes(q) || m.name.toLowerCase().includes(q));
|
|
327
|
+
}
|
|
328
|
+
function renderLiveModelList(query, filtered, selectedIdx, header) {
|
|
329
|
+
const ordered = [...filtered].sort(
|
|
330
|
+
(a, b) => (b.release_date ?? "").localeCompare(a.release_date ?? "")
|
|
331
|
+
);
|
|
332
|
+
const visible = ordered.slice(0, LIVE_PICKER_MAX_VISIBLE);
|
|
333
|
+
const lines = [];
|
|
334
|
+
lines.push(boxTop("Select a model"));
|
|
335
|
+
lines.push(boxRow(color2.dim(header)));
|
|
336
|
+
const caret = query.length > 0 ? color2.dim("\u258F") : theme.cursor("\u258F");
|
|
337
|
+
lines.push(boxRow(`${theme.accent("\u276F")} ${color2.dim("Select model:")} ${query}${caret}`));
|
|
338
|
+
lines.push(boxDivider());
|
|
339
|
+
let flat = 0;
|
|
340
|
+
for (const m of visible) {
|
|
341
|
+
const selected = flat === selectedIdx;
|
|
342
|
+
const marker = selected ? theme.cursor("\u25B6") : " ";
|
|
343
|
+
const ctxRaw = m.limit?.context ? `${(m.limit.context / 1e3).toFixed(0)}k` : "?";
|
|
344
|
+
const ctx = theme.ctx(ctxRaw.padStart(6));
|
|
345
|
+
const costRaw = m.cost?.input !== void 0 ? `$${m.cost.input}/$${m.cost.output ?? "?"}` : "";
|
|
346
|
+
const cost = costRaw ? theme.cost(costRaw) : "";
|
|
347
|
+
const capTags = [];
|
|
348
|
+
if (m.tool_call) capTags.push("tools");
|
|
349
|
+
if (m.reasoning) capTags.push("reason");
|
|
350
|
+
if (m.modalities?.input?.includes("image")) capTags.push("vision");
|
|
351
|
+
const caps = capTags.map((c) => theme.caps(c)).join(color2.dim(" "));
|
|
352
|
+
const id = selected ? theme.accent(color2.bold(m.id)) : m.id;
|
|
353
|
+
lines.push(boxRow(`${marker} ${padVisible(id, 34)} ${ctx} ${padVisible(cost, 12)} ${caps}`));
|
|
354
|
+
flat++;
|
|
355
|
+
}
|
|
356
|
+
if (ordered.length > LIVE_PICKER_MAX_VISIBLE) {
|
|
357
|
+
lines.push(
|
|
358
|
+
boxRow(color2.dim(` \u2026 ${ordered.length - LIVE_PICKER_MAX_VISIBLE} more \u2014 type to filter`))
|
|
359
|
+
);
|
|
360
|
+
}
|
|
361
|
+
lines.push(boxDivider());
|
|
362
|
+
lines.push(
|
|
363
|
+
boxRow(
|
|
364
|
+
keyHints([
|
|
365
|
+
["\u2191\u2193", "move"],
|
|
366
|
+
["Enter", "select"],
|
|
367
|
+
["Esc", "clear"],
|
|
368
|
+
["Ctrl+C", "quit"]
|
|
369
|
+
])
|
|
370
|
+
)
|
|
371
|
+
);
|
|
372
|
+
lines.push(boxBottom());
|
|
373
|
+
return lines.join("\n");
|
|
374
|
+
}
|
|
375
|
+
async function runLiveModelPicker(provider, defaultModel) {
|
|
376
|
+
const stdin = process.stdin;
|
|
377
|
+
const out = process.stdout;
|
|
378
|
+
if (!stdin.isTTY || !out.isTTY) return void 0;
|
|
379
|
+
const header = `${provider.name} (${provider.id}) models:`;
|
|
380
|
+
const byNewest = (a, b) => (b.release_date ?? "").localeCompare(a.release_date ?? "");
|
|
381
|
+
const ranked = [...provider.models].sort(byNewest);
|
|
382
|
+
const defaultIdx = defaultModel !== void 0 ? ranked.findIndex((m) => m.id === defaultModel) : -1;
|
|
383
|
+
setOutputLineGuard(null);
|
|
384
|
+
let state = {
|
|
385
|
+
query: "",
|
|
386
|
+
selected: defaultIdx >= 0 ? defaultIdx : 0,
|
|
387
|
+
status: "typing"
|
|
388
|
+
};
|
|
389
|
+
const order = (filtered) => [...filtered].sort(byNewest);
|
|
390
|
+
let ordered = order(filterModels(state.query, provider.models));
|
|
391
|
+
const visibleCount = () => Math.min(ordered.length, LIVE_PICKER_MAX_VISIBLE);
|
|
392
|
+
const clamp = () => {
|
|
393
|
+
if (state.selected >= visibleCount()) state.selected = Math.max(0, visibleCount() - 1);
|
|
394
|
+
};
|
|
395
|
+
clamp();
|
|
396
|
+
const preamble = codexPickerPreamble(provider);
|
|
397
|
+
if (preamble) writeOut(preamble);
|
|
398
|
+
let frame = renderLiveModelList(state.query, ordered, state.selected, header);
|
|
399
|
+
writeOut(frame);
|
|
400
|
+
return new Promise((resolve) => {
|
|
401
|
+
const wasRaw = stdin.isRaw;
|
|
402
|
+
const wasPaused = stdin.isPaused();
|
|
403
|
+
setRawMode(stdin, true);
|
|
404
|
+
stdin.resume();
|
|
405
|
+
stdin.setEncoding("utf8");
|
|
406
|
+
const cleanup = () => {
|
|
407
|
+
stdin.off("data", onData);
|
|
408
|
+
setRawMode(stdin, wasRaw);
|
|
409
|
+
if (wasPaused) stdin.pause();
|
|
410
|
+
};
|
|
411
|
+
const repaint = () => {
|
|
412
|
+
const ups = (frame.match(/\n/g) ?? []).length;
|
|
413
|
+
writeOut(`\x1B[${ups}A\r\x1B[J`);
|
|
414
|
+
ordered = order(filterModels(state.query, provider.models));
|
|
415
|
+
clamp();
|
|
416
|
+
frame = renderLiveModelList(state.query, ordered, state.selected, header);
|
|
417
|
+
writeOut(frame);
|
|
418
|
+
};
|
|
419
|
+
const onData = (chunk) => {
|
|
420
|
+
ordered = order(filterModels(state.query, provider.models));
|
|
421
|
+
state = applyPickerKey(state, chunk, visibleCount());
|
|
422
|
+
ordered = order(filterModels(state.query, provider.models));
|
|
423
|
+
clamp();
|
|
424
|
+
if (state.status === "cancelled") {
|
|
425
|
+
cleanup();
|
|
426
|
+
writeOut("\n");
|
|
427
|
+
resolve(void 0);
|
|
428
|
+
return;
|
|
429
|
+
}
|
|
430
|
+
if (state.status === "submitted") {
|
|
431
|
+
if (ordered.length === 0) {
|
|
432
|
+
state = { ...state, status: "typing" };
|
|
433
|
+
repaint();
|
|
434
|
+
return;
|
|
435
|
+
}
|
|
436
|
+
const pick = ordered[state.selected] ?? expectDefined(ordered[0]);
|
|
437
|
+
cleanup();
|
|
438
|
+
writeOut("\n");
|
|
439
|
+
resolve(pick);
|
|
440
|
+
return;
|
|
441
|
+
}
|
|
442
|
+
repaint();
|
|
443
|
+
};
|
|
444
|
+
stdin.on("data", onData);
|
|
445
|
+
});
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
// src/picker.ts
|
|
449
|
+
function appendLocalPresetProviders(merged) {
|
|
450
|
+
const existing = new Set(merged.map((p) => p.id));
|
|
451
|
+
for (const preset of LOCAL_LLM_PRESETS) {
|
|
452
|
+
if (existing.has(preset.id)) continue;
|
|
453
|
+
merged.push({
|
|
454
|
+
id: preset.id,
|
|
455
|
+
name: preset.label,
|
|
456
|
+
family: "openai-compatible",
|
|
457
|
+
apiBase: preset.defaultBaseUrl,
|
|
458
|
+
// No env vars → with a loopback apiBase this reads as a keyless
|
|
459
|
+
// local gateway, so the picker offers it without a key.
|
|
460
|
+
envVars: [],
|
|
461
|
+
// No catalog models yet; OmniRoute/LM Studio/etc. auto-discover at
|
|
462
|
+
// boot or the user picks `m` to set a list. An empty list still
|
|
463
|
+
// lets the provider be chosen — pickModel surfaces the "no models
|
|
464
|
+
// listed" hint and the user can type an id directly.
|
|
465
|
+
models: []
|
|
466
|
+
});
|
|
467
|
+
}
|
|
468
|
+
return merged;
|
|
469
|
+
}
|
|
470
|
+
function filterProviders(query, providers) {
|
|
471
|
+
const q = query.trim().toLowerCase();
|
|
472
|
+
if (!q) return [...providers];
|
|
473
|
+
return providers.filter(
|
|
474
|
+
(p) => p.id.toLowerCase().includes(q) || p.name.toLowerCase().includes(q)
|
|
475
|
+
);
|
|
476
|
+
}
|
|
477
|
+
var PROVIDER_FAMILY_PREFERRED_ORDER = [
|
|
478
|
+
"anthropic",
|
|
479
|
+
"anthropic-oauth",
|
|
480
|
+
"openai",
|
|
481
|
+
"openai-codex",
|
|
482
|
+
"github-copilot",
|
|
483
|
+
"google",
|
|
484
|
+
"openai-compatible"
|
|
485
|
+
];
|
|
486
|
+
function orderProvidersForDisplay(filtered) {
|
|
487
|
+
const families = /* @__PURE__ */ new Map();
|
|
488
|
+
for (const p of filtered) {
|
|
489
|
+
const arr = families.get(p.family) ?? [];
|
|
490
|
+
arr.push(p);
|
|
491
|
+
families.set(p.family, arr);
|
|
492
|
+
}
|
|
493
|
+
const order = [
|
|
494
|
+
...PROVIDER_FAMILY_PREFERRED_ORDER.filter((f) => families.has(f)),
|
|
495
|
+
...[...families.keys()].filter((f) => !PROVIDER_FAMILY_PREFERRED_ORDER.includes(f))
|
|
496
|
+
];
|
|
497
|
+
const flat = [];
|
|
498
|
+
for (const fam of order) {
|
|
499
|
+
const arr = (families.get(fam) ?? []).slice().sort((a, b) => a.id.toLowerCase().localeCompare(b.id.toLowerCase()));
|
|
500
|
+
flat.push(...arr);
|
|
501
|
+
}
|
|
502
|
+
return flat;
|
|
503
|
+
}
|
|
504
|
+
function renderLiveProviderList(query, filtered, selectedIdx, savedSet) {
|
|
505
|
+
const ordered = orderProvidersForDisplay(filtered);
|
|
506
|
+
const scrollOffset = Math.max(0, selectedIdx - LIVE_PICKER_MAX_VISIBLE + 1);
|
|
507
|
+
const visible = ordered.slice(scrollOffset, scrollOffset + LIVE_PICKER_MAX_VISIBLE);
|
|
508
|
+
const lines = [];
|
|
509
|
+
lines.push(boxTop("Select a provider"));
|
|
510
|
+
const caret = query.length > 0 ? color3.dim("\u258F") : theme.cursor("\u258F");
|
|
511
|
+
lines.push(boxRow(`${theme.accent("\u276F")} ${color3.dim("Select provider:")} ${query}${caret}`));
|
|
512
|
+
lines.push(boxDivider());
|
|
513
|
+
if (scrollOffset > 0) {
|
|
514
|
+
lines.push(boxRow(color3.dim(` ${scrollOffset} more above \u2191`)));
|
|
515
|
+
}
|
|
516
|
+
let flat = 0;
|
|
517
|
+
let lastFamily = "";
|
|
518
|
+
for (const p of visible) {
|
|
519
|
+
if (p.family !== lastFamily) {
|
|
520
|
+
lines.push(boxRow(`${theme.accent("\xB7")} ${color3.dim(p.family.toUpperCase())}`));
|
|
521
|
+
lastFamily = p.family;
|
|
522
|
+
}
|
|
523
|
+
const selected = flat === selectedIdx - scrollOffset;
|
|
524
|
+
const sel = selected ? theme.cursor("\u25B6") : " ";
|
|
525
|
+
let marker;
|
|
526
|
+
if (savedSet) {
|
|
527
|
+
const mark = savedSet.has(p.id) ? color3.cyan("\u25C9") : color3.dim("\u25CB");
|
|
528
|
+
marker = `${sel} ${mark}`;
|
|
529
|
+
} else {
|
|
530
|
+
marker = `${sel}`;
|
|
531
|
+
}
|
|
532
|
+
const id = selected ? theme.accent(color3.bold(p.id)) : p.id;
|
|
533
|
+
const name = selected ? p.name : color3.dim(p.name);
|
|
534
|
+
lines.push(boxRow(`${marker} ${padVisible(id, 24)} ${name}`));
|
|
535
|
+
flat++;
|
|
536
|
+
}
|
|
537
|
+
if (scrollOffset + LIVE_PICKER_MAX_VISIBLE < ordered.length) {
|
|
538
|
+
lines.push(
|
|
539
|
+
boxRow(
|
|
540
|
+
color3.dim(` ${ordered.length - scrollOffset - LIVE_PICKER_MAX_VISIBLE} more below \u2193`)
|
|
541
|
+
)
|
|
542
|
+
);
|
|
543
|
+
}
|
|
544
|
+
lines.push(boxDivider());
|
|
545
|
+
lines.push(
|
|
546
|
+
boxRow(
|
|
547
|
+
keyHints([
|
|
548
|
+
["\u2191\u2193", "scroll"],
|
|
549
|
+
["Enter", "select"],
|
|
550
|
+
["Esc", "clear"],
|
|
551
|
+
["Ctrl+C", "quit"]
|
|
552
|
+
])
|
|
553
|
+
)
|
|
554
|
+
);
|
|
555
|
+
lines.push(boxBottom());
|
|
556
|
+
return lines.join("\n");
|
|
557
|
+
}
|
|
558
|
+
async function saveToGlobalConfig(configPath, provider, model, homeFn = () => process.env.HOME ?? os.homedir()) {
|
|
559
|
+
try {
|
|
560
|
+
const { atomicWrite } = await import("@wrongstack/core/utils");
|
|
561
|
+
const fs = await import("node:fs/promises");
|
|
562
|
+
let existing = {};
|
|
563
|
+
try {
|
|
564
|
+
const raw = await fs.readFile(configPath, "utf8");
|
|
565
|
+
existing = JSON.parse(raw);
|
|
566
|
+
} catch {
|
|
567
|
+
}
|
|
568
|
+
const oldCfg = { ...existing };
|
|
569
|
+
existing.provider = provider;
|
|
570
|
+
existing.model = model;
|
|
571
|
+
try {
|
|
572
|
+
await backupCurrent(homeFn, configPath);
|
|
573
|
+
} catch (err) {
|
|
574
|
+
console.warn(
|
|
575
|
+
JSON.stringify({
|
|
576
|
+
level: "warn",
|
|
577
|
+
event: "picker.backup_failed",
|
|
578
|
+
message: toErrorMessage(err),
|
|
579
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
580
|
+
})
|
|
581
|
+
);
|
|
582
|
+
}
|
|
583
|
+
await atomicWrite(configPath, JSON.stringify(existing, null, 2), { mode: 384 });
|
|
584
|
+
try {
|
|
585
|
+
await appendHistory(
|
|
586
|
+
oldCfg,
|
|
587
|
+
existing,
|
|
588
|
+
`Provider/model changed: ${oldCfg.provider ?? "(none)"} \u2192 ${provider}, ${oldCfg.model ?? "(none)"} \u2192 ${model}`,
|
|
589
|
+
homeFn,
|
|
590
|
+
configPath
|
|
591
|
+
);
|
|
592
|
+
} catch {
|
|
593
|
+
}
|
|
594
|
+
return true;
|
|
595
|
+
} catch (err) {
|
|
596
|
+
console.warn(
|
|
597
|
+
JSON.stringify({
|
|
598
|
+
level: "warn",
|
|
599
|
+
event: "picker.save_failed",
|
|
600
|
+
message: toErrorMessage(err),
|
|
601
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
602
|
+
})
|
|
603
|
+
);
|
|
604
|
+
return false;
|
|
605
|
+
}
|
|
606
|
+
}
|
|
607
|
+
var QUERY_MARKER = "Select provider:";
|
|
608
|
+
function cursorToQuery(frame, query) {
|
|
609
|
+
const rows = frame.split("\n");
|
|
610
|
+
const lastIdx = rows.length - 1;
|
|
611
|
+
const queryIdx = rows.findIndex((r) => r.includes(QUERY_MARKER));
|
|
612
|
+
if (queryIdx < 0) return;
|
|
613
|
+
const up = lastIdx - queryIdx;
|
|
614
|
+
const queryLine = rows[queryIdx] ?? "";
|
|
615
|
+
const plain = stripAnsi2(queryLine);
|
|
616
|
+
const markerAt = plain.indexOf(QUERY_MARKER);
|
|
617
|
+
const col = markerAt + QUERY_MARKER.length + 1 + query.length + 1;
|
|
618
|
+
if (up > 0) writeOut2(`\x1B[${up}A`);
|
|
619
|
+
writeOut2(`\x1B[${col}G`);
|
|
620
|
+
}
|
|
621
|
+
async function runLiveProviderPicker(displayList, savedSet) {
|
|
622
|
+
const stdin = process.stdin;
|
|
623
|
+
const out = process.stdout;
|
|
624
|
+
if (!stdin.isTTY || !out.isTTY) return void 0;
|
|
625
|
+
setOutputLineGuard2(null);
|
|
626
|
+
let state = { query: "", selected: 0, status: "typing" };
|
|
627
|
+
let ordered = orderProvidersForDisplay(filterProviders(state.query, displayList));
|
|
628
|
+
const visibleCount = () => ordered.length;
|
|
629
|
+
const clamp = () => {
|
|
630
|
+
if (state.selected >= visibleCount()) state.selected = Math.max(0, visibleCount() - 1);
|
|
631
|
+
};
|
|
632
|
+
clamp();
|
|
633
|
+
let frame = renderLiveProviderList(state.query, ordered, state.selected, savedSet);
|
|
634
|
+
writeOut2(frame);
|
|
635
|
+
writeOut2("\x1B7");
|
|
636
|
+
cursorToQuery(frame, state.query);
|
|
637
|
+
return new Promise((resolve) => {
|
|
638
|
+
const wasRaw = stdin.isRaw;
|
|
639
|
+
const wasPaused = stdin.isPaused();
|
|
640
|
+
setRawMode2(stdin, true);
|
|
641
|
+
stdin.resume();
|
|
642
|
+
stdin.setEncoding("utf8");
|
|
643
|
+
const cleanup = () => {
|
|
644
|
+
stdin.off("data", onData);
|
|
645
|
+
setRawMode2(stdin, wasRaw);
|
|
646
|
+
if (wasPaused) stdin.pause();
|
|
647
|
+
};
|
|
648
|
+
const repaint = () => {
|
|
649
|
+
writeOut2("\x1B8");
|
|
650
|
+
const ups = (frame.match(/\n/g) ?? []).length;
|
|
651
|
+
writeOut2(`\x1B[${ups}A\r\x1B[J`);
|
|
652
|
+
ordered = orderProvidersForDisplay(filterProviders(state.query, displayList));
|
|
653
|
+
clamp();
|
|
654
|
+
frame = renderLiveProviderList(state.query, ordered, state.selected, savedSet);
|
|
655
|
+
writeOut2(frame);
|
|
656
|
+
writeOut2("\x1B7");
|
|
657
|
+
cursorToQuery(frame, state.query);
|
|
658
|
+
};
|
|
659
|
+
const onData = (chunk) => {
|
|
660
|
+
ordered = orderProvidersForDisplay(filterProviders(state.query, displayList));
|
|
661
|
+
state = applyPickerKey(state, chunk, visibleCount());
|
|
662
|
+
ordered = orderProvidersForDisplay(filterProviders(state.query, displayList));
|
|
663
|
+
clamp();
|
|
664
|
+
if (state.status === "cancelled") {
|
|
665
|
+
cleanup();
|
|
666
|
+
writeOut2("\n");
|
|
667
|
+
resolve(void 0);
|
|
668
|
+
return;
|
|
669
|
+
}
|
|
670
|
+
if (state.status === "submitted") {
|
|
671
|
+
if (ordered.length === 0) {
|
|
672
|
+
state = { ...state, status: "typing" };
|
|
673
|
+
repaint();
|
|
674
|
+
return;
|
|
675
|
+
}
|
|
676
|
+
const pick = ordered[state.selected] ?? ordered[0];
|
|
677
|
+
cleanup();
|
|
678
|
+
writeOut2("\n");
|
|
679
|
+
resolve(pick);
|
|
680
|
+
return;
|
|
681
|
+
}
|
|
682
|
+
repaint();
|
|
683
|
+
};
|
|
684
|
+
stdin.on("data", onData);
|
|
685
|
+
});
|
|
686
|
+
}
|
|
687
|
+
async function runPicker(deps) {
|
|
688
|
+
const { modelsRegistry, renderer, reader, config, defaultProvider, defaultModel } = deps;
|
|
689
|
+
renderer.write(
|
|
690
|
+
`
|
|
691
|
+
${theme.accent(color3.bold("\u258C WrongStack"))} ${color3.dim("Provider & Model Selection")}
|
|
692
|
+
`
|
|
693
|
+
);
|
|
694
|
+
renderer.write(color3.dim(`${theme.chrome("\xB7")} Loading provider catalog\u2026
|
|
695
|
+
`));
|
|
696
|
+
let providers;
|
|
697
|
+
try {
|
|
698
|
+
providers = await modelsRegistry.listProviders();
|
|
699
|
+
} catch {
|
|
700
|
+
renderer.writeError(
|
|
701
|
+
"Failed to load provider catalog. Pass --provider and --model to skip the picker."
|
|
702
|
+
);
|
|
703
|
+
return void 0;
|
|
704
|
+
}
|
|
705
|
+
const supported = providers.filter((p) => p.family !== "unsupported");
|
|
706
|
+
const catalogById = new Map(supported.map((p) => [p.id, p]));
|
|
707
|
+
const overlay = config?.providers ?? {};
|
|
708
|
+
const seen = /* @__PURE__ */ new Set();
|
|
709
|
+
const merged = [];
|
|
710
|
+
for (const p of supported) {
|
|
711
|
+
const cfg = overlay[p.id];
|
|
712
|
+
seen.add(p.id);
|
|
713
|
+
if (cfg) {
|
|
714
|
+
merged.push({
|
|
715
|
+
...p,
|
|
716
|
+
family: cfg.family ?? p.family,
|
|
717
|
+
apiBase: cfg.baseUrl ?? p.apiBase,
|
|
718
|
+
envVars: cfg.envVars && cfg.envVars.length > 0 ? cfg.envVars : p.envVars,
|
|
719
|
+
// When the user has saved an explicit model list, it wins — they
|
|
720
|
+
// know which models their endpoint actually serves (e.g. LM
|
|
721
|
+
// Studio, vLLM, or a proxy with custom model ids). Otherwise the
|
|
722
|
+
// catalog list keeps providing suggestions.
|
|
723
|
+
models: visibleModelIds(
|
|
724
|
+
p.id,
|
|
725
|
+
config ?? { providers: {} },
|
|
726
|
+
p.models.map((m) => m.id),
|
|
727
|
+
cfg
|
|
728
|
+
).map((m) => p.models.find((pm) => pm.id === m) ?? { id: m, name: m })
|
|
729
|
+
});
|
|
730
|
+
} else {
|
|
731
|
+
merged.push(p);
|
|
732
|
+
}
|
|
733
|
+
}
|
|
734
|
+
for (const [id, cfg] of Object.entries(overlay)) {
|
|
735
|
+
if (seen.has(id)) continue;
|
|
736
|
+
if (!cfg?.family || cfg.family === "unsupported") continue;
|
|
737
|
+
const catalogType = cfg.type && cfg.type !== id ? cfg.type : void 0;
|
|
738
|
+
const inherited = catalogType ? catalogById.get(catalogType) : void 0;
|
|
739
|
+
merged.push({
|
|
740
|
+
id,
|
|
741
|
+
name: inherited ? `${inherited.name} ${color3.dim("(alias)")}` : id,
|
|
742
|
+
family: cfg.family,
|
|
743
|
+
apiBase: cfg.baseUrl ?? inherited?.apiBase,
|
|
744
|
+
envVars: cfg.envVars ?? inherited?.envVars ?? [],
|
|
745
|
+
models: visibleModelIds(
|
|
746
|
+
id,
|
|
747
|
+
config ?? { providers: {} },
|
|
748
|
+
(inherited?.models ?? []).map((m) => m.id),
|
|
749
|
+
cfg
|
|
750
|
+
).map((m) => inherited?.models.find((pm) => pm.id === m) ?? { id: m, name: m }),
|
|
751
|
+
npm: inherited?.npm
|
|
752
|
+
});
|
|
753
|
+
}
|
|
754
|
+
const keyed = merged.filter((p) => hasApiKey(p, config) || isKeylessLocalProvider(p));
|
|
755
|
+
let displayList = keyed;
|
|
756
|
+
let showingFallback = false;
|
|
757
|
+
if (keyed.length === 0) {
|
|
758
|
+
displayList = merged;
|
|
759
|
+
showingFallback = merged.length > 0;
|
|
760
|
+
}
|
|
761
|
+
appendLocalPresetProviders(displayList);
|
|
762
|
+
if (displayList.length === 0) {
|
|
763
|
+
renderer.writeError("No supported providers found in catalog.");
|
|
764
|
+
return void 0;
|
|
765
|
+
}
|
|
766
|
+
if (process.stdin.isTTY) {
|
|
767
|
+
const chosen2 = await runLiveProviderPicker(displayList);
|
|
768
|
+
if (!chosen2) {
|
|
769
|
+
renderer.write(color3.dim("Cancelled.\n"));
|
|
770
|
+
return void 0;
|
|
771
|
+
}
|
|
772
|
+
return pickModel(chosen2, modelsRegistry, renderer, reader, defaultModel);
|
|
773
|
+
}
|
|
774
|
+
const families = /* @__PURE__ */ new Map();
|
|
775
|
+
for (const p of displayList) {
|
|
776
|
+
const list = families.get(p.family) ?? [];
|
|
777
|
+
list.push(p);
|
|
778
|
+
families.set(p.family, list);
|
|
779
|
+
}
|
|
780
|
+
const ordered = [];
|
|
781
|
+
const preferredOrder = [
|
|
782
|
+
"anthropic",
|
|
783
|
+
"anthropic-oauth",
|
|
784
|
+
"openai",
|
|
785
|
+
"openai-codex",
|
|
786
|
+
"github-copilot",
|
|
787
|
+
"google",
|
|
788
|
+
"openai-compatible"
|
|
789
|
+
];
|
|
790
|
+
const familyOrder = [
|
|
791
|
+
...preferredOrder.filter((f) => families.has(f)),
|
|
792
|
+
...[...families.keys()].filter((f) => !preferredOrder.includes(f))
|
|
793
|
+
];
|
|
794
|
+
let idx = 1;
|
|
795
|
+
let defaultIdx;
|
|
796
|
+
renderer.write("\n");
|
|
797
|
+
renderer.write(`${boxTop("Select a provider")}
|
|
798
|
+
`);
|
|
799
|
+
for (const fam of familyOrder) {
|
|
800
|
+
const list = [...families.get(fam) ?? []].sort(
|
|
801
|
+
(a, b) => a.id.toLowerCase().localeCompare(b.id.toLowerCase())
|
|
802
|
+
);
|
|
803
|
+
if (!list || list.length === 0) continue;
|
|
804
|
+
renderer.write(`${boxRow(`${theme.accent("\xB7")} ${color3.dim(fam.toUpperCase())}`)}
|
|
805
|
+
`);
|
|
806
|
+
for (const p of list) {
|
|
807
|
+
const envFound = p.envVars.some((v) => !!process.env[v]);
|
|
808
|
+
const entry = config?.providers?.[p.id];
|
|
809
|
+
const configKey = typeof entry?.apiKey === "string" && entry.apiKey.length > 0 || Array.isArray(entry?.apiKeys) && entry?.apiKeys?.some((k) => k?.apiKey);
|
|
810
|
+
const marker = envFound ? color3.green("\u25CF") : configKey ? color3.cyan("\u25C9") : color3.dim("\u25CB");
|
|
811
|
+
const isDefault = p.id === defaultProvider;
|
|
812
|
+
if (isDefault) defaultIdx = idx;
|
|
813
|
+
const idLabel = isDefault ? theme.accent(color3.bold(p.id)) : p.id;
|
|
814
|
+
const suffix = isDefault ? color3.dim(" (default)") : "";
|
|
815
|
+
renderer.write(
|
|
816
|
+
`${boxRow(`${color3.dim(`${idx}.`.padStart(4))} ${marker} ${padVisible(idLabel, 22)} ${color3.dim(p.name)}${suffix}`)}
|
|
817
|
+
`
|
|
818
|
+
);
|
|
819
|
+
ordered.push({ provider: p, index: idx });
|
|
820
|
+
idx++;
|
|
821
|
+
}
|
|
822
|
+
}
|
|
823
|
+
renderer.write(`${boxDivider()}
|
|
824
|
+
`);
|
|
825
|
+
if (showingFallback) {
|
|
826
|
+
renderer.write(
|
|
827
|
+
`${boxRow(`${color3.yellow("\u26A0 No API keys detected.")} ${color3.dim("Run `wstack auth <provider>` after picking.")}`)}
|
|
828
|
+
`
|
|
829
|
+
);
|
|
830
|
+
} else {
|
|
831
|
+
renderer.write(`${boxRow(color3.dim("\u25CF env key \u25C9 stored in config \u25CB no key"))}
|
|
832
|
+
`);
|
|
833
|
+
}
|
|
834
|
+
renderer.write(`${boxBottom()}
|
|
835
|
+
`);
|
|
836
|
+
const defaultHint = defaultIdx !== void 0 && defaultProvider ? ` ${color3.dim(`[Enter = ${defaultProvider}]`)}` : "";
|
|
837
|
+
const providerAnswer = (await reader.readLine(
|
|
838
|
+
`
|
|
839
|
+
${color3.amber("?")} Select provider (1-${ordered.length})${defaultHint} ${color3.dim("[q to quit]")}: `
|
|
840
|
+
)).trim();
|
|
841
|
+
if (providerAnswer.toLowerCase() === "q") {
|
|
842
|
+
renderer.write(color3.dim("Cancelled.\n"));
|
|
843
|
+
return void 0;
|
|
844
|
+
}
|
|
845
|
+
if (!providerAnswer) {
|
|
846
|
+
if (defaultIdx !== void 0) {
|
|
847
|
+
const def = ordered[defaultIdx - 1];
|
|
848
|
+
if (def) return pickModel(def.provider, modelsRegistry, renderer, reader, defaultModel);
|
|
849
|
+
}
|
|
850
|
+
renderer.write(color3.dim("Cancelled.\n"));
|
|
851
|
+
return void 0;
|
|
852
|
+
}
|
|
853
|
+
const providerIdx = Number.parseInt(providerAnswer, 10);
|
|
854
|
+
if (Number.isNaN(providerIdx) || providerIdx < 1 || providerIdx > ordered.length) {
|
|
855
|
+
const byId = ordered.find((o) => o.provider.id.toLowerCase() === providerAnswer.toLowerCase());
|
|
856
|
+
if (!byId) {
|
|
857
|
+
renderer.writeError(`Invalid selection: "${providerAnswer}"`);
|
|
858
|
+
return void 0;
|
|
859
|
+
}
|
|
860
|
+
return pickModel(byId.provider, modelsRegistry, renderer, reader, defaultModel);
|
|
861
|
+
}
|
|
862
|
+
const chosen = ordered[providerIdx - 1];
|
|
863
|
+
if (!chosen) return void 0;
|
|
864
|
+
const modelHint = chosen.provider.id === defaultProvider ? defaultModel : void 0;
|
|
865
|
+
return pickModel(chosen.provider, modelsRegistry, renderer, reader, modelHint);
|
|
866
|
+
}
|
|
867
|
+
async function pickModel(provider, registry, renderer, reader, defaultModel) {
|
|
868
|
+
renderer.write(`
|
|
869
|
+
${boxTop("Select a model")}
|
|
870
|
+
`);
|
|
871
|
+
renderer.write(
|
|
872
|
+
`${boxRow(`${color3.bold(provider.name)} ${color3.dim(`(${provider.id})`)} models:`)}
|
|
873
|
+
`
|
|
874
|
+
);
|
|
875
|
+
renderer.write(`${boxBottom()}
|
|
876
|
+
`);
|
|
877
|
+
const codexBlock = codexPickerPreamble(provider);
|
|
878
|
+
if (codexBlock) renderer.write(codexBlock);
|
|
879
|
+
const models = [...provider.models].sort(
|
|
880
|
+
(a, b) => (b.release_date ?? "").localeCompare(a.release_date ?? "")
|
|
881
|
+
);
|
|
882
|
+
if (models.length === 0) {
|
|
883
|
+
renderer.write(
|
|
884
|
+
color3.dim(
|
|
885
|
+
" No models listed yet for this provider \u2014 type a model id to use it (local servers auto-discover models at launch).\n"
|
|
886
|
+
)
|
|
887
|
+
);
|
|
888
|
+
const typed = (await reader.readLine(`
|
|
889
|
+
${color3.amber("?")} Model id ${color3.dim("(or Enter to cancel)")}: `)).trim();
|
|
890
|
+
if (!typed) {
|
|
891
|
+
renderer.write(color3.dim("Cancelled.\n"));
|
|
892
|
+
return void 0;
|
|
893
|
+
}
|
|
894
|
+
renderer.write(`
|
|
895
|
+
${color3.green("\u2713")} ${color3.bold(provider.id)} / ${color3.bold(typed)}
|
|
896
|
+
|
|
897
|
+
`);
|
|
898
|
+
return { provider: provider.id, model: typed };
|
|
899
|
+
}
|
|
900
|
+
if (process.stdin.isTTY) {
|
|
901
|
+
const chosen = await runLiveModelPicker(provider, defaultModel);
|
|
902
|
+
if (!chosen) {
|
|
903
|
+
renderer.write(color3.dim("Cancelled.\n"));
|
|
904
|
+
return void 0;
|
|
905
|
+
}
|
|
906
|
+
renderer.write(
|
|
907
|
+
`
|
|
908
|
+
${color3.green("\u2713")} ${color3.bold(provider.id)} / ${color3.bold(chosen.id)}
|
|
909
|
+
|
|
910
|
+
`
|
|
911
|
+
);
|
|
912
|
+
return { provider: provider.id, model: chosen.id };
|
|
913
|
+
}
|
|
914
|
+
const defaultIdxInModels = defaultModel !== void 0 ? models.findIndex((m) => m.id === defaultModel) : -1;
|
|
915
|
+
const pageSize = 30;
|
|
916
|
+
let offset = 0;
|
|
917
|
+
while (offset < models.length) {
|
|
918
|
+
const page = models.slice(offset, offset + pageSize);
|
|
919
|
+
const pageFrom = offset + 1;
|
|
920
|
+
const pageTo = Math.min(offset + page.length, models.length);
|
|
921
|
+
renderer.write(`${boxTop(`Models ${pageFrom}\u2013${pageTo} of ${models.length}`)}
|
|
922
|
+
`);
|
|
923
|
+
for (let i = 0; i < page.length; i++) {
|
|
924
|
+
const m = expectDefined2(page[i]);
|
|
925
|
+
const num = offset + i + 1;
|
|
926
|
+
const ctxRaw = m.limit?.context ? `${(m.limit.context / 1e3).toFixed(0)}k` : "?";
|
|
927
|
+
const ctx = theme.ctx(ctxRaw.padStart(6));
|
|
928
|
+
const cost = m.cost?.input !== void 0 ? `$${m.cost.input}/$${m.cost.output ?? "?"}` : "";
|
|
929
|
+
const costCol = cost ? theme.cost(cost) : "";
|
|
930
|
+
const capTags = [];
|
|
931
|
+
if (m.tool_call) capTags.push("tools");
|
|
932
|
+
if (m.reasoning) capTags.push("reason");
|
|
933
|
+
if (m.modalities?.input?.includes("image")) capTags.push("vision");
|
|
934
|
+
const capStr = capTags.map((c) => theme.caps(c)).join(color3.dim(" "));
|
|
935
|
+
const isDefault = m.id === defaultModel;
|
|
936
|
+
const idLabel = isDefault ? theme.accent(color3.bold(m.id)) : m.id;
|
|
937
|
+
const suffix = isDefault ? color3.dim(" (default)") : "";
|
|
938
|
+
const num5 = color3.dim(`${num}.`.padStart(5));
|
|
939
|
+
renderer.write(
|
|
940
|
+
`${boxRow(`${num5} ${padVisible(idLabel, 34)} ${ctx} ${padVisible(costCol, 11)} ${capStr}${suffix}`)}
|
|
941
|
+
`
|
|
942
|
+
);
|
|
943
|
+
}
|
|
944
|
+
renderer.write(`${boxBottom()}
|
|
945
|
+
`);
|
|
946
|
+
offset += pageSize;
|
|
947
|
+
if (offset < models.length) {
|
|
948
|
+
const more = (await reader.readLine(
|
|
949
|
+
`
|
|
950
|
+
${color3.amber("?")} Showing ${Math.min(offset, models.length)}/${models.length} \u2014 Enter number, ${color3.dim("Enter")} for more, or ${color3.dim("q")} to quit: `
|
|
951
|
+
)).trim();
|
|
952
|
+
if (more.toLowerCase() === "q") {
|
|
953
|
+
renderer.write(color3.dim("Cancelled.\n"));
|
|
954
|
+
return void 0;
|
|
955
|
+
}
|
|
956
|
+
if (!more) continue;
|
|
957
|
+
return resolveModelSelection(more, models, provider, registry, renderer, reader);
|
|
958
|
+
}
|
|
959
|
+
}
|
|
960
|
+
const defaultHint = defaultIdxInModels >= 0 && defaultModel ? ` ${color3.dim(`[Enter = ${defaultModel}]`)}` : "";
|
|
961
|
+
const answer = (await reader.readLine(
|
|
962
|
+
`
|
|
963
|
+
${color3.amber("?")} Select model (1-${models.length})${defaultHint} ${color3.dim("[q to quit]")}: `
|
|
964
|
+
)).trim();
|
|
965
|
+
if (answer.toLowerCase() === "q") {
|
|
966
|
+
renderer.write(color3.dim("Cancelled.\n"));
|
|
967
|
+
return void 0;
|
|
968
|
+
}
|
|
969
|
+
if (!answer) {
|
|
970
|
+
if (defaultIdxInModels >= 0 && defaultModel) {
|
|
971
|
+
renderer.write(
|
|
972
|
+
`
|
|
973
|
+
${color3.green("\u2713")} ${color3.bold(provider.id)} / ${color3.bold(defaultModel)}
|
|
974
|
+
|
|
975
|
+
`
|
|
976
|
+
);
|
|
977
|
+
return { provider: provider.id, model: defaultModel };
|
|
978
|
+
}
|
|
979
|
+
renderer.write(color3.dim("Cancelled.\n"));
|
|
980
|
+
return void 0;
|
|
981
|
+
}
|
|
982
|
+
return resolveModelSelection(answer, models, provider, registry, renderer, reader);
|
|
983
|
+
}
|
|
984
|
+
async function resolveModelSelection(answer, models, provider, _registry, renderer, _reader) {
|
|
985
|
+
const idx = Number.parseInt(answer, 10);
|
|
986
|
+
let modelId;
|
|
987
|
+
if (!Number.isNaN(idx) && idx >= 1 && idx <= models.length) {
|
|
988
|
+
modelId = models[idx - 1]?.id;
|
|
989
|
+
} else {
|
|
990
|
+
const lower = answer.toLowerCase();
|
|
991
|
+
const match = models.find((m) => m.id.toLowerCase() === lower);
|
|
992
|
+
if (match) {
|
|
993
|
+
modelId = match.id;
|
|
994
|
+
} else {
|
|
995
|
+
const partial = models.filter((m) => m.id.toLowerCase().includes(lower));
|
|
996
|
+
if (partial.length === 1) {
|
|
997
|
+
modelId = partial[0]?.id;
|
|
998
|
+
} else if (partial.length > 1) {
|
|
999
|
+
renderer.writeError(`"${answer}" matches multiple models. Be more specific.`);
|
|
1000
|
+
return void 0;
|
|
1001
|
+
}
|
|
1002
|
+
}
|
|
1003
|
+
}
|
|
1004
|
+
if (!modelId) {
|
|
1005
|
+
modelId = answer;
|
|
1006
|
+
}
|
|
1007
|
+
renderer.write(`
|
|
1008
|
+
${color3.green("\u2713")} ${color3.bold(provider.id)} / ${color3.bold(modelId)}
|
|
1009
|
+
|
|
1010
|
+
`);
|
|
1011
|
+
return { provider: provider.id, model: modelId };
|
|
1012
|
+
}
|
|
1013
|
+
|
|
1014
|
+
export {
|
|
1015
|
+
parseArgs,
|
|
1016
|
+
parseAuthFlags,
|
|
1017
|
+
parseSpawnFlags,
|
|
1018
|
+
LOCAL_LLM_PRESETS,
|
|
1019
|
+
saveToGlobalConfig,
|
|
1020
|
+
runLiveProviderPicker,
|
|
1021
|
+
runPicker
|
|
1022
|
+
};
|
|
1023
|
+
//# sourceMappingURL=chunk-JBSQ7ONN.js.map
|