# frozen_string_literal: true RSpec.describe DiscourseAi::Completions::FunctionCallNormalizer do let(:buffer) { +"" } let(:normalizer) do blk = ->(data, cancel) { buffer << data } cancel = -> { @done = true } DiscourseAi::Completions::FunctionCallNormalizer.new(blk, cancel) end def pass_through!(data) normalizer << data expect(buffer[-data.length..-1]).to eq(data) end it "is usable in non streaming mode" do xml = (<<~XML).strip hello hello XML text, function_calls = DiscourseAi::Completions::FunctionCallNormalizer.normalize(xml) expect(text).to eq("hello") expected_function_calls = (<<~XML).strip hello tool_0 XML expect(function_calls).to eq(expected_function_calls) end it "strips junk from end of function calls" do xml = (<<~XML).strip hello hello junk XML _text, function_calls = DiscourseAi::Completions::FunctionCallNormalizer.normalize(xml) expected_function_calls = (<<~XML).strip hello tool_0 XML expect(function_calls).to eq(expected_function_calls) end it "returns nil for function calls if there are none" do input = "hello world\n" text, function_calls = DiscourseAi::Completions::FunctionCallNormalizer.normalize(input) expect(text).to eq(input) expect(function_calls).to eq(nil) end it "passes through data if there are no function calls detected" do pass_through!("hello") pass_through!("hello") pass_through!("world") pass_through!("") end it "properly handles non English tools" do normalizer << "hello\n" normalizer << (<<~XML).strip hello 世界 XML expected = (<<~XML).strip hello 世界 tool_0 XML function_calls = normalizer.function_calls expect(function_calls).to eq(expected) end it "works correctly even if you only give it 1 letter at a time" do xml = (<<~XML).strip abc hello world abc hello2 world aba XML xml.each_char { |char| normalizer << char } expect(buffer + normalizer.function_calls).to eq(xml) end it "supports multiple invokes" do xml = (<<~XML).strip hello world abc hello2 world aba XML normalizer << xml expect(normalizer.function_calls).to eq(xml) end it "can will cancel if it encounteres " do normalizer << "" expect(normalizer.done).to eq(false) normalizer << "" expect(normalizer.done).to eq(true) expect(@done).to eq(true) expect(normalizer.function_calls).to eq("") end it "pauses on function call and starts buffering" do normalizer << "hello" expect(buffer).to eq("hello") expect(normalizer.done).to eq(false) end end