Skip to content
This repository was archived by the owner on Jan 14, 2026. It is now read-only.

Commit bca8c99

Browse files
committed
refactor(gitcommit): flatten tool response structures
- Remove nested output/user_msg/llm_msg wrapper objects - Remove setup handlers from tool definitions - Rename agent to tools in all handler signatures - Remove v17 compatibility code and comments
1 parent 4d810e6 commit bca8c99

3 files changed

Lines changed: 72 additions & 121 deletions

File tree

lua/codecompanion/_extensions/gitcommit/tools/ai_release_notes.lua

Lines changed: 17 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,9 @@
11
local prompts = require("codecompanion._extensions.gitcommit.prompts.release_notes")
22

3-
---@class CodeCompanion.GitCommit.Tools.AIReleaseNotes
3+
---@class CodeCompanion.GitCommit.Tools.AIReleaseNotes: CodeCompanion.Tools.Tool
44
local AIReleaseNotes = {}
55

66
AIReleaseNotes.name = "ai_release_notes"
7-
AIReleaseNotes.description = "Generate comprehensive release notes using AI analysis of commit history"
87

98
AIReleaseNotes.schema = {
109
type = "function",
@@ -194,77 +193,44 @@ AIReleaseNotes.cmds = {
194193
-- Get detailed commit history
195194
local commits, error_msg = get_detailed_commits(from_tag, to_tag)
196195
if not commits then
197-
return {
198-
status = "error",
199-
data = {
200-
output = error_msg,
201-
user_msg = "" .. error_msg,
202-
llm_msg = "<aiReleaseNotes>fail: " .. error_msg .. "</aiReleaseNotes>",
203-
},
204-
}
196+
return { status = "error", data = error_msg }
205197
end
206198

207199
if #commits == 0 then
208200
local msg = string.format("No commits found between %s and %s", from_tag, to_tag)
209-
return {
210-
status = "success",
211-
data = {
212-
output = msg,
213-
user_msg = "" .. msg,
214-
llm_msg = "<aiReleaseNotes>success: " .. msg .. "</aiReleaseNotes>",
215-
},
216-
}
201+
return { status = "success", data = msg }
217202
end
218203

219204
local prompt = prompts.create_smart_prompt(commits, style, { from = from_tag, to = to_tag })
220205

221-
local user_msg =
222-
string.format("📝 Generating %s release notes: %s → %s (%d commits)", style, from_tag, to_tag, #commits)
223-
224-
local llm_msg = string.format("<aiReleaseNotes>\n%s\n</aiReleaseNotes>", prompt)
225-
226-
return {
227-
status = "success",
228-
data = {
229-
output = prompt,
230-
user_msg = user_msg,
231-
llm_msg = llm_msg,
232-
},
233-
}
206+
return { status = "success", data = prompt }
234207
end,
235208
}
236209

237210
AIReleaseNotes.handlers = {
238-
setup = function(_self, _agent)
239-
return true
240-
end,
241-
on_exit = function(_self, _agent) end,
211+
on_exit = function(self, tools) end,
242212
}
243213

244214
AIReleaseNotes.output = {
245-
success = function(self, agent, _cmd, stdout)
246-
local chat = agent.chat
247-
local data = stdout[1]
248-
local llm_msg = data and data.llm_msg or data.output
249-
local user_msg = data and data.user_msg or data.output
250-
return chat:add_tool_output(self, llm_msg, user_msg)
215+
success = function(self, tools, cmd, stdout)
216+
local chat = tools.chat
217+
local output = stdout and #stdout > 0 and vim.iter(stdout):flatten():join("\n") or ""
218+
local user_msg = "Release notes generated"
219+
chat:add_tool_output(self, output, user_msg)
251220
end,
252-
error = function(self, agent, _cmd, stderr, stdout)
253-
local chat = agent.chat
254-
local data = stderr[1] or stdout[1]
255-
local llm_msg = data and data.llm_msg or (type(data) == "string" and data or "AI release notes generation failed")
256-
local user_msg = data and data.user_msg or "AI release notes generation failed"
257-
return chat:add_tool_output(self, llm_msg, user_msg)
221+
error = function(self, tools, cmd, stderr, stdout)
222+
local chat = tools.chat
223+
local errors = stderr and #stderr > 0 and vim.iter(stderr):flatten():join("\n") or "Unknown error"
224+
local user_msg = "Release notes generation failed"
225+
chat:add_tool_output(self, errors, user_msg)
258226
end,
259227
}
260228

261229
AIReleaseNotes.opts = {
262-
-- v18+ uses require_approval_before
263-
require_approval_before = function(_self, _agent)
230+
require_approval_before = function(self, tools)
264231
return false
265232
end,
266-
-- COMPAT(v17): Remove when dropping v17 support
267-
requires_approval = function(_self, _agent)
233+
requires_approval = function(self, tools)
268234
return false
269235
end,
270236
}

lua/codecompanion/_extensions/gitcommit/tools/git_edit.lua

Lines changed: 25 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
11
local GitTool = require("codecompanion._extensions.gitcommit.tools.git").GitTool
22
local validation = require("codecompanion._extensions.gitcommit.tools.validation")
33

4-
---@class CodeCompanion.GitCommit.Tools.GitEdit
4+
---@class CodeCompanion.GitCommit.Tools.GitEdit: CodeCompanion.Tools.Tool
55
local GitEdit = {}
66

77
GitEdit.name = "git_edit"
8-
GitEdit.description = "Tool for write-access Git operations like stage, unstage, branch creation, etc."
98

109
GitEdit.schema = {
1110
type = "function",
@@ -587,14 +586,11 @@ Available write-access Git operations:
587586
}
588587

589588
GitEdit.handlers = {
590-
setup = function(self, agent)
591-
return true
592-
end,
593-
on_exit = function(self, agent) end,
589+
on_exit = function(self, tools) end,
594590
}
595591

596592
GitEdit.output = {
597-
prompt = function(self, _tools)
593+
prompt = function(self, tools)
598594
local operation = self.args and self.args.operation or "unknown"
599595
local details = ""
600596
if operation == "stage" or operation == "unstage" then
@@ -612,36 +608,40 @@ GitEdit.output = {
612608
return string.format("Execute git %s%s?", operation, details)
613609
end,
614610

615-
success = function(self, agent, _cmd, stdout)
616-
local chat = agent.chat
617-
local operation = self.args.operation
618-
local user_msg = string.format("Git edit operation [%s] executed successfully", operation)
619-
return chat:add_tool_output(self, stdout[1], user_msg)
611+
success = function(self, tools, cmd, stdout)
612+
local chat = tools.chat
613+
local operation = self.args and self.args.operation or "unknown"
614+
local output = stdout and #stdout > 0 and vim.iter(stdout):flatten():join("\n") or ""
615+
local user_msg = string.format("Git %s completed", operation)
616+
chat:add_tool_output(self, output, user_msg)
620617
end,
621618

622-
error = function(self, agent, _cmd, stderr, stdout)
623-
local chat = agent.chat
624-
local operation = self.args.operation
625-
local error_msg = stderr and stderr[1] or ("Git edit operation [%s] failed"):format(operation)
626-
local user_msg = string.format("Git edit operation [%s] failed", operation)
627-
return chat:add_tool_output(self, error_msg, user_msg)
619+
error = function(self, tools, cmd, stderr, stdout)
620+
local chat = tools.chat
621+
local operation = self.args and self.args.operation or "unknown"
622+
local errors = stderr and #stderr > 0 and vim.iter(stderr):flatten():join("\n") or "Unknown error"
623+
local user_msg = string.format("Git %s failed", operation)
624+
chat:add_tool_output(self, errors, user_msg)
628625
end,
629626

630-
rejected = function(self, tools, _cmd, _opts)
631-
local chat = tools.chat
627+
rejected = function(self, tools, cmd, opts)
632628
local operation = self.args and self.args.operation or "unknown"
633629
local message = string.format("User rejected the git %s operation", operation)
634-
return chat:add_tool_output(self, message, message)
630+
opts = vim.tbl_extend("force", { message = message }, opts or {})
631+
local ok, helpers = pcall(require, "codecompanion.interactions.chat.tools.builtin.helpers")
632+
if ok and helpers and helpers.rejected then
633+
helpers.rejected(self, tools, cmd, opts)
634+
else
635+
tools.chat:add_tool_output(self, message)
636+
end
635637
end,
636638
}
637639

638640
GitEdit.opts = {
639-
-- v18+ uses require_approval_before
640-
require_approval_before = function(self, agent)
641+
require_approval_before = function(self, tools)
641642
return true
642643
end,
643-
-- COMPAT(v17): Remove when dropping v17 support
644-
requires_approval = function(self, agent)
644+
requires_approval = function(self, tools)
645645
return true
646646
end,
647647
}

lua/codecompanion/_extensions/gitcommit/tools/git_read.lua

Lines changed: 30 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
11
local GitTool = require("codecompanion._extensions.gitcommit.tools.git").GitTool
22
local validation = require("codecompanion._extensions.gitcommit.tools.validation")
33

4-
---@class CodeCompanion.GitCommit.Tools.GitRead
4+
---@class CodeCompanion.GitCommit.Tools.GitRead: CodeCompanion.Tools.Tool
55
local GitRead = {}
66

77
GitRead.name = "git_read"
8-
GitRead.description = "Tool for read-only Git operations like status, log, diff, etc."
98

109
GitRead.schema = {
1110
type = "function",
@@ -315,77 +314,63 @@ GitRead.cmds = {
315314
-- Handle unexpected execution errors
316315
if not ok then
317316
local error_msg = "Git read operation failed unexpectedly: " .. tostring(result)
318-
return {
319-
status = "error",
320-
data = {
321-
output = error_msg,
322-
user_msg = error_msg,
323-
llm_msg = "<gitReadTool>fail: " .. error_msg .. "</gitReadTool>",
324-
},
325-
}
317+
return { status = "error", data = error_msg }
326318
end
327319

328-
local success, output, user_msg, llm_msg = result.success, result.output, result.user_msg, result.llm_msg
320+
local op_success, output = result.success, result.output
329321

330-
-- Ensure proper response format even if operation fails
331-
if success then
332-
return { status = "success", data = { output = output, user_msg = user_msg, llm_msg = llm_msg } }
322+
if op_success then
323+
return { status = "success", data = output or "Operation completed" }
333324
else
334-
-- Ensure consistent error message format
335-
local formatted_output = {
336-
output = output or "Git read operation failed",
337-
user_msg = user_msg or "Git read operation failed",
338-
llm_msg = llm_msg or "<gitReadTool>fail: Git read operation failed</gitReadTool>",
339-
}
340-
return { status = "error", data = formatted_output }
325+
return { status = "error", data = output or "Git read operation failed" }
341326
end
342327
end,
343328
}
344329

345330
GitRead.handlers = {
346-
setup = function(_self, _agent)
347-
return true
348-
end,
349-
on_exit = function(_self, _agent) end,
331+
on_exit = function(self, tools) end,
350332
}
351333

352334
GitRead.output = {
353-
prompt = function(self, _tools)
335+
prompt = function(self, tools)
354336
local operation = self.args and self.args.operation or "unknown"
355337
return string.format("Execute git %s?", operation)
356338
end,
357339

358-
success = function(self, agent, _cmd, stdout)
359-
local chat = agent.chat
360-
local data = stdout[1]
361-
local llm_msg = data and data.llm_msg or data.output
362-
local user_msg = data and data.user_msg or data.output
363-
return chat:add_tool_output(self, llm_msg, user_msg)
340+
success = function(self, tools, cmd, stdout)
341+
local chat = tools.chat
342+
local operation = self.args and self.args.operation or "unknown"
343+
local output = stdout and #stdout > 0 and vim.iter(stdout):flatten():join("\n") or ""
344+
local user_msg = string.format("Git %s completed", operation)
345+
chat:add_tool_output(self, output, user_msg)
364346
end,
365347

366-
error = function(self, agent, _cmd, stderr, stdout)
367-
local chat = agent.chat
368-
local data = stderr[1] or stdout[1]
369-
local llm_msg = data and data.llm_msg or (type(data) == "string" and data or "Git read operation failed")
370-
local user_msg = data and data.user_msg or "Git read operation failed"
371-
return chat:add_tool_output(self, llm_msg, user_msg)
348+
error = function(self, tools, cmd, stderr, stdout)
349+
local chat = tools.chat
350+
local operation = self.args and self.args.operation or "unknown"
351+
local errors = stderr and #stderr > 0 and vim.iter(stderr):flatten():join("\n") or "Unknown error"
352+
local user_msg = string.format("Git %s failed", operation)
353+
chat:add_tool_output(self, errors, user_msg)
372354
end,
373355

374-
rejected = function(self, tools, _cmd, _opts)
375-
local chat = tools.chat
356+
rejected = function(self, tools, cmd, opts)
376357
local operation = self.args and self.args.operation or "unknown"
377358
local message = string.format("User rejected the git %s operation", operation)
378-
return chat:add_tool_output(self, message, message)
359+
opts = vim.tbl_extend("force", { message = message }, opts or {})
360+
local ok, helpers = pcall(require, "codecompanion.interactions.chat.tools.builtin.helpers")
361+
if ok and helpers and helpers.rejected then
362+
helpers.rejected(self, tools, cmd, opts)
363+
else
364+
tools.chat:add_tool_output(self, message)
365+
end
379366
end,
380367
}
381368

382369
GitRead.opts = {
383-
-- v18+ uses require_approval_before
384-
require_approval_before = function(_self, _agent)
370+
require_approval_before = function(self, tools)
385371
return false
386372
end,
387-
-- COMPAT(v17): Remove when dropping v17 support
388-
requires_approval = function(_self, _agent)
373+
requires_approval = function(self, tools)
389374
return false
390375
end,
391376
}

0 commit comments

Comments
 (0)