Skip to content
12 changes: 7 additions & 5 deletions .agents/templates/git-committer-user-prompt.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
Please follow the below steps to create a good commit message:

1. **Run two run_terminal_command tool calls:**

- Run \`git diff\` to review both staged and unstaged modifications.
- Run \`git log\` to check recent commit messages, ensuring consistency with this repository’s style.

Expand All @@ -9,8 +10,9 @@ Please follow the below steps to create a good commit message:
3. **Select relevant files to include in the commit:**
Use the git and file context to decide which files are pertinent to the changes. Stage any new untracked files that are relevant, but avoid committing previously modified files (from the beginning of the conversation) unless they directly relate to this commit.

3. **Analyze the staged changes and compose a commit message:**
4. **Analyze the staged changes and compose a commit message:**
Enclose your analysis in <commit_analysis> tags. Within these tags, you should:

- Note which files have been altered or added.
- Categorize the nature of the changes (e.g., new feature, fix, refactor, documentation, etc.).
- Consider the purpose or motivation behind the alterations.
Expand All @@ -22,7 +24,7 @@ Please follow the below steps to create a good commit message:
- Ensure the message provides clarity—avoid generic or vague terms like “Update” or “Fix” without context.
- Revisit your draft to confirm it truly reflects the changes and their intention.

4. **Create the commit, ending with this specific footer:**
5. **Create the commit, ending with this specific footer:**
\`\`\`
Generated with Codebuff 🤖
Co-Authored-By: Codebuff <noreply@codebuff.com>
Expand All @@ -48,7 +50,7 @@ Please follow the below steps to create a good commit message:
- Make sure your commit message is concise yet descriptive, focusing on the intention behind the changes rather than merely describing them.

5. **Wrapping up**
Finally, after creating the commit, you should use the update_report tool with a concise summary of what you committed and whether it was successful.
Use end_turn to end your turn immediately after using the update_report tool.
Finally, after creating the commit, you should use the set_output tool with a structured summary of what you committed and whether it was successful. The output should include fields like `success`, `message`, and `commitHash` if available.
Use end_turn to end your turn immediately after using the set_output tool.

There's no need to write anything else outside these tool calls.
There's no need to write anything else outside these tool calls.
10 changes: 4 additions & 6 deletions .agents/templates/git-committer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,7 @@ import { DynamicAgentConfig } from '@codebuff/common/types/dynamic-agent-templat
export default {
id: 'CodebuffAI/git-committer',
version: '0.0.1',
model: 'google/gemini-2.5-pro',
override: false,
// implementation: 'llm',
model: 'anthropic/claude-sonnet-4',
name: 'Git Committer',
purpose:
'A git committer agent specialized to commit current changes with an appropriate commit message.',
Expand All @@ -16,11 +14,11 @@ export default {
},
},
includeMessageHistory: false,
outputMode: 'report',
outputMode: 'json',
toolNames: [
'read_files',
'run_terminal_command',
'update_report',
'set_output',
'think_deeply',
'end_turn',
],
Expand All @@ -30,5 +28,5 @@ export default {
path: './git-committer-user-prompt.md',
},
agentStepPrompt:
'Make sure to end your response by using update_report to update the report with a concise summary of what you committed and whether it was successful. Finally, use end_turn to end your turn.',
'Make sure to end your response by using set_output to output a structured summary of what you committed and whether it was successful. Finally, use end_turn to end your turn.',
} satisfies DynamicAgentConfig
24 changes: 1 addition & 23 deletions backend/src/__tests__/parent-instructions.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ describe('Parent Instructions Injection', () => {
subagents: [],
messageHistory: [],
stepsRemaining: 10,
report: {},
output: undefined,
}

// Test parent instructions collection directly
Expand Down Expand Up @@ -153,17 +153,6 @@ describe('Parent Instructions Injection', () => {
const researcherTemplate = agentRegistry['researcher']
expect(researcherTemplate).toBeDefined()

// Create mock agent state
const agentState: AgentState = {
agentId: 'test-agent',
agentType: 'researcher',
agentContext: {},
subagents: [],
messageHistory: [],
stepsRemaining: 10,
report: {},
}

// Test parent instructions collection directly
const parentInstructions = await collectParentInstructions(
'researcher',
Expand Down Expand Up @@ -249,17 +238,6 @@ describe('Parent Instructions Injection', () => {
const researcherTemplate = agentRegistry['researcher']
expect(researcherTemplate).toBeDefined()

// Create mock agent state
const agentState: AgentState = {
agentId: 'test-agent',
agentType: 'researcher',
agentContext: {},
subagents: [],
messageHistory: [],
stepsRemaining: 10,
report: {},
}

// Test parent instructions collection directly
const parentInstructions = await collectParentInstructions(
'researcher',
Expand Down
66 changes: 26 additions & 40 deletions backend/src/__tests__/run-agent-step-tools.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -168,14 +168,12 @@ describe('runAgentStep - update_report tool', () => {
agentTemplates: {},
}

it('should update report with simple key-value pair', async () => {
it('should set output with simple key-value pair', async () => {
const mockResponse =
getToolCallString(
'update_report',
'set_output',
{
json_update: {
message: 'Hi',
},
message: 'Hi',
},
false
) + getToolCallString('end_turn', {}, true)
Expand Down Expand Up @@ -209,22 +207,20 @@ describe('runAgentStep - update_report tool', () => {
}
)

expect(result.agentState.report).toEqual({
expect(result.agentState.output).toEqual({
message: 'Hi',
})
expect(result.shouldEndTurn).toBe(true)
})

it('should update report with json_update', async () => {
it('should set output with complex data', async () => {
const mockResponse =
getToolCallString(
'update_report',
'set_output',
{
json_update: {
message: 'Analysis complete',
status: 'success',
findings: ['Bug in auth.ts', 'Missing validation'],
},
message: 'Analysis complete',
status: 'success',
findings: ['Bug in auth.ts', 'Missing validation'],
},
false
) + getToolCallString('end_turn', {}, true)
Expand Down Expand Up @@ -259,23 +255,21 @@ describe('runAgentStep - update_report tool', () => {
}
)

expect(result.agentState.report).toEqual({
expect(result.agentState.output).toEqual({
message: 'Analysis complete',
status: 'success',
findings: ['Bug in auth.ts', 'Missing validation'],
})
expect(result.shouldEndTurn).toBe(true)
})

it('should merge with existing report data', async () => {
it('should replace existing output data', async () => {
const mockResponse =
getToolCallString(
'update_report',
'set_output',
{
json_update: {
newField: 'new value',
existingField: 'updated value',
},
newField: 'new value',
existingField: 'updated value',
},
false
) + getToolCallString('end_turn', {}, true)
Expand All @@ -286,8 +280,8 @@ describe('runAgentStep - update_report tool', () => {

const sessionState = getInitialSessionState(mockFileContext)
const agentState = sessionState.mainAgentState
// Pre-populate the report with existing data
agentState.report = {
// Pre-populate the output with existing data
agentState.output = {
existingField: 'original value',
anotherField: 'unchanged',
}
Expand All @@ -307,37 +301,31 @@ describe('runAgentStep - update_report tool', () => {
fileContext: mockFileContext,
agentRegistry,
agentState,
prompt: 'Update the report',
prompt: 'Update the output',
params: undefined,
assistantMessage: undefined,
assistantPrefix: undefined,
}
)

expect(result.agentState.report).toEqual({
existingField: 'updated value', // Should be updated
anotherField: 'unchanged', // Should remain unchanged
newField: 'new value', // Should be added
expect(result.agentState.output).toEqual({
newField: 'new value',
existingField: 'updated value',
})
})

it('should handle empty json_update parameter', async () => {
it('should handle empty output parameter', async () => {
const mockResponse =
getToolCallString(
'update_report',
{
json_update: {},
},
false
) + getToolCallString('end_turn', {}, true)
getToolCallString('set_output', {}, false) +
getToolCallString('end_turn', {}, true)

spyOn(aisdk, 'promptAiSdkStream').mockImplementation(async function* () {
yield mockResponse
})

const sessionState = getInitialSessionState(mockFileContext)
const agentState = sessionState.mainAgentState
agentState.report = { existingField: 'value' }
agentState.output = { existingField: 'value' }
const { agentRegistry } = await getAllAgentTemplates({
fileContext: mockFileContext,
})
Expand All @@ -361,9 +349,7 @@ describe('runAgentStep - update_report tool', () => {
}
)

// Should preserve existing report data
expect(result.agentState.report).toEqual({
existingField: 'value',
})
// Should replace with empty object
expect(result.agentState.output).toEqual({})
})
})
Loading