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
634 changes: 634 additions & 0 deletions .agents/tmux-cli.ts

Large diffs are not rendered by default.

20 changes: 0 additions & 20 deletions agents/__tests__/context-pruner.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1087,26 +1087,6 @@ describe('context-pruner spawn_agents with prompt and params', () => {
expect(content).toContain('params: {"command":"npm test"}')
})

test('includes both prompt and params for spawn_agent_inline', () => {
const messages = [
createMessage('user', 'Search code'),
createToolCallMessage('call-1', 'spawn_agent_inline', {
agent_type: 'code-searcher',
prompt: 'Find usages of deprecated API',
params: { searchQueries: [{ pattern: 'oldFunction' }] },
}),
createToolResultMessage('call-1', 'spawn_agent_inline', { output: {} }),
]

const results = runHandleSteps(messages)
const content = results[0].input.messages[0].content[0].text

expect(content).toContain('Spawned agent: code-searcher')
expect(content).toContain('prompt: "Find usages of deprecated API"')
expect(content).toContain('params:')
expect(content).toContain('oldFunction')
})

test('truncates very long prompts (over 1000 chars)', () => {
const longPrompt = 'X'.repeat(1500)
const messages = [
Expand Down
27 changes: 14 additions & 13 deletions agents/base2/base2.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,13 @@ export function createBase2(
publisher,
model: isFree ? 'minimax/minimax-m2.5' : 'anthropic/claude-opus-4.6',
providerOptions: isFree ? {
only: ['fireworks'],
order: ['fireworks'],
only: ['inceptron/fp8'],
order: ['inceptron/fp8'],
allow_fallbacks: false,
data_collection: 'deny',
} : undefined,
} : {
only: ['amazon-bedrock'],
},
displayName: 'Buffy the Orchestrator',
spawnerPrompt:
'Advanced base agent that orchestrates planning, editing, and reviewing for complex coding tasks',
Expand Down Expand Up @@ -68,16 +70,13 @@ export function createBase2(
!noAskUser && 'ask_user',
'skill',
'set_output',
isFree && 'code_search',
isFree && 'list_directory',
isFree && 'glob',
'code_search',
'list_directory',
'glob',
),
spawnableAgents: buildArray(
!isMax && 'file-picker',
isMax && 'file-picker-max',
!isFree && 'code-searcher',
!isFree && 'directory-lister',
!isFree && 'glob-matcher',
'researcher-web',
'researcher-docs',
isFree ? 'commander-lite' : 'commander',
Expand All @@ -89,6 +88,7 @@ export function createBase2(
isFree && 'code-reviewer-lite',
isDefault && 'code-reviewer',
isMax && 'code-reviewer-multi-prompt',
isDefault && 'tmux-cli',
'context-pruner',
),

Expand All @@ -109,6 +109,7 @@ export function createBase2(
}
- **Be careful about terminal commands:** Be careful about instructing subagents to run terminal commands that could be destructive or have effects that are hard to undo (e.g. git push, git commit, running any scripts -- especially ones that could alter production environments (!), installing packages globally, etc). Don't run any of these effectful commands unless the user explicitly asks you to.
- **Do what the user asks:** If the user asks you to do something, even running a risky terminal command, do it.
- **Don't use set_output:** The set_output tool is for spawned subagents to report results. Don't use it yourself.

# Code Editing Mandates

Expand Down Expand Up @@ -140,7 +141,7 @@ 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, code-searcher, directory-lister, glob-matcher, and web/docs researchers) before making edits.',
'- 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.',
isFree &&
'- Spawn the editor-lite agent to implement the changes after you have gathered all the context you need.',
isDefault &&
Expand Down Expand Up @@ -196,11 +197,11 @@ ${buildArray(
<user>please implement [a complex new feature]</user>

<response>
[ You spawn 3 file-pickers, a code-searcher, and a docs researcher in parallel to find relevant files and do research online ]
[ 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 read a few of the relevant files using the read_files tool in two separate tool calls ]

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

[ 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 ]`
Expand Down Expand Up @@ -299,7 +300,7 @@ ${PLACEHOLDER.GIT_CHANGES_PROMPT}
}
}

const EXPLORE_PROMPT = `- Iteratively spawn file pickers, code-searchers, directory-listers, glob-matchers, commanders, and web/docs researchers to gather context as needed. 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, commanders, 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.`

function buildImplementationInstructionsPrompt({
isSonnet,
Expand Down
3 changes: 0 additions & 3 deletions agents/context-pruner.ts
Original file line number Diff line number Diff line change
Expand Up @@ -297,9 +297,6 @@ const definition: AgentDefinition = {
/** Agent IDs whose output should be excluded from spawn_agents results */
const SPAWN_AGENTS_OUTPUT_BLACKLIST = [
'file-picker',
'code-searcher',
'directory-lister',
'glob-matcher',
'researcher-web',
'researcher-docs',
'commander',
Expand Down
5 changes: 5 additions & 0 deletions agents/editor/best-of-n/best-of-n-selector2.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,11 @@ export const createBestOfNSelector2 = (options: {
effort: 'high',
},
}),
...(isOpus && {
providerOptions: {
only: ['amazon-bedrock'],
},
}),
displayName: isGpt5
? 'Best-of-N GPT-5 Diff Selector'
: isOpus
Expand Down
5 changes: 5 additions & 0 deletions agents/editor/best-of-n/editor-implementor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,11 @@ export const createBestOfNImplementor = (options: {
: isGemini
? 'google/gemini-3-pro-preview'
: 'openai/gpt-5.1',
...(isOpus && {
providerOptions: {
only: ['amazon-bedrock'],
},
}),
displayName: 'Implementation Generator',
spawnerPrompt:
'Generates a complete implementation using propose_* tools that draft changes without applying them',
Expand Down
3 changes: 3 additions & 0 deletions agents/editor/best-of-n/editor-multi-prompt.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ export function createMultiPromptEditor(): Omit<SecretAgentDefinition, 'id'> {
return {
publisher,
model: 'anthropic/claude-opus-4.6',
providerOptions: {
only: ['amazon-bedrock'],
},
displayName: 'Multi-Prompt Editor',
spawnerPrompt:
'Edits code by spawning multiple implementor agents with different strategy prompts, selects the best implementation, and applies the changes. It also returns further suggested improvements which you should take seriously and act on. Pass as input an array of short prompts specifying different implementation approaches or strategies. Make sure to read any files intended to be edited before spawning this agent.',
Expand Down
5 changes: 5 additions & 0 deletions agents/editor/editor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,11 @@ export const createCodeEditor = (options: {
: options.model === 'minimax'
? 'minimax/minimax-m2.5'
: 'anthropic/claude-opus-4.6',
...(options.model === 'opus' && {
providerOptions: {
only: ['amazon-bedrock'],
},
}),
displayName: 'Code Editor',
spawnerPrompt:
"Expert code editor that implements code changes based on the user's request. Do not specify an input prompt for this agent; it inherits the context of the entire conversation with the user. Make sure to read any files intended to be edited before spawning this agent as it cannot read files on its own.",
Expand Down
5 changes: 5 additions & 0 deletions agents/general-agent/general-agent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,11 @@ export const createGeneralAgent = (options: {
return {
publisher,
model: isGpt5 ? 'openai/gpt-5.2' : 'anthropic/claude-opus-4.6',
...(!isGpt5 && {
providerOptions: {
only: ['amazon-bedrock'],
},
}),
...(isGpt5 && {
reasoningOptions: {
effort: 'high' as const,
Expand Down
3 changes: 3 additions & 0 deletions agents/reviewer/code-reviewer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,9 @@ const definition: SecretAgentDefinition = {
id: 'code-reviewer',
publisher,
...createReviewer('anthropic/claude-opus-4.6'),
providerOptions: {
only: ['amazon-bedrock'],
},
}

export default definition
3 changes: 3 additions & 0 deletions agents/reviewer/multi-prompt/code-reviewer-multi-prompt.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ export function createCodeReviewerMultiPrompt(): Omit<
return {
publisher,
model: 'anthropic/claude-opus-4.6',
providerOptions: {
only: ['amazon-bedrock'],
},
displayName: 'Multi-Prompt Code Reviewer',
spawnerPrompt:
'Reviews code by spawning multiple code-reviewer agents with different focus prompts, then combines all review outputs into a comprehensive review. Make sure to read relevant files before spawning this agent. Pass an input array of short prompts specifying several different review focuses or perspectives.',
Expand Down
5 changes: 5 additions & 0 deletions agents/thinker/best-of-n/thinker-best-of-n.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,11 @@ export function createThinkerBestOfN(
: isOpus
? 'anthropic/claude-opus-4.6'
: 'anthropic/claude-sonnet-4.5',
...(isOpus && {
providerOptions: {
only: ['amazon-bedrock'],
},
}),
displayName: isGpt5
? 'Best-of-N GPT-5 Thinker'
: isOpus
Expand Down
5 changes: 5 additions & 0 deletions agents/thinker/best-of-n/thinker-selector.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,11 @@ export function createThinkerSelector(
model: isOpus
? 'anthropic/claude-opus-4.6'
: 'anthropic/claude-sonnet-4.5',
...(isOpus && {
providerOptions: {
only: ['amazon-bedrock'],
},
}),
displayName: isOpus
? 'Opus Thinker Output Selector'
: 'Thinker Output Selector',
Expand Down
3 changes: 3 additions & 0 deletions agents/thinker/thinker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ const definition: SecretAgentDefinition = {
id: 'thinker',
publisher,
model: 'anthropic/claude-opus-4.6',
providerOptions: {
only: ['amazon-bedrock'],
},
displayName: 'Theo the Theorizer',
spawnerPrompt:
'Does deep thinking given the current conversation history and a specific prompt to focus on. Use this to help you solve a specific problem. It is better to gather any relevant context before spawning this agent.',
Expand Down
1 change: 0 additions & 1 deletion cli/src/components/blocks/agent-block-grid.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,6 @@ export const AgentBlockGrid = memo(
availableWidth={availableWidth}
getItemKey={getItemKey}
renderItem={renderItem}
marginTop={1}
/>
)
},
Expand Down
6 changes: 3 additions & 3 deletions cli/src/components/blocks/agent-branch-item.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ export const AgentBranchItem = memo((props: AgentBranchItemProps) => {
if (React.isValidElement(value)) {
if (value.key === null || value.key === undefined) {
return (
<box key="expanded-node" style={{ flexDirection: 'column', gap: 0 }}>
<box key="expanded-node" style={{ flexDirection: 'column', gap: 1 }}>
{value}
</box>
)
Expand All @@ -135,7 +135,7 @@ export const AgentBranchItem = memo((props: AgentBranchItemProps) => {

if (Array.isArray(value)) {
return (
<box key="expanded-array" style={{ flexDirection: 'column', gap: 0 }}>
<box key="expanded-array" style={{ flexDirection: 'column', gap: 1 }}>
{value.map((child, idx) => (
<box
key={`expanded-array-${idx}`}
Expand All @@ -149,7 +149,7 @@ export const AgentBranchItem = memo((props: AgentBranchItemProps) => {
}

return (
<box key="expanded-unknown" style={{ flexDirection: 'column', gap: 0 }}>
<box key="expanded-unknown" style={{ flexDirection: 'column', gap: 1 }}>
{value}
</box>
)
Expand Down
17 changes: 5 additions & 12 deletions cli/src/components/blocks/agent-branch-wrapper.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import React, {

import { AgentBlockGrid } from './agent-block-grid'
import { AgentBranchItem } from './agent-branch-item'
import { trimTrailingNewlines, sanitizePreview } from './block-helpers'
import { trimNewlines, sanitizePreview } from './block-helpers'
import { ContentWithMarkdown } from './content-with-markdown'
import { ImplementorGroup } from './implementor-row'
import { ThinkingBlock } from './thinking-block'
Expand All @@ -18,7 +18,6 @@ import { useTheme } from '../../hooks/use-theme'
import { useChatStore } from '../../state/chat-store'
import { isTextBlock } from '../../types/chat'
import { getAgentStatusInfo } from '../../utils/agent-helpers'
import { extractHtmlBlockMargins } from '../../utils/block-margins'
import {
processBlocks,
type BlockProcessorHandlers,
Expand Down Expand Up @@ -248,11 +247,12 @@ const AgentBody = memo(
const isNestedStreamingText =
p.parentIsStreaming || nestedStatus === 'running'
const filteredNestedContent = isNestedStreamingText
? trimTrailingNewlines(textBlock.content)
? trimNewlines(textBlock.content)
: textBlock.content.trim()
if (!filteredNestedContent) {
return null
}
const markdownOptionsForLevel = p.getAgentMarkdownOptions(0)
const marginTop = textBlock.marginTop ?? 0
const marginBottom = textBlock.marginBottom ?? 0
const explicitColor = textBlock.color
const nestedTextColor = explicitColor ?? p.theme.foreground

Expand All @@ -262,8 +262,6 @@ const AgentBody = memo(
style={{
wrapMode: 'word',
fg: nestedTextColor,
marginTop,
marginBottom,
}}
>
<ContentWithMarkdown
Expand All @@ -278,17 +276,13 @@ const AgentBody = memo(

if (block.type === 'html') {
const htmlBlock = block as HtmlContentBlock
const { marginTop, marginBottom } =
extractHtmlBlockMargins(htmlBlock)

return (
<box
key={`${p.keyPrefix}-html-${index}`}
style={{
flexDirection: 'column',
gap: 0,
marginTop,
marginBottom,
}}
>
{htmlBlock.render({
Expand Down Expand Up @@ -390,7 +384,6 @@ export const AgentBranchWrapper = memo(
flexDirection: 'column',
gap: 0,
width: '100%',
marginTop: 1,
}}
>
<text style={{ wrapMode: 'word' }}>
Expand Down
4 changes: 2 additions & 2 deletions cli/src/components/blocks/block-helpers.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@

export function trimTrailingNewlines(str: string): string {
return str.replace(/\n+$/, '')
export function trimNewlines(str: string): string {
return str.replace(/^\n+|\n+$/g, '')
}

export function sanitizePreview(text: string): string {
Expand Down
4 changes: 1 addition & 3 deletions cli/src/components/blocks/image-block.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ export const ImageBlock = memo(({ block, availableWidth }: ImageBlockProps) => {
if (inlineSequence) {
// Render inline image using terminal escape sequence
return (
<box style={{ flexDirection: 'column', gap: 0, marginTop: 1, marginBottom: 1 }}>
<box style={{ flexDirection: 'column', gap: 0 }}>
{/* Image caption/metadata */}
<text style={{ wrapMode: 'none', fg: theme.muted }}>
<span attributes={TextAttributes.DIM}>📷 </span>
Expand All @@ -84,8 +84,6 @@ export const ImageBlock = memo(({ block, availableWidth }: ImageBlockProps) => {
style={{
flexDirection: 'column',
gap: 0,
marginTop: 1,
marginBottom: 1,
paddingLeft: 1,
borderStyle: 'single',
borderColor: theme.border,
Expand Down
Loading
Loading