Repository navigation
Expand file tree
/
Copy pathconfig_file.lua
More file actions
193 lines (169 loc) · 5.85 KB
/
Copy pathconfig_file.lua
File metadata and controls
193 lines (169 loc) · 5.85 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
local Promise = require('opencode.promise')
local sha1 = require('opencode.sha1')
local M = {
config_promise = nil,
project_promise = nil,
providers_promise = nil,
}
---@type fun(): Promise<OpencodeConfigFile|nil>
M.get_opencode_config = Promise.async(function()
if not M.config_promise then
local state = require('opencode.state')
M.config_promise = Promise.retry(function()
return state.api_client:get_config()
end, 3, 500)
end
local ok, result = pcall(function()
return M.config_promise:await()
end)
if not ok then
M.config_promise = nil
vim.notify('Error fetching Opencode config: ' .. vim.inspect(result), vim.log.levels.ERROR)
return nil
end
return result
end)
---@type fun(): Promise<OpencodeProject|nil>
M.get_opencode_project = Promise.async(function()
if not M.project_promise then
local state = require('opencode.state')
M.project_promise = Promise.retry(function()
return state.api_client:get_current_project()
end, 3, 500)
end
local ok, result = pcall(function()
return M.project_promise:await()
end)
if not ok then
M.project_promise = nil
vim.notify('Error fetching Opencode project: ' .. vim.inspect(result), vim.log.levels.ERROR)
return nil
end
return result --[[@as OpencodeProject|nil]]
end)
---Get the snapshot storage path for the current workspace
---Matches opencode's Global.Path.data + "snapshot" + projectId + Hash.fast(worktree)
---Can be overridden via config.snapshot_path (base path, project_id and worktree_hash are appended)
---@type fun(): Promise<string>
M.get_workspace_snapshot_path = Promise.async(function()
local project = M.get_opencode_project():await() --[[@as OpencodeProject|nil]]
if not project then
return ''
end
local data_home = require('opencode.config').snapshot_path
if not data_home or data_home == '' then
data_home = vim.uv.os_getenv('XDG_DATA_HOME')
if not data_home or data_home == '' then
data_home = vim.uv.os_homedir() .. '/.local/share'
end
data_home = vim.fs.joinpath(data_home, 'opencode')
end
local cwd = vim.fn.getcwd()
local worktree_hash = sha1(cwd)
if not worktree_hash then
return ''
end
local path = vim.fs.joinpath(data_home, 'snapshot', project.id, worktree_hash)
return vim.fs.normalize(path)
end)
local _providers_render_callback = false
---@return Promise<OpencodeProvidersResponse|nil>
function M.get_opencode_providers()
if not M.providers_promise then
local state = require('opencode.state')
M.providers_promise = state.api_client:list_providers()
end
local wrapped = M.providers_promise:catch(function(err)
vim.notify('Error fetching Opencode providers: ' .. vim.inspect(err), vim.log.levels.ERROR)
M.providers_promise = nil
return nil
end)
if not _providers_render_callback then
_providers_render_callback = true
wrapped:finally(function()
local ok, _ = pcall(function()
require('opencode.ui.topbar').render()
end)
end)
end
return wrapped
end
--- Get model information for a specific provider and model
--- @param provider string Provider ID
--- @param model string Model ID
--- @return OpencodeModel|nil Model information with variants
M.get_model_info = function(provider, model)
local providers_response = M.get_opencode_providers():peek()
local providers = providers_response and providers_response.providers or {}
local filtered_providers = vim.tbl_filter(function(p)
return p.id == provider
end, providers)
if #filtered_providers == 0 then
return nil
end
return filtered_providers[1] and filtered_providers[1].models and filtered_providers[1].models[model] or nil
end
---@type fun(): Promise<string[]>
M.get_opencode_agents = Promise.async(function()
local cfg = M.get_opencode_config():await()
if not cfg then
return {}
end
local agents = {}
for agent, opts in pairs(cfg.agent or {}) do
-- Only include agents that are enabled and have the right mode
if opts.disable ~= true and opts.hidden ~= true and (opts.mode == 'primary' or opts.mode == 'all') then
table.insert(agents, agent)
end
end
table.sort(agents)
for _, mode in ipairs({ 'plan', 'build' }) do
if not vim.tbl_contains(agents, mode) then
local mode_config = cfg.agent and cfg.agent[mode]
if mode_config == nil or (mode_config.disable ~= true and mode_config.hidden ~= true) then
table.insert(agents, 1, mode)
end
end
end
return agents
end)
---@type fun(): Promise<string[]>
M.get_subagents = Promise.async(function()
local cfg = M.get_opencode_config():await()
if not cfg then
return {}
end
local subagents = {}
for agent, opts in pairs(cfg.agent or {}) do
-- Only include agents that are not disabled, not hidden, and not primary-only
if opts.disable ~= true and opts.hidden ~= true and (opts.mode ~= 'primary' or opts.mode == 'all') then
table.insert(subagents, agent)
end
end
for _, default_agent in ipairs({ 'general', 'explore' }) do
if not vim.tbl_contains(subagents, default_agent) then
local agent_config = cfg.agent and cfg.agent[default_agent]
if agent_config == nil or (agent_config.disable ~= true and agent_config.hidden ~= true) then
table.insert(subagents, 1, default_agent)
end
end
end
return subagents
end)
---@type fun(): Promise<table<string, table>|nil>
M.get_user_commands = Promise.async(function()
local cfg = M.get_opencode_config():await()
return cfg and cfg.command or nil
end)
---@type fun(): Promise<table<string, table>|nil>
M.get_mcp_servers = Promise.async(function()
local cfg = M.get_opencode_config():await()
return cfg and cfg.mcp or nil
end)
---Does this opencode user command take arguments?
---@param command OpencodeCommand
---@return boolean
function M.command_takes_arguments(command)
return command.template and command.template:find('$ARGUMENTS') ~= nil or false
end
return M