From 6d1b18cb95327b9057cff931f8a5dd9aef211ce2 Mon Sep 17 00:00:00 2001 From: Raghu Betina Date: Mon, 19 Oct 2026 12:07:09 -0500 Subject: [PATCH 1/2] Flush PP's buffer before writing messages directly Message#pretty_print writes straight to q.output so IRB's ColorPrinter can't escape our ANSI codes. Inside an Array, though, PP is still buffering the "[" and the separators between elements, so `pp chat.messages` printed every message first and every comma last: `[{...},{...}{...} , ]`. Flushing first puts the buffered text out ahead of each message. Items#pretty_print gets the same fix. New specs pin the exact plain-text layout of Chat#inspect and of an Array of messages. Lessons show this output verbatim, and until now the specs only checked that inspect returned a String. --- CHANGELOG.md | 6 ++++++ lib/ai/items.rb | 2 ++ lib/ai/message.rb | 5 ++++- spec/unit/chat_spec.rb | 45 +++++++++++++++++++++++++++++++++++++++ spec/unit/items_spec.rb | 6 ++++++ spec/unit/message_spec.rb | 26 +++++++++++++++++++++- 6 files changed, 88 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index cd8e8d9..11b764b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [Unreleased] + +### Fixed + +- **`pp` of an Array of messages**: `pp chat.messages` (and IRB's echo of `chat.messages`) printed `},{` and `}{` between messages and piled the leftover separators up before the closing bracket (`} , ]`). Messages now print as `[{...}, {...}]`, matching `p`. `AI::Items` had the same problem inside an Array and gets the same fix. + ## [0.8.0] - 2026-10-19 ### Changed diff --git a/lib/ai/items.rb b/lib/ai/items.rb index f2e48ec..6411d0c 100644 --- a/lib/ai/items.rb +++ b/lib/ai/items.rb @@ -35,7 +35,9 @@ def pretty_inspect "#{inspect}\n" end + # Same direct write as AI::Message#pretty_print, for the same reasons. def pretty_print(q) + q.flush q.output << inspect end diff --git a/lib/ai/message.rb b/lib/ai/message.rb index 7856256..97de932 100644 --- a/lib/ai/message.rb +++ b/lib/ai/message.rb @@ -11,8 +11,11 @@ def pretty_inspect end # IRB's ColorPrinter calls pretty_print and re-colorizes text, - # which escapes our ANSI codes. Write directly to output to bypass. + # which escapes our ANSI codes. Write directly to output to bypass, + # but flush first: inside an Array, PP is still buffering the "[" and + # earlier separators, so an unflushed write lands ahead of them. def pretty_print(q) + q.flush q.output << inspect end diff --git a/spec/unit/chat_spec.rb b/spec/unit/chat_spec.rb index 2701981..7aac674 100644 --- a/spec/unit/chat_spec.rb +++ b/spec/unit/chat_spec.rb @@ -743,6 +743,51 @@ def schema_client_double it "returns a String" do expect(chat.inspect).to be_a(String) end + + # Lessons show this output verbatim, so pin the exact layout. + context "when not writing to a terminal" do + before { allow($stdout).to receive(:tty?).and_return(false) } + + it "lists a new chat's attributes one per line" do + new_chat = AI::Chat.new(api_key: "test-key", proxy: false) + + expect(new_chat.inspect).to eq(<<~TEXT.chomp) + # + TEXT + end + + it "lists messages by index with aligned keys" do + proxied_chat = AI::Chat.new(api_key: "test-key", proxy: true) + proxied_chat.system("You are an assistant that talks like Shakespeare.") + proxied_chat.user("What is the motto of Ruby lang?") + + expect(proxied_chat.inspect).to eq(<<~TEXT.chomp) + # + TEXT + end + end end describe "#pretty_inspect" do diff --git a/spec/unit/items_spec.rb b/spec/unit/items_spec.rb index 94af000..20d2a50 100644 --- a/spec/unit/items_spec.rb +++ b/spec/unit/items_spec.rb @@ -61,6 +61,12 @@ expect(out).to include("Conversation: conv_abc123") expect(out).to include("Items: 2") end + + it "keeps separators in place inside an Array" do + out = PP.pp([items, items], +"") + + expect(out).to eq("[#{items.inspect}, #{items.inspect}]\n") + end end describe "#to_html" do diff --git a/spec/unit/message_spec.rb b/spec/unit/message_spec.rb index e4756f6..a05b230 100644 --- a/spec/unit/message_spec.rb +++ b/spec/unit/message_spec.rb @@ -68,11 +68,35 @@ end end + describe "printing an Array of messages with pp" do + before { allow($stdout).to receive(:tty?).and_return(false) } + + it "keeps each separator between the messages it separates" do + messages = [ + AI::Message[role: "user", content: "Hello"], + AI::Message[role: "assistant", content: "Hi!", response: {id: "resp_1"}] + ] + + expect(PP.pp(messages, +"")).to eq(<<~TEXT) + [{ + role: "user", + content: "Hello" + }, { + role: "assistant", + content: "Hi!", + response: { + id: "resp_1" + } + }] + TEXT + end + end + describe "#pretty_print" do it "writes directly to output to bypass IRB colorization" do message = AI::Message[role: "user", content: "Hello"] output = StringIO.new - mock_q = double("PrettyPrint", output: output) + mock_q = double("PrettyPrint", output: output, flush: nil) message.pretty_print(mock_q) From fd31bf32ea1676e2543c5000e5f4fe7ac82bfc6a Mon Sep 17 00:00:00 2001 From: Raghu Betina Date: Mon, 19 Oct 2026 13:21:44 -0500 Subject: [PATCH 2/2] Release 0.8.1 --- CHANGELOG.md | 2 +- Gemfile.lock | 2 +- ai-chat.gemspec | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 11b764b..bc34827 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,7 +5,7 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## [Unreleased] +## [0.8.1] - 2026-10-19 ### Fixed diff --git a/Gemfile.lock b/Gemfile.lock index beaad89..8bc4331 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,7 +1,7 @@ PATH remote: . specs: - ai-chat (0.8.0) + ai-chat (0.8.1) amazing_print (~> 2.0) base64 (~> 0.1, > 0.1.1) json (~> 2.0) diff --git a/ai-chat.gemspec b/ai-chat.gemspec index 20cd0a1..2e763f1 100644 --- a/ai-chat.gemspec +++ b/ai-chat.gemspec @@ -2,7 +2,7 @@ Gem::Specification.new do |spec| spec.name = "ai-chat" - spec.version = "0.8.0" + spec.version = "0.8.1" spec.authors = ["Raghu Betina", "Jelani Woods"] spec.email = ["raghu@firstdraft.com", "jelani@firstdraft.com"] spec.homepage = "https://github.com/firstdraft/ai-chat"