Disable expert mode in TUI
ober
a1eccf0e068094904a98b56ffdceb38c4b621303
--- a/docs/cli.md +++ b/docs/cli.md @@ -25,7 +25,7 @@ Parsed before any subcommand. | `--tui` | — | Launch the terminal UI. | | `--no-tui` | — | Force the line-mode REPL (the default). | | `--no-mcp` | — | Skip MCP server initialization. | -| `--no-expert` | — | Disable configured expert escalation for this process. | +| `--no-expert` | — | Disable configured expert escalation for this process. With the binary's default no-prompt launch, this still starts the TUI unless `--no-tui` is also passed. | | `--repl-port` | `N` | Start a debug Scheme REPL on `localhost:N`. | | `--verbose` | — | Log TUI events to `~/jcode.log`. | | `--trace` | `FILE` | Trace everything — full HTTP (keys redacted), tool args/results, logs. Implies `--debug`. Also honours `$JCODE_TRACE`. | @@ -125,6 +125,14 @@ Available in the REPL and TUI. |---|---| | `/themes` | List TUI color themes. | | `/theme [name]` | Cycle the TUI theme, or switch to a named theme. | +| `/expert off\|on\|status` | Disable, re-enable, or inspect expert escalation for the current TUI session. | +| `/no-expert` | Disable expert escalation for the current TUI session. | + +### Expert escalation + +| Command | Effect | +|---|---| +| `/expert <prompt>` | Route one prompt to the configured expert model. | ### Tools, skills & extensions --- a/docs/escalation.md +++ b/docs/escalation.md @@ -157,8 +157,10 @@ The expert response replaces the primary response. If the expert call fails, `jcode` falls back to the primary response instead of dropping a usable answer. For provider evaluation runs where the primary model must be the only model -called, pass `--no-expert` or set `JCODE_NO_EXPERT=1`. This disables both the -explicit `<expert/>` route and automatic escalation for that process. +called, pass `--no-expert` or set `JCODE_NO_EXPERT=1`. In the TUI, you can also +run `/expert off` or `/no-expert` for the current session, then `/expert on` to +re-enable it unless `JCODE_NO_EXPERT` is set. This disables both the explicit +`<expert/>` route and automatic escalation for that process or session. ## Provider availability --- a/docs/tui.md +++ b/docs/tui.md @@ -68,6 +68,13 @@ rendering, live diffs, themes, and a stats sidebar. | `Ctrl-C` | Cancel / clear the input | | `Ctrl-D` | Quit (on empty input) | +## Expert Escalation + +Start with `jcode --no-expert` to launch the TUI with expert escalation +disabled. Inside the TUI, use `/expert off` or `/no-expert` to disable it for +the current session, `/expert on` to re-enable it, and `/expert status` to show +the current state. + ## Themes The default theme is **opencode-dark**, a port of OpenCode's warm neutral --- a/main-binary.ss +++ b/main-binary.ss @@ -13,7 +13,7 @@ ((null? args) #f) ;; -p starts the one-shot prompt: everything after is positional. ((equal? (car args) "-p") (pair? (cdr args))) - ((member (car args) '("--help" "-h" "--version" "-v" "--debug" "-d" "--tui" "--no-tui" "--verbose" "--repl" "--no-mcp")) + ((member (car args) '("--help" "-h" "--version" "-v" "--debug" "-d" "--tui" "--no-tui" "--verbose" "--repl" "--no-mcp" "--no-expert")) (has-positional-args? (cdr args))) ((member (car args) '("--model" "-m" "--provider" "--repl-port" "--trace")) (if (null? (cdr args)) #f (has-positional-args? (cddr args)))) --- a/src/jcode/ui/tui-input.ss +++ b/src/jcode/ui/tui-input.ss @@ -46,7 +46,8 @@ '(("/help" . "Show help") ("/model" . "Show or set model") ("/provider" . "Show or set provider") - ("/expert" . "Force a prompt to the configured expert model") + ("/expert" . "Force or toggle expert escalation") + ("/no-expert" . "Disable expert escalation") ("/tools" . "List available tools") ("/mcp" . "MCP server status") ("/skills" . "List skills") --- a/src/jcode/ui/tui.ss +++ b/src/jcode/ui/tui.ss @@ -683,7 +683,8 @@ " /activity Live harness activity screen (Esc returns)" " /jcode Switch back to the main jcode tab" " /close-tab Close the current external tab" - " /expert <q> Force this prompt to the configured expert model" + " /expert <q>|off|on|status Force or toggle expert escalation" + " /no-expert Disable expert escalation for this TUI session" " /themes List available themes" " /theme [name] Cycle theme, or switch to a named theme" " /sidebar Toggle sidebar (Ctrl-B)" @@ -778,11 +779,21 @@ (equal? cmd "ask-grok")) (handle-ask-external! state (string->symbol (substring cmd 4 (string-length cmd))))) + ((equal? cmd "no-expert") + (handle-expert-mode! state "off")) ((equal? cmd "expert") - (handle-expert! state "")) + (handle-expert-mode! state "status")) ((string-prefix? "expert " cmd) - (handle-expert! state - (substring cmd 7 (string-length cmd)))) + (let ((arg (string-trim (substring cmd 7 (string-length cmd))))) + (cond + ((member arg '("off" "disable" "disabled" "no" "false")) + (handle-expert-mode! state "off")) + ((member arg '("on" "enable" "enabled" "yes" "true")) + (handle-expert-mode! state "on")) + ((member arg '("status" "?")) + (handle-expert-mode! state "status")) + (else + (handle-expert! state arg))))) ((equal? cmd "sessions") (let ((sessions (session-list))) (add-message! state @@ -1745,6 +1756,45 @@ (add-message! state (msg-block-system (format "Saved session to ~a" path)))))) +;; ---- /expert ---- + +(def (expert-env-disabled?) + (let ((v (getenv "JCODE_NO_EXPERT"))) + (and v (not (string=? v "")) (not (string=? v "0"))))) + +(def (expert-configured?) + (and (config-ref "expert" "provider") + (config-ref "expert" "model") + #t)) + +(def (expert-status-text) + (cond + ((expert-env-disabled?) + "Expert escalation is disabled by JCODE_NO_EXPERT. Unset it or set it to 0 before starting jcode to enable experts.") + ((current-expert-disabled) + "Expert escalation is disabled for this TUI session. Run /expert on to re-enable it.") + ((expert-configured?) + (format "Expert escalation is enabled: ~a/~a. Run /expert off to disable it." + (config-ref "expert" "provider") + (config-ref "expert" "model"))) + (else + "Expert escalation is enabled, but no expert is configured. Add expert.provider and expert.model to jcode.json."))) + +(def (handle-expert-mode! state action) + (cond + ((equal? action "off") + (current-expert-disabled #t) + (add-message! state + (msg-block-system + "Expert escalation disabled for this TUI session. /expert on re-enables it."))) + ((equal? action "on") + (current-expert-disabled #f) + (add-message! state + (msg-block-system (expert-status-text)))) + (else + (add-message! state + (msg-block-system (expert-status-text)))))) + ;; ---- /expert <prompt> ---- ;; Force the next turn to the configured expert by parameterizing the ;; provider/model overrides for the duration of run-agent!. The worker @@ -1753,6 +1803,10 @@ (def (handle-expert! state arg) (let ((prompt (string-trim arg))) (cond + ((or (expert-env-disabled?) (current-expert-disabled)) + (add-message! state + (msg-block-system + "Expert escalation is disabled. Run /expert on, or unset JCODE_NO_EXPERT if it is set."))) ((not (config-expert-enabled?)) (add-message! state (msg-block-system --- a/test/run.ss +++ b/test/run.ss @@ -4334,6 +4334,10 @@ (lambda (cs) (and (member cmd cs) #t)))) dispatcher)) +(check-pred! "binary auto-tui treats --no-expert as an option" + (slurp-file "main-binary.ss") + (lambda (src) (str-find src "\"--no-expert\"" 0))) + ;; ── Results ─────────────────────────────────────────────────────── (printf "~n~a passed, ~a failed~n" pass-count fail-count)