Luigit
repositories / dotfiles

dotfiles

bugabingas dorkfiles

owned by admin

neovim/tests/bugabinga/pivi/assemble_spec.lua

Raw
---@diagnostic disable: duplicate-set-field, need-check-nil, param-type-mismatch, assign-type-mismatch
local assemble = require 'bugabinga.pivi.assemble'
local fixture = dofile 'tests/helpers/pivi_fixture.lua'

local delta = function( value )
  return { type = 'message_update', assistantMessageEvent = value, }
end

local feed = function( events )
  local state = assemble.new()
  for _, event in ipairs( events ) do
    state = assemble.apply( state, event )
  end
  return state
end

describe( 'pivi assemble', function()
  it( 'concatenates text deltas by content index', function()
    local state = feed {
      { type = 'message_start', message = { role = 'assistant', }, },
      delta { type = 'text_start', contentIndex = 0, },
      delta { type = 'text_delta', contentIndex = 0, delta = 'Hello', },
      delta { type = 'text_delta', contentIndex = 0, delta = ' world', },
    }
    assert.equal( 'Hello world', assemble.text( state ) )
  end )

  it( 'keeps interleaved content blocks in index order', function()
    local state = feed {
      delta { type = 'text_delta', contentIndex = 2, delta = 'second', },
      delta { type = 'text_delta', contentIndex = 0, delta = 'first ', },
    }
    assert.equal( 'first second', assemble.text( state ) )
  end )

  it( 'separates thinking from visible text', function()
    local state = feed {
      delta { type = 'thinking_delta', contentIndex = 0, delta = 'pondering', },
      delta { type = 'text_delta', contentIndex = 1, delta = 'answer', },
    }
    assert.equal( 'answer', assemble.text( state ) )
    assert.equal( 'pondering', assemble.thinking( state ) )
  end )

  it( 'buffers tool call arguments and marks completion', function()
    local state = feed {
      delta { type = 'toolcall_start', contentIndex = 0, id = 'call_1', toolName = 'edit', },
      delta { type = 'toolcall_delta', contentIndex = 0, delta = '{"path":"a.lua"', },
    }

    local streaming = assemble.tool_calls( state )[1]
    assert.equal( 'call_1', streaming.id )
    assert.equal( 'edit', streaming.name )
    assert.equal( '{"path":"a.lua"', streaming.arguments_text )
    assert.is_false( streaming.complete )

    state = assemble.apply( state, delta {
      type = 'toolcall_end',
      contentIndex = 0,
      toolCall = { id = 'call_1', name = 'edit', arguments = { path = 'a.lua', }, },
    } )

    local finished = assemble.tool_calls( state )[1]
    assert.is_true( finished.complete )
    assert.equal( 'a.lua', finished.arguments.path )
  end )

  it( 'treats message_end as authoritative over accumulated deltas', function()
    local state = feed {
      delta { type = 'text_delta', contentIndex = 0, delta = 'partial junk', },
      {
        type = 'message_end',
        message = {
          role = 'assistant',
          content = { { type = 'text', text = 'final answer', }, },
        },
      },
    }
    assert.equal( 'final answer', assemble.text( state ) )
    assert.is_true( state.complete )
  end )

  it( 'resets on a new assistant message and ignores user messages', function()
    local state = feed {
      delta { type = 'text_delta', contentIndex = 0, delta = 'old', },
      { type = 'message_start', message = { role = 'user', }, },
    }
    assert.equal( 'old', assemble.text( state ) )

    state = assemble.apply( state, { type = 'message_start', message = { role = 'assistant', }, } )
    assert.equal( '', assemble.text( state ) )
  end )

  it( 'reproduces a recorded streaming answer', function()
    local state = assemble.new()
    for _, frame in ipairs( fixture.frames 'rpc-text-stream.jsonl' ) do
      state = assemble.apply( state, frame )
    end

    local final
    for _, frame in ipairs( fixture.of_type( 'rpc-text-stream.jsonl', 'message_end' ) ) do
      if frame.message and frame.message.role == 'assistant' then final = frame.message end
    end

    local expected = ''
    for _, block in ipairs( final.content ) do
      if block.type == 'text' then expected = expected .. block.text end
    end

    assert.equal( expected, assemble.text( state ) )
    assert.is_true( #assemble.thinking( state ) > 0 )
  end )

  it( 'assembles a recorded tool call from its argument deltas', function()
    local state = assemble.new()
    local streaming, completed = {}, {}

    -- A recorded run holds several assistant messages, and each one resets the
    -- assembled state, so a completed call is captured while it is current.
    for _, frame in ipairs( fixture.frames 'rpc-tool-stream.jsonl' ) do
      state = assemble.apply( state, frame )
      for _, call in ipairs( assemble.tool_calls( state ) ) do
        if call.complete then
          -- The first completion carries the streamed argument text; the later
          -- authoritative message_end rebuilds the call without it.
          completed[call.id] = completed[call.id] or call
        elseif call.arguments_text ~= '' then
          table.insert( streaming, call.arguments_text )
        end
      end
    end

    assert.is_true( #streaming > 1 )
    for index = 2, #streaming do
      assert.equal( streaming[index - 1], streaming[index]:sub( 1, #streaming[index - 1] ) )
    end

    local recorded
    for _, event in ipairs( fixture.deltas 'rpc-tool-stream.jsonl' ) do
      if event.type == 'toolcall_end' then recorded = event.toolCall end
    end

    assert.is_table( recorded )

    local finished = completed[recorded.id]
    assert.is_table( finished )
    assert.equal( recorded.name, finished.name )
    assert.equal( recorded.arguments.path, finished.arguments.path )
    assert.equal( recorded.arguments.path, vim.json.decode( finished.arguments_text ).path )
  end )

  it( 'survives a recorded delta that carries an empty payload', function()
    local empty = 0
    for _, event in ipairs( fixture.deltas 'rpc-tool-stream.jsonl' ) do
      if event.type == 'toolcall_delta' and ( event.delta == nil or event.delta == '' ) then
        empty = empty + 1
      end
    end
    assert.is_true( empty > 0 )

    local state = assemble.new()
    local seen = 0
    for _, frame in ipairs( fixture.frames 'rpc-tool-stream.jsonl' ) do
      state = assemble.apply( state, frame )
      seen = math.max( seen, #assemble.tool_calls( state ) )
    end
    assert.is_true( seen > 0 )
  end )

  it( 'ignores unknown events and malformed deltas', function()
    local state = feed {
      { type = 'totally_unknown_event', },
      { type = 'message_update', },
      delta { type = 'nonsense', contentIndex = 0, },
      'not a table',
    }
    assert.equal( '', assemble.text( state ) )
  end )
end )