-
Notifications
You must be signed in to change notification settings - Fork 6
Expand file tree
/
Copy pathstate.lua
More file actions
225 lines (182 loc) · 5.53 KB
/
Copy pathstate.lua
File metadata and controls
225 lines (182 loc) · 5.53 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
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
---@class eca.StateStatus
---@field state string
---@field text string
---@class eca.StateConfig
---@field welcome_message string?
---@field behaviors { list: string[], default: string?, selected: string? }
---@field models { list: string[], default: string?, selected: string? }
---@class eca.StateUsage
---@field tokens { limit: number, session: number }
---@field costs { last_message: string, session: string }
---@class eca.StateTool
---@field type string
---@field name string
---@field status string
---
---@class eca.State
---@field status eca.StateStatus
---@field config eca.StateConfig
---@field usage eca.StateUsage
---@field tools table<string, eca.StateTool>
local State = {}
---@return eca.State
function State._new()
local instance = setmetatable({
status = {
state = "idle",
text = "Idle",
},
config = {
welcome_message = nil,
behaviors = {
list = {},
default = nil,
selected = nil,
},
models = {
list = {},
default = nil,
selected = nil,
},
},
usage = {
tokens = {
limit = 0,
session = 0,
},
costs = {
last_message = "0.00",
session = "0.00",
},
},
tools = {},
}, { __index = State })
local handlers = {
["chat/contentReceived"] = function(message) instance:_chat_content_received(message) end,
["config/updated"] = function(message) instance:_config_updated(message) end,
["tool/serverUpdated"] = function(message) instance:_tool_server_updated(message) end,
}
require("eca.observer").subscribe("state-1", function(message)
if not message or not message.method then
return
end
local handler = handlers[message.method]
if not handler or type(handler) ~= 'function' then
return
end
handler(message)
end)
return instance
end
local _instance
---@return eca.State
function State.new()
if not _instance then
_instance = State._new()
end
return _instance
end
function State:_chat_content_received(message)
if not message or not message.params then
return
end
if not message.params.content or not message.params.content.type then
return
end
local content = message.params.content
if content.type == "progress" then
self:_update_status(content)
end
if content.type == "usage" then
self:_update_usage(content)
end
end
function State:_config_updated(message)
if not message or not message.params then
return
end
if not message.params.chat or type(message.params.chat) ~= "table" then
return
end
self:_update_config({ chat = vim.deepcopy(message.params.chat) })
end
function State:_tool_server_updated(message)
if not message or not message.params then
return
end
self:_update_tools(message.params)
end
function State:_update_config(config)
local chat = config.chat
if not chat or type(chat) ~= "table" then
return
end
self.config.behaviors = {
list = (chat.behaviors and vim.deepcopy(chat.behaviors)) or self.config.behaviors.list,
default = (chat.defaultBehavior) or self.config.behaviors.default,
selected = (chat.selectBehavior) or self.config.behaviors.selected,
}
self.config.models = {
list = (chat.models and vim.deepcopy(chat.models)) or self.config.models.list,
default = (chat.defaultModel) or self.config.models.default,
selected = (chat.selectModel) or self.config.models.selected,
}
self.config.welcome_message = (chat and chat.welcomeMessage) or self.config.welcome_message
vim.schedule(function()
require("eca.observer").notify({ type = "state/updated", content = { config = vim.deepcopy(self.config) } })
end)
end
function State:_update_status(status)
self.status.state = status.state or self.status.state
self.status.text = status.text or self.status.text
vim.schedule(function()
require("eca.observer").notify({ type = "state/updated", content = { status = vim.deepcopy(self.status) } })
end)
end
function State:_update_usage(usage)
self.usage = {
tokens = {
limit = (usage.limit and usage.limit.context) or self.usage.tokens.limit,
session = usage.sessionTokens or self.usage.tokens.session,
},
costs = {
last_message = usage.lastMessageCost or self.usage.costs.last_message,
session = usage.sessionCost or self.usage.costs.session,
},
}
vim.schedule(function()
require("eca.observer").notify({ type = "state/updated", content = { usage = vim.deepcopy(self.usage) } })
end)
end
function State:_update_tools(tool)
if not tool.name then
return
end
self.tools[tool.name] = {
name = tool.name,
type = tool.type or (self.tools[tool.name] and self.tools[tool.name].type) or "unknown",
status = tool.status or (self.tools[tool.name] and self.tools[tool.name].status) or "unknown",
}
vim.schedule(function()
require("eca.observer").notify({ type = "state/updated", content = { tools = vim.deepcopy(self.tools) } })
end)
end
function State:update_selected_model(model)
if not model or type(model) ~= "string" then
return
end
self.config.models.selected = model
vim.schedule(function()
require("eca.observer").notify({ type = "state/updated", content = { config = vim.deepcopy(self.config) } })
end)
end
function State:update_selected_behavior(behavior)
if not behavior or type(behavior) ~= "string" then
return
end
self.config.behaviors.selected = behavior
vim.schedule(function()
require("eca.observer").notify({ type = "state/updated", content = { config = vim.deepcopy(self.config) } })
end)
end
return State