Class: Pikuri::Workspace::Confirmer::Terminal
- Inherits:
-
Pikuri::Workspace::Confirmer
- Object
- Pikuri::Workspace::Confirmer
- Pikuri::Workspace::Confirmer::Terminal
- Defined in:
- lib/pikuri/workspace/confirmer.rb
Overview
Stdin/stdout implementation. Renders the request as up to several lines (a leading puts guarantees separation from any streamed output the Terminal listener may have produced just above):
-
a bold-yellow warning block — one line per Sanitizer::Warning — shown only when the sanitizer flagged something suspicious in the question or detail
-
the question, bold
-
the detail, dim — omitted when
nil -
the (y/n)? cue
Both question and detail pass through Sanitizer, which neutralizes control bytes — without it, a model could craft a command or description containing “rrm -rf ~/” that visually overwrites the echoed line after the user has already read it —and reports why it was unsafe so the user reads the warning before answering. Colors come from Rainbow (already in the dependency closure via pikuri-core), which self-disables on non-TTY output; the bold-yellow warning rendering is this terminal chrome’s call, not the sanitizer’s (the Warning carries plain text only).
Then reads one line from $stdin and parses it strictly:
-
“y” / “yes” (case-insensitive, stripped) →
true -
“n” / “no” →
false -
EOF / Ctrl+D (
getsreturnsnil) →false, deliberate abort -
anything else (blank, typo, “maybe”) → re-prompt with a short “Please answer y or n: ” line and loop
No retry cap; EOF eventually breaks adversarial input.
Constant Summary
Constants inherited from Pikuri::Workspace::Confirmer
Instance Method Summary collapse
Instance Method Details
#confirm?(request:) ⇒ Boolean
109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 |
# File 'lib/pikuri/workspace/confirmer.rb', line 109 def confirm?(request:) question = Pikuri::Sanitizer.sanitize(request.question) detail = request.detail ? Pikuri::Sanitizer.sanitize(request.detail) : nil warnings = question.warnings + (detail ? detail.warnings : []) puts unless warnings.empty? puts Rainbow('⚠ Suspicious content detected — read carefully before approving:').yellow.bold warnings.each { |w| puts Rainbow(" ! #{w.explanation}").yellow } end puts Rainbow(question.text).bold puts Rainbow(detail.text).dimgray if detail puts '(y/n)?' $stdout.flush loop do line = $stdin.gets return false if line.nil? answer = line.strip.downcase return true if answer == 'y' || answer == 'yes' return false if answer == 'n' || answer == 'no' print 'Please answer y or n: ' $stdout.flush end end |