Skip to content
45 changes: 45 additions & 0 deletions lua/eca/commands.lua
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,51 @@ function M.setup()
desc = "Restart ECA server",
})

vim.api.nvim_create_user_command("EcaServerMessages", function()
local has_snacks, snacks = pcall(require, "snacks")
if not has_snacks then
Logger.notify("snacks.nvim is not available", vim.log.levels.ERROR)
return
end

snacks.picker(
---@type snacks.picker.Config
{
source = "eca messages",
finder = function(opts, ctx)
---@type snacks.picker.finder.Item[]
local items = {}
local eca = require("eca")
if not eca or not eca.server then
Logger.notify("ECA plugin is not available", vim.log.levels.ERROR)
return items
end

for msg in vim.iter(eca.server.messages) do
local decoded = vim.json.decode(msg.content)
table.insert(items, {
text = decoded.method,
idx = decoded.id,
preview = {
text = vim.inspect(decoded),
ft = "lua",
},
})
end
return items
end,
preview = "preview",
format = "text",
confirm = function(self, item, _)
vim.fn.setreg("", item.preview.text)
self:close()
end,
}
)
end, {
desc = "Display Messages Sent to and Received by ECA server",
})

vim.api.nvim_create_user_command("EcaLogs", function(opts)
local Api = require("eca.api")
local subcommand = opts.args and opts.args:match("%S+") or "show"
Expand Down
3 changes: 2 additions & 1 deletion lua/eca/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -242,8 +242,9 @@ function M.setup(opts)
H.signs()

-- Initialize the ECA server with callbacks
M.state = require("eca.state").new()
M.server = Server.new()
M.mediator = require("eca.mediator").new(M.server)
M.mediator = require("eca.mediator").new(M.server, M.state)
-- Start server automatically in background
vim.defer_fn(function()
M.server:start()
Expand Down
45 changes: 44 additions & 1 deletion lua/eca/mediator.lua
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
---@class eca.Mediator
---@field server eca.Server
---@field state eca.State
local mediator = {}

---@param server eca.Server
---@param state eca.State
---@return eca.Mediator
function mediator.new(server)
function mediator.new(server, state)
return setmetatable({
server = server,
state = state,
}, { __index = mediator })
end

Expand All @@ -23,4 +26,44 @@ function mediator:send(method, params, callback)
self.server:send_request(method, params, callback)
end

function mediator:selected_behavior()
return self.state.config.behaviors.selected
end

function mediator:selected_model()
return self.state.config.models.selected
end

function mediator:tokens_session()
return self.state.usage.tokens.session
end

function mediator:tokens_limit()
return self.state.usage.tokens.limit
end

function mediator:costs_session()
return self.state.usage.costs.session
end

function mediator:status_state()
return self.state.status.state
end

function mediator:status_text()
return self.state.status.text
end

function mediator:mcps()
local mcps = {}

for _, tool in pairs(self.state.tools) do
if tool.type == "mcp" then
table.insert(mcps, tool)
end
end

return mcps
end

return mediator
4 changes: 2 additions & 2 deletions lua/eca/observer.lua
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
local observer = {}

---@type { [integer]: fun(message: table) }
---@type { [string]: fun(message: table) }
local subscriptions = {}

---@param id integer
---@param id string
---@param on_update fun(message: table)
function observer.subscribe(id, on_update)
subscriptions[id] = on_update
Expand Down
11 changes: 4 additions & 7 deletions lua/eca/server.lua
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ local Logger = require("eca.logger")
---@field on_stop function Callback when the server stops
---Called when a notification is received(message without an ID)
---@field on_notification fun(server: eca.Server, message: table)
---@field capabilities eca.ServerCapabilities Server capabilities
---@field private path_finder eca.PathFinder Server path finder
---@field pending_requests {id: fun(err, data)} -- outgoing requests with callbacks
local M = {}
Expand Down Expand Up @@ -50,7 +49,6 @@ function M.new(opts)
path_finder = opts.path_finder,
messages = {},
pending_requests = {},
capabilities = {},
initialized = false,
next_id = 0,
}, { __index = M })
Expand All @@ -67,7 +65,7 @@ local function on_stdout(server)
if #message.content ~= message.content_length then
return
end
table.insert(messages, message)
table.insert(server.messages, message)
local msg = vim.json.decode(message.content)
server:handle_message(msg)
end)
Expand Down Expand Up @@ -171,20 +169,18 @@ function M:initialize()
},
},
workspaceFolders = workspace_folders,
}, function(err, result)
}, function(err, _)
if err then
Logger.notify("Could not initialize server: " .. err, vim.log.levels.ERROR)
return
end
if result then
self.capabilities = result
end

self:send_notification("initialized", {})

if self.on_initialize then
self.on_initialize()
end
self.initialized = true
end)
end

Expand Down Expand Up @@ -259,6 +255,7 @@ function M:send_request(method, params, callback)
end

local json = vim.json.encode(message)
table.insert(self.messages, { content = json, content_length = #json })
local content = string.format("Content-Length: %d\r\n\r\n%s", #json, json)
self.process:write(content)
end
Expand Down
Loading