Repository navigation
Expand file tree
/
Copy pathreply.lua
More file actions
60 lines (56 loc) · 1.7 KB
/
Copy pathreply.lua
File metadata and controls
60 lines (56 loc) · 1.7 KB
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
local Promise = require('opencode.promise')
local M = {}
---@class OpencodeReplyRequest
---@field promise Promise<table> Resolves to an assistant message; caller validates its content
---@field stop fun(reason?: string)
---Submit one input to a fresh, exclusively owned session and await its reply.
---@param observation table
---@param input table
---@return OpencodeReplyRequest
function M.start(observation, input)
local reply = Promise.new()
local submitted ---@type OpencodeSubmission?
local stopped ---@type string?
local unsubscribe = observation:watch({ 'messages' }, function() end)
local function cleanup()
if unsubscribe then
unsubscribe()
unsubscribe = nil
end
end
local function stop(reason)
stopped = reason or 'Reply request cancelled'
if submitted then
submitted.stop(stopped)
end
reply:reject(stopped)
cleanup()
end
Promise.async(function()
submitted = observation:submit(input):await()
if stopped then
submitted.stop(stopped)
return
end
local completion = submitted.completion:await()
if reply:is_resolved() then
return
end
if completion.kind == 'reply' then
reply:resolve(completion.message)
return
end
if completion.outcome ~= 'succeeded' then
error('Reply request completion failed: ' .. vim.inspect(completion))
end
local message = observation._runtime.find_reply(observation, submitted.input.id)
if not message then
error('Reply request cannot associate the completed reply with its input')
end
reply:resolve(message)
end)():catch(function(err)
reply:reject(err)
end)
return { promise = reply:finally(cleanup), stop = stop }
end
return M