zot/internal
patriceckhart ac6d556f0a feat(tool-gate): --no-yolo flag, confirm dialog, /yolo runtime toggle
Adds a per-tool-call confirmation gate. Default stays yolo mode
(tools run freely, same as today). Pass --no-yolo to require
explicit user approval before each tool invocation.

Interactive TUI:
  A dialog appears before every tool call. Shows the tool name and
  a one-line preview of its args (command / path / url / etc.)
  with four choices, selectable by arrow keys or numeric shortcut:

    1. yes                     (run this call)
    2. yes, always this tool   (skip prompts for this tool,
                                session-scoped)
    3. yes, always             (skip prompts for every tool,
                                session-scoped)
    4. no                      (refuse and let the model try
                                something else)

  Esc/ctrl+c refuses the current prompt. Esc during a running turn
  both cancels the turn AND drains any pending confirm so the
  agent goroutine doesn't deadlock. Multiple pending confirms are
  queued and answered one at a time with a count visible in the
  header.

  Type /yolo to disable the gate for the rest of the session
  (equivalent to the "yes, always" choice but without needing a
  pending prompt). Any currently-open confirm auto-allows so the
  agent keeps moving.

Print / JSON / RPC modes:
  No interactive prompt is available, so every tool call is
  auto-refused with a reason the model can learn from:
  "tool call refused: --no-yolo is active and there is no
  interactive prompt in this mode; ask the user what to do
  instead". Observed behaviour: the model pivots to asking the
  user directly instead of looping on the same tool.

Implementation:
  internal/core/confirm.go
    - ConfirmDecision, Confirmer interface
    - ConfirmGate with session-scoped memory for "always this tool"
      and "always everything" decisions, both concurrency-safe
    - BuildPreview: turns {"command":"ls"} into "ls", etc.
    - Lives in core to avoid a modes -> agent import cycle
  internal/core/confirm_test.go
    - Tests: nil gate allows, nil-inner refuses with reason, one-
      shot allow doesn't remember, remember-tool short-circuits
      only same tool, remember-all short-circuits everything,
      refusal reasons surface, empty-reason gets a default,
      runtime AllowAll works, BuildPreview handles each field
  internal/agent/modes/confirm_dialog.go
    - Queue-based dialog, HandleKey wiring, CancelAll and
      AllowAllPending for the two exit cases
  internal/agent/modes/interactive.go
    - InteractiveConfig gains NoYolo + ConfirmGate fields
    - Interactive implements core.Confirmer via a response channel
    - Confirm dialog dispatched FIRST in the key-handler chain so
      keys never leak to other dialogs while the agent is blocked
    - Esc-while-busy also calls confirmDialog.CancelAll so the
      agent unblocks
    - /yolo slash command handled in runSlash
  internal/agent/cli.go
    - Constructs the ConfirmGate when args.NoYolo is set,
      BeforeToolExecute calls it first, extensions only see calls
      the user already approved
    - After iv is built, SetConfirmer(iv) wires the gate's inner
      so interactive + gate share the same struct
    - wireNoYoloAutoRefuse() for print / json modes
  internal/agent/args.go
    - --no-yolo flag and help text
  internal/agent/modes/slash_suggest.go
    - /yolo added to slashCatalog

Verified end-to-end: fresh zot --no-yolo -p "read sample.ts" now
returns "I can't read files in this mode (--no-yolo without an
interactive prompt). How would you like to proceed" instead of
actually reading.
2026-04-19 19:12:45 +02:00
..
agent feat(tool-gate): --no-yolo flag, confirm dialog, /yolo runtime toggle 2026-04-19 19:12:45 +02:00
assets add logo to callback page 2026-04-18 10:15:53 +02:00
auth add auto compaction 2026-04-18 10:34:08 +02:00
core feat(tool-gate): --no-yolo flag, confirm dialog, /yolo runtime toggle 2026-04-19 19:12:45 +02:00
extproto feat(ext): phase 4 - full-event interception, arg rewrites, /reload-ext 2026-04-19 17:02:04 +02:00
provider perf(anthropic): fix cost double-count, tighten caching, correct catalog 2026-04-19 18:57:18 +02:00
skills perf(prompt): cut system prompt to the bone (410 -> 54 tokens) 2026-04-19 17:39:38 +02:00
tui perf(read): drop line numbers from model-facing output 2026-04-19 17:33:05 +02:00