summaryrefslogtreecommitdiff
path: root/init.lua
blob: 532152a9a69fd53105ebec5d0710458892d437c9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
local config = require("rsvp.config")
local Player = require("rsvp.player").Player

local function activate()
    local panto = require("panto")
    local ext = panto.ext
    local settings, err = config.read(ext.config and ext.config.rsvp)
    if not settings then error("panto-rsvp: " .. err) end
    local uv = require("luv")

    local player = Player.new {
        settings = settings,
        highlight = function(body) return ext.highlight(body, "markdown") end,
        width = panto.text.width,
        truncate = panto.text.truncate,
        style = function() return ext.style() end,
        new_timer = function() return uv.new_timer() end,
        mount = function(component, placement) return ext.mount(component, placement) end,
        input_mode = function(spec) return ext.input_mode(spec) end,
    }

    local function subscribe(name, handler)
        ext.on(name, handler)
    end

    subscribe("session_ready", function()
        local ok, text = pcall(function()
            local latest
            for _, message in ipairs(ext.agent:conversation():messages()) do
                if message.role == "assistant" then
                    for _, block in ipairs(message.blocks or {}) do
                        if block.type == "text" then latest = block.text or "" end
                    end
                end
            end
            return latest or ""
        end)
        player:snapshot_source(ok and text or "")
    end)
    subscribe("render_assistant_text", function(event)
        player:set_source(event.text or "", false, event.index)
    end)
    subscribe("render_assistant_text_delta", function(event)
        if event.text ~= nil then player:update_source(event.text, false, event.index) end
    end)
    subscribe("render_assistant_text_complete", function(event)
        player:update_source(event.text or "", true, event.index)
    end)
    subscribe("suspend", function() player:suspend() end)
    subscribe("turn_start", function() player:cancel("turn") end)
    subscribe("turn_interrupt", function() player:cancel("turn") end)
    subscribe("session_end", function() player:cancel("session_end") end)

    ext.register_command {
        name = "rsvp",
        description = "Read the latest assistant text one paragraph at a time.",
        handler = function(arguments)
            if arguments and arguments ~= "" then return "Usage: /rsvp" end
            local ok, why = player:activate()
            if not ok then
                return "RSVP unavailable" .. (why and (": " .. tostring(why)) or "")
            end
        end,
    }
end

return { name = "rsvp", activate = activate }