Skip to content

Commit 9489e68

Browse files
committed
Avoid AI::Chat inspect recursion
Build Chat inspect/to_html output without calling ai on self, which prevents AmazingPrint fallback recursion in HTML views.
1 parent 1171e8e commit 9489e68

1 file changed

Lines changed: 33 additions & 9 deletions

File tree

lib/ai/chat.rb

Lines changed: 33 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -228,13 +228,11 @@ def inspectable_attributes
228228
end
229229

230230
def inspect
231-
ensure_amazing_print_loaded!
232-
ai(plain: !$stdout.tty?, multiline: true)
231+
pretty_format(plain: !$stdout.tty?, multiline: true)
233232
end
234233

235234
def to_html
236-
ensure_amazing_print_loaded!
237-
AI.wrap_html(ai(html: true, multiline: true))
235+
AI.wrap_html(pretty_format(html: true, multiline: true))
238236
end
239237

240238
def pretty_inspect
@@ -247,12 +245,38 @@ class InputClassificationError < StandardError; end
247245

248246
class WrongAPITokenUsedError < StandardError; end
249247

250-
def ensure_amazing_print_loaded!
251-
return if defined?(AmazingPrint::AI)
248+
# Build a pretty representation without calling `ai` on `self`.
249+
# This avoids a recursion loop when AmazingPrint falls back to `#inspect`.
250+
# :reek:DuplicateMethodCall
251+
# :reek:TooManyStatements
252+
def pretty_format(html: false, plain: false, multiline: true)
253+
inspector = AmazingPrint::Inspector.new(html: html, plain: plain, multiline: multiline)
254+
255+
attrs = inspectable_attributes.map do |(name, value)|
256+
[name.to_s, value]
257+
end
258+
259+
data = attrs.map do |(name, value)|
260+
"#{name}: #{inspector.awesome(value)}"
261+
end
252262

253-
require_relative "amazing_print"
254-
rescue LoadError
255-
# amazing_print is optional; skip custom formatting if not available
263+
lt = html ? "&lt;" : "<"
264+
gt = html ? "&gt;" : ">"
265+
266+
output = if multiline
267+
"##{lt}#{self.class}\n#{data.map { |line| " #{line}" }.join("\n")}\n#{gt}"
268+
else
269+
"##{lt}#{self.class} #{data.join(", ")}#{gt}"
270+
end
271+
272+
html ? "<pre>#{output}</pre>" : output
273+
rescue NameError, LoadError
274+
fallback = if multiline
275+
"#<#{self.class}\n#{inspectable_attributes.map { |(n, v)| " #{n}: #{v.inspect}" }.join("\n")}\n>"
276+
else
277+
"#<#{self.class} #{inspectable_attributes.map { |(n, v)| "#{n}: #{v.inspect}" }.join(", ")}>"
278+
end
279+
html ? "<pre>#{fallback}</pre>" : fallback
256280
end
257281

258282
# :reek:FeatureEnvy

0 commit comments

Comments
 (0)