Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 10 additions & 10 deletions agents/__tests__/editor.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,9 +62,9 @@ describe('editor agent', () => {
expect(gpt5Editor.model).toBe('openai/gpt-5.1')
})

test('creates minimax editor', () => {
const minimaxEditor = createCodeEditor({ model: 'minimax' })
expect(minimaxEditor.model).toBe('minimax/minimax-m2.5')
test('creates glm editor', () => {
const glmEditor = createCodeEditor({ model: 'glm' })
expect(glmEditor.model).toBe('z-ai/glm-5.1')
})

test('gpt-5 editor does not include think tags in instructions', () => {
Expand All @@ -74,9 +74,9 @@ describe('editor agent', () => {
})

test('glm editor does not include think tags in instructions', () => {
const minimaxEditor = createCodeEditor({ model: 'minimax' })
expect(minimaxEditor.instructionsPrompt).not.toContain('<think>')
expect(minimaxEditor.instructionsPrompt).not.toContain('</think>')
const glmEditor = createCodeEditor({ model: 'glm' })
expect(glmEditor.instructionsPrompt).not.toContain('<think>')
expect(glmEditor.instructionsPrompt).not.toContain('</think>')
})

test('opus editor includes think tags in instructions', () => {
Expand All @@ -88,17 +88,17 @@ describe('editor agent', () => {
test('all variants have same base properties', () => {
const opusEditor = createCodeEditor({ model: 'opus' })
const gpt5Editor = createCodeEditor({ model: 'gpt-5' })
const minimaxEditor = createCodeEditor({ model: 'minimax' })
const glmEditor = createCodeEditor({ model: 'glm' })

// All should have same basic structure
expect(opusEditor.displayName).toBe(gpt5Editor.displayName)
expect(gpt5Editor.displayName).toBe(minimaxEditor.displayName)
expect(gpt5Editor.displayName).toBe(glmEditor.displayName)

expect(opusEditor.outputMode).toBe(gpt5Editor.outputMode)
expect(gpt5Editor.outputMode).toBe(minimaxEditor.outputMode)
expect(gpt5Editor.outputMode).toBe(glmEditor.outputMode)

expect(opusEditor.toolNames).toEqual(gpt5Editor.toolNames)
expect(gpt5Editor.toolNames).toEqual(minimaxEditor.toolNames)
expect(gpt5Editor.toolNames).toEqual(glmEditor.toolNames)
})
})

Expand Down
32 changes: 16 additions & 16 deletions agents/base2/base2.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ export function createBase2(

return {
publisher,
model: isFree ? 'minimax/minimax-m2.5' : 'anthropic/claude-opus-4.6',
model: isFree ? 'z-ai/glm-5.1' : 'anthropic/claude-opus-4.6',
providerOptions: isFree ? {
data_collection: 'deny',
} : {
Expand Down Expand Up @@ -58,7 +58,7 @@ export function createBase2(
'spawn_agents',
'read_files',
'read_subtree',
!isFast && !isFree && 'write_todos',
!isFast && 'write_todos',
!isFast && !noAskUser && 'suggest_followups',
'str_replace',
'write_file',
Expand All @@ -67,13 +67,13 @@ export function createBase2(
!noAskUser && 'ask_user',
'skill',
'set_output',
'code_search',
'list_directory',
'glob',
),
spawnableAgents: buildArray(
!isMax && 'file-picker',
isMax && 'file-picker-max',
'code-searcher',
'researcher-web',
'researcher-docs',
'basher',
Expand Down Expand Up @@ -124,15 +124,15 @@ export function createBase2(
- Add thoughtful details like hover states, transitions, and micro-interactions
- Apply design principles: hierarchy, contrast, balance, and movement
- Create an impressive demonstration showcasing web development capabilities
- **Refactoring Awareness:** Whenever you modify an exported symbol like a function or class or variable, you should find and update all the references to it appropriately using the code_search tool.
- **Refactoring Awareness:** Whenever you modify an exported symbol like a function or class or variable, you should find and update all the references to it appropriately by spawning a code-searcher agent.
- **Testing:** If you create a unit test, you should run it to see if it passes, and fix it if it doesn't.
- **Package Management:** When adding new packages, use the basher agent to install the package rather than editing the package.json file with a guess at the version number to use (or similar for other languages). This way, you will be sure to have the latest version of the package. Do not install packages globally unless asked by the user (e.g. Don't run \`npm install -g <package-name>\`). Always try to use the package manager associated with the project (e.g. it might be \`pnpm\` or \`bun\` or \`yarn\` instead of \`npm\`, or similar for other languages).
- **Code Hygiene:** Make sure to leave things in a good state:
- Don't forget to add any imports that might be needed
- Remove unused variables, functions, and files as a result of your changes.
- If you added files or functions meant to replace existing code, then you should also remove the previous code.
- **Minimal new code comments:** Do not add many new comments while writing code, unless they were preexisting comments (keep those!) or unless the user asks you to add comments!
- **Don't type cast as "any" type:** Don't cast variables as "any" (or similar for other languages). This is a bad practice as it leads to bugs. The code is more robust when every expression is typed.
- **Don't type cast as "any" type:** Don't cast variables as "any" (or similar for other languages). This is a bad practice as it leads to bugs. Exception: when the value can truly be any type.
- **Prefer str_replace to write_file:** str_replace is more efficient for targeted changes and gives more feedback. Only use write_file for new files or when necessary to rewrite the entire file.

# Spawning agents guidelines

Expand All @@ -141,9 +141,9 @@ Use the spawn_agents tool to spawn specialized agents to help you complete the u
- **Spawn multiple agents in parallel:** This increases the speed of your response **and** allows you to be more comprehensive by spawning more total agents to synthesize the best response.
- **Sequence agents properly:** Keep in mind dependencies when spawning different agents. Don't spawn agents in parallel that depend on each other.
${buildArray(
'- Spawn context-gathering agents (file pickers and web/docs researchers) before making edits. Use the code_search, list_directory, and glob tools directly for searching and exploring the codebase.',
'- Spawn context-gathering agents (file pickers, code searchers, and web/docs researchers) before making edits. Use the list_directory and glob tools directly for searching and exploring the codebase.',
isFree && 'Do not spawn the thinker-gpt agent, unless the user asks. Not everyone has connected their ChatGPT subscription to Codebuff to allow for it.',
isFree && 'You must spawn the thinker-with-files-gemini agent to think through and plan the reponse to most requests, unless the request is trivial. This agent is extremely useful as it is very smart! You must pass the relevant filePaths when spawning it, since it does not have access to the conversation history.',
isFree && `Spawn the thinker-with-files-gemini agent for complex problems — it's very smart. Skip it for routine edits and clearly-scoped changes. Pass the relevant filePaths since it has no conversation history.`,
isDefault &&
'- Spawn the editor agent to implement the changes after you have gathered all the context you need.',
(isDefault || isMax) &&
Expand Down Expand Up @@ -197,16 +197,16 @@ ${buildArray(
<user>please implement [a complex new feature]</user>

<response>
[ You spawn 3 file-pickers and a docs researcher in parallel to find relevant files and do research online. You use the code_search, list_directory, and glob tools directly to search the codebase. ]
[ You spawn 3 file-pickers, 2 code-searchers, and a docs researcher in parallel to find relevant files and do research online. You use the list_directory and glob tools directly to search the codebase. ]

[ You read a few of the relevant files using the read_files tool in two separate tool calls ]

[ You use code_search and glob tools, and spawn another file-picker to find more relevant files ]
[ You spawn another file-picker and code-searcher to find more relevant files, and use glob tools ]

[ You read a few other relevant files using the read_files tool ]${!noAskUser
? `\n\n[ You ask the user for important clarifications on their request or alternate implementation strategies using the ask_user tool ]`
: ''
}${isFree ? `\n\n[ You spawn the thinker-with-files-gemini agent with the relevant filePaths to plan the best response ]` : ''}
}
${isDefault
? `[ You implement the changes using the editor agent ]`
: isFast || isFree
Expand All @@ -217,7 +217,7 @@ ${isDefault
${isDefault
? `[ You spawn a code-reviewer, a basher to typecheck the changes, and another basher to run tests, all in parallel ]`
: isFree
? `[ You spawn a code-reviewer-lite to review the changes, and a basher to typecheck the changes, and another basher to run tests, all in parallel ]`
? `[ You spawn a code-reviewer-lite to review the changes, a basher to typecheck the local changes, a basher to typecheck the whole project, and another basher to run tests, all in parallel ]`
: isMax
? `[ You spawn a basher to typecheck the changes, and another basher to run tests, in parallel. Then, you spawn a code-reviewer-multi-prompt to review the changes. ]`
: '[ You spawn a basher to typecheck the changes and another basher to run tests, all in parallel ]'
Expand Down Expand Up @@ -300,7 +300,7 @@ ${PLACEHOLDER.GIT_CHANGES_PROMPT}
}
}

const EXPLORE_PROMPT = `- Iteratively spawn file pickers, bashers, and web/docs researchers to gather context as needed. Use the code_search, list_directory, and glob tools directly for searching and exploring the codebase. The file-picker agent in particular is very useful to find relevant files -- try spawning multiple in parallel (say, 2-5) to explore different parts of the codebase. Use read_subtree if you need to grok a particular part of the codebase. Read all the relevant files using the read_files tool.`
const EXPLORE_PROMPT = `- Iteratively spawn file pickers, code searchers, bashers, and web/docs researchers to gather context as needed. Use the list_directory and glob tools directly for searching and exploring the codebase. The file-picker and code-searcher agents are very useful to find relevant files -- try spawning multiple in parallel (say, 2-5 file-pickers and 1-3 code-searchers) to explore different parts of the codebase. Use read_subtree if you need to grok a particular part of the codebase. Read all the relevant files using the read_files tool.`

function buildImplementationInstructionsPrompt({
isSonnet,
Expand Down Expand Up @@ -331,10 +331,10 @@ ${buildArray(
`- Important: Read as many files as could possibly be relevant to the task over several steps to improve your understanding of the user's request and produce the best possible code changes. Find more examples within the codebase similar to the user's request, dependencies that help with understanding how things work, tests, etc. This is frequently 12-20 files, depending on the task.`,
!noAskUser &&
'After getting context on the user request from the codebase or from research, use the ask_user tool to ask the user for important clarifications on their request or alternate implementation strategies. You should skip this step if the choice is obvious -- only ask the user if you need their help making the best choice.',
(isDefault || isMax) &&
(isDefault || isMax || isFree) &&
`- For any task requiring 3+ steps, use the write_todos tool to write out your step-by-step implementation plan. Include ALL of the applicable tasks in the list.${isFast ? '' : ' You should include a step to review the changes after you have implemented the changes.'}:${hasNoValidation ? '' : ' You should include at least one step to validate/test your changes: be specific about whether to typecheck, run tests, run lints, etc.'} You may be able to do reviewing and validation in parallel in the same step. Skip write_todos for simple tasks like quick edits or answering questions.`,
isFree &&
`- For most requests, spawn the thinker-with-files-gemini agent to think through and plan the best response. This agent is extremely useful as it is very smart. You must take advantage of it and spawn it about once per user request. Gather all the necessary context *before* spawning it, and pass the relevant filePaths since it does not have access to the conversation history.`,
`- For complex problems, spawn the thinker-with-files-gemini agent after gathering context. Skip it for routine edits and clearly-scoped changes. Pass the relevant filePaths.`,
(isDefault || isMax) &&
`- For quick problems, briefly explain your reasoning to the user. If you need to think longer, write your thoughts within the <think> tags. Finally, for complex problems, spawn the thinker agent to help find the best solution. (gpt-5-agent is a last resort for complex problems)`,
isDefault &&
Expand Down Expand Up @@ -380,7 +380,7 @@ function buildImplementationStepPrompt({
`Keep working until the user's request is completely satisfied${!hasNoValidation ? ' and validated' : ''}, or until you require more information from the user.`,
'You must use the skill tool to load any potentially relevant skills.',
isFree &&
`You must spawn the thinker-with-files-gemini agent once per user request to plan the best response. Pass the relevant filePaths since it does not have access to the conversation history.`,
`Spawn the thinker-with-files-gemini agent for complex problems, not routine edits. Pass the relevant filePaths.`,
isMax &&
`You must spawn the 'editor-multi-prompt' agent to implement code changes rather than using the str_replace or write_file tools, since it will generate the best code changes.`,
(isDefault || isMax) &&
Expand Down
23 changes: 9 additions & 14 deletions agents/basher.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,30 +11,25 @@ const basher: AgentDefinition = {
model: 'google/gemini-3.1-flash-lite-preview',
displayName: 'Basher',
spawnerPrompt:
'Runs a single terminal command and describes its output using an LLM. A lightweight shell command executor. Requires both a shell command and a prompt.',
'Runs a single terminal command and (recommended) describes its output using an LLM using the what_to_summarize field. A lightweight shell command executor. Every basher spawn MUST include params: { command: "<shell>" }.',

inputSchema: {
prompt: {
type: 'string',
description:
'What information from the command output is desired. Be specific about what to look for or extract.',
},
params: {
type: 'object',
properties: {
command: {
type: 'string',
description: 'Terminal command to run in bash shell',
description: 'The terminal command to run in bash shell. Don\'t forget this field!',
},
what_to_summarize: {
type: 'string',
description:
'What information from the command output is desired. Be specific about what to look for or extract. This is optional, and if not provided, the basher will return the full command output without summarization.',
},
timeout_seconds: {
type: 'number',
description: 'Set to -1 for no timeout. Default 30',
},
rawOutput: {
type: 'boolean',
description:
'If true, returns the full command output without summarization. Defaults to false.',
},
},
required: ['command'],
},
Expand Down Expand Up @@ -73,7 +68,7 @@ Do not use any tools! Only analyze the output of the command.`,
}

const timeout_seconds = params?.timeout_seconds as number | undefined
const rawOutput = params?.rawOutput as boolean | undefined
const what_to_summarize = params?.what_to_summarize as string | undefined

// Run the command
const { toolResult } = yield {
Expand All @@ -84,7 +79,7 @@ Do not use any tools! Only analyze the output of the command.`,
},
}

if (rawOutput) {
if (!what_to_summarize) {
// Return the raw command output without summarization
const result = toolResult?.[0]
// Only return object values (command output objects), not plain strings
Expand Down
2 changes: 1 addition & 1 deletion agents/editor/editor-lite.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { createCodeEditor } from './editor'
import type { AgentDefinition } from '../types/agent-definition'

const definition: AgentDefinition = {
...createCodeEditor({ model: 'minimax' }),
...createCodeEditor({ model: 'glm' }),
id: 'editor-lite',
}
export default definition
8 changes: 4 additions & 4 deletions agents/editor/editor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,16 @@ import { publisher } from '../constants'
import type { AgentDefinition } from '../types/agent-definition'

export const createCodeEditor = (options: {
model: 'gpt-5' | 'opus' | 'minimax'
model: 'gpt-5' | 'opus' | 'glm'
}): Omit<AgentDefinition, 'id'> => {
const { model } = options
return {
publisher,
model:
options.model === 'gpt-5'
? 'openai/gpt-5.1'
: options.model === 'minimax'
? 'minimax/minimax-m2.5'
: options.model === 'glm'
? 'z-ai/glm-5.1'
: 'anthropic/claude-opus-4.6',
...(options.model === 'opus' && {
providerOptions: {
Expand Down Expand Up @@ -65,7 +65,7 @@ OR for new files or major rewrites:
}
</codebuff_tool_call>

${model === 'gpt-5' || model === 'minimax'
${model === 'gpt-5' || model === 'glm'
? ''
: `Before you start writing your implementation, you should use <think> tags to think about the best way to implement the changes.

Expand Down
2 changes: 1 addition & 1 deletion agents/file-explorer/code-searcher.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ const codeSearcher: SecretAgentDefinition = {
id: 'code-searcher',
displayName: 'Code Searcher',
spawnerPrompt:
'Mechanically runs multiple code search queries (using ripgrep line-oriented search) and returns up to 250 results across all source files, showing each line that matches the search pattern. Excludes git-ignored files.',
`Mechanically runs multiple code search queries (using ripgrep line-oriented search) and returns up to 250 results across all source files, showing each line that matches the search pattern. Excludes git-ignored files. You MUST pass searchQueries in params. Example input: { "params": { "searchQueries": [{ "pattern": "createUser", "flags": "-g *.ts" }, { "pattern": "deleteUser", "flags": "-g *.ts" }, { "pattern": "UserSchema", "maxResults": 5 }] } }`,
model: 'anthropic/claude-sonnet-4.5',
publisher,
includeMessageHistory: false,
Expand Down
2 changes: 1 addition & 1 deletion agents/reviewer/code-reviewer-lite.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { createReviewer } from './code-reviewer'
const definition: SecretAgentDefinition = {
id: 'code-reviewer-lite',
publisher,
...createReviewer('minimax/minimax-m2.5'),
...createReviewer('z-ai/glm-5.1'),
}

export default definition
2 changes: 1 addition & 1 deletion agents/thinker/thinker-with-files-gemini.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ const definition: SecretAgentDefinition = {
model: 'google/gemini-3.1-pro-preview',
displayName: 'Theo the Theorizer with Files (Gemini)',
reasoningOptions: {
effort: 'low',
effort: 'medium',
},
spawnerPrompt:
'Does deep thinking given the prompt and provided files using Gemini. Use this to help you solve a specific problem. This agent has no context on the conversation history so it cannot see files you have read or previous discussion. Instead, you must provide all the relevant context via the prompt or filePaths for this agent to work well.',
Expand Down
1 change: 1 addition & 0 deletions agents/types/agent-definition.ts
Original file line number Diff line number Diff line change
Expand Up @@ -424,6 +424,7 @@ export type ModelName =
| 'moonshotai/kimi-k2.5'
| 'moonshotai/kimi-k2.5:nitro'
| 'z-ai/glm-5'
| 'z-ai/glm-5.1'
| 'z-ai/glm-4.6'
| 'z-ai/glm-4.6:nitro'
| 'z-ai/glm-4.7'
Expand Down
2 changes: 1 addition & 1 deletion cli/release/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "codebuff",
"version": "1.0.639",
"version": "1.0.640",
"description": "AI coding agent",
"license": "MIT",
"bin": {
Expand Down
1 change: 1 addition & 0 deletions cli/src/chat.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -1525,6 +1525,7 @@ export const Chat = ({
},
cwd: getProjectRoot() ?? process.cwd(),
})}
onInterruptStream={chatKeyboardHandlers.onInterruptStream}
/>
)}
</box>
Expand Down
Loading
Loading