Skip to content

Commit 673cf6a

Browse files
committed
Merge origin/main into refactoring-phase-2
Resolved 4 merge conflicts: - cli/src/utils/constants.ts: Keep TAB_WIDTH constant + add ToolName import - cli/src/hooks/use-send-message.ts: Remove obsolete getCodebuffClient check (handled by useMessageExecution hook) - packages/agent-runtime/src/run-agent-step.ts: Keep toolDefinitions param (model/fetch not needed by prepareStepContext) - packages/billing/src/balance-calculator.ts: Keep billing-core delegation + add new drizzle imports
2 parents 7e9a558 + eed92fb commit 673cf6a

File tree

75 files changed

+3605
-1970
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

75 files changed

+3605
-1970
lines changed

.agents/claude-code-cli.ts

Lines changed: 99 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
import { createCliAgent } from './lib/create-cli-agent'
22

3-
export default createCliAgent({
3+
import type { AgentDefinition } from './types/agent-definition'
4+
5+
const baseDefinition = createCliAgent({
46
id: 'claude-code-cli',
57
displayName: 'Claude Code CLI',
68
cliName: 'Claude Code',
@@ -10,3 +12,99 @@ export default createCliAgent({
1012
'Always use `--dangerously-skip-permissions` when testing to avoid permission prompts that would block automated tests.',
1113
model: 'anthropic/claude-opus-4.5',
1214
})
15+
16+
// Constants must be inside handleSteps since it gets serialized via .toString()
17+
const definition: AgentDefinition = {
18+
...baseDefinition,
19+
handleSteps: function* ({ prompt, params, logger }) {
20+
const START_COMMAND = 'claude --dangerously-skip-permissions'
21+
const CLI_NAME = 'Claude Code'
22+
23+
yield {
24+
toolName: 'add_message',
25+
input: {
26+
role: 'assistant',
27+
content: 'I\'ll first gather context and prepare before starting the ' + CLI_NAME + ' CLI session.\n\n' +
28+
'Let me read relevant files and understand the task to provide better guidance to the CLI.',
29+
},
30+
includeToolCall: false,
31+
}
32+
33+
yield 'STEP'
34+
35+
logger.info('Starting ' + CLI_NAME + ' tmux session...')
36+
37+
const { toolResult } = yield {
38+
toolName: 'run_terminal_command',
39+
input: {
40+
command: './scripts/tmux/tmux-cli.sh start --command "' + START_COMMAND + '"',
41+
timeout_seconds: 30,
42+
},
43+
}
44+
45+
// Parse response from tmux-cli.sh (outputs plain session name on success, error to stderr on failure)
46+
let sessionName = ''
47+
let parseError = ''
48+
49+
const result = toolResult?.[0]
50+
if (result && result.type === 'json') {
51+
const value = result.value as Record<string, unknown>
52+
const stdout = typeof value?.stdout === 'string' ? value.stdout.trim() : ''
53+
const stderr = typeof value?.stderr === 'string' ? value.stderr.trim() : ''
54+
const exitCode = typeof value?.exitCode === 'number' ? value.exitCode : undefined
55+
56+
if (!stdout && !stderr) {
57+
parseError = 'tmux-cli.sh returned empty output'
58+
} else if (exitCode !== 0 || !stdout) {
59+
parseError = stderr || 'tmux-cli.sh failed with no error message'
60+
} else {
61+
sessionName = stdout
62+
}
63+
} else {
64+
parseError = 'Unexpected result type from run_terminal_command'
65+
}
66+
67+
if (!sessionName) {
68+
const errorMsg = parseError || 'Session name was empty'
69+
logger.error({ parseError: errorMsg }, 'Failed to start tmux session')
70+
yield {
71+
toolName: 'set_output',
72+
input: {
73+
overallStatus: 'failure',
74+
summary: 'Failed to start ' + CLI_NAME + ' tmux session. ' + errorMsg,
75+
sessionName: '',
76+
scriptIssues: [
77+
{
78+
script: 'tmux-cli.sh',
79+
issue: errorMsg,
80+
errorOutput: JSON.stringify(toolResult),
81+
suggestedFix: 'Ensure tmux-cli.sh outputs the session name to stdout and exits with code 0. Check that tmux is installed.',
82+
},
83+
],
84+
captures: [],
85+
},
86+
}
87+
return
88+
}
89+
90+
logger.info('Successfully started tmux session: ' + sessionName)
91+
92+
yield {
93+
toolName: 'add_message',
94+
input: {
95+
role: 'assistant',
96+
content: 'I have started a ' + CLI_NAME + ' tmux session: `' + sessionName + '`\n\n' +
97+
'I will use this session for all CLI interactions. The session name must be included in my final output.\n\n' +
98+
'Now I\'ll proceed with the task using the helper scripts:\n' +
99+
'- Send commands: `./scripts/tmux/tmux-cli.sh send "' + sessionName + '" "..."`\n' +
100+
'- Capture output: `./scripts/tmux/tmux-cli.sh capture "' + sessionName + '" --label "..."`\n' +
101+
'- Stop when done: `./scripts/tmux/tmux-cli.sh stop "' + sessionName + '"`',
102+
},
103+
includeToolCall: false,
104+
}
105+
106+
yield 'STEP_ALL'
107+
},
108+
}
109+
110+
export default definition

.agents/codebuff-local-cli.ts

Lines changed: 88 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
import { createCliAgent } from './lib/create-cli-agent'
22

3-
export default createCliAgent({
3+
import type { AgentDefinition } from './types/agent-definition'
4+
5+
const baseDefinition = createCliAgent({
46
id: 'codebuff-local-cli',
57
displayName: 'Codebuff Local CLI',
68
cliName: 'Codebuff',
@@ -9,10 +11,95 @@ export default createCliAgent({
911
permissionNote:
1012
'No permission flags needed for Codebuff local dev server.',
1113
model: 'anthropic/claude-opus-4.5',
14+
skipPrepPhase: true,
1215
spawnerPromptExtras: `**Use this agent after modifying:**
1316
- \`cli/src/components/\` - UI components, layouts, rendering
1417
- \`cli/src/hooks/\` - hooks that affect what users see
1518
- Any CLI visual elements: borders, colors, spacing, text formatting
1619
1720
**When to use:** After implementing CLI UI changes, use this to verify the visual output actually renders correctly. Unit tests and typechecks cannot catch layout bugs, rendering issues, or visual regressions. This agent captures real terminal output including colors and layout.`,
1821
})
22+
23+
// Constants must be inside handleSteps since it gets serialized via .toString()
24+
const definition: AgentDefinition = {
25+
...baseDefinition,
26+
handleSteps: function* ({ prompt, params, logger }) {
27+
const START_COMMAND = 'bun --cwd=cli run dev'
28+
const CLI_NAME = 'Codebuff'
29+
30+
logger.info('Starting ' + CLI_NAME + ' tmux session...')
31+
32+
const { toolResult } = yield {
33+
toolName: 'run_terminal_command',
34+
input: {
35+
command: './scripts/tmux/tmux-cli.sh start --command "' + START_COMMAND + '"',
36+
timeout_seconds: 30,
37+
},
38+
}
39+
40+
// Parse response from tmux-cli.sh (outputs plain session name on success, error to stderr on failure)
41+
let sessionName = ''
42+
let parseError = ''
43+
44+
const result = toolResult?.[0]
45+
if (result && result.type === 'json') {
46+
const value = result.value as Record<string, unknown>
47+
const stdout = typeof value?.stdout === 'string' ? value.stdout.trim() : ''
48+
const stderr = typeof value?.stderr === 'string' ? value.stderr.trim() : ''
49+
const exitCode = typeof value?.exitCode === 'number' ? value.exitCode : undefined
50+
51+
if (!stdout && !stderr) {
52+
parseError = 'tmux-cli.sh returned empty output'
53+
} else if (exitCode !== 0 || !stdout) {
54+
parseError = stderr || 'tmux-cli.sh failed with no error message'
55+
} else {
56+
sessionName = stdout
57+
}
58+
} else {
59+
parseError = 'Unexpected result type from run_terminal_command'
60+
}
61+
62+
if (!sessionName) {
63+
const errorMsg = parseError || 'Session name was empty'
64+
logger.error({ parseError: errorMsg }, 'Failed to start tmux session')
65+
yield {
66+
toolName: 'set_output',
67+
input: {
68+
overallStatus: 'failure',
69+
summary: 'Failed to start ' + CLI_NAME + ' tmux session. ' + errorMsg,
70+
sessionName: '',
71+
scriptIssues: [
72+
{
73+
script: 'tmux-cli.sh',
74+
issue: errorMsg,
75+
errorOutput: JSON.stringify(toolResult),
76+
suggestedFix: 'Ensure tmux-cli.sh outputs the session name to stdout and exits with code 0. Check that tmux is installed.',
77+
},
78+
],
79+
captures: [],
80+
},
81+
}
82+
return
83+
}
84+
85+
logger.info('Successfully started tmux session: ' + sessionName)
86+
87+
yield {
88+
toolName: 'add_message',
89+
input: {
90+
role: 'assistant',
91+
content: 'I have started a ' + CLI_NAME + ' tmux session: `' + sessionName + '`\n\n' +
92+
'I will use this session for all CLI interactions. The session name must be included in my final output.\n\n' +
93+
'Now I\'ll proceed with the task using the helper scripts:\n' +
94+
'- Send commands: `./scripts/tmux/tmux-cli.sh send "' + sessionName + '" "..."`\n' +
95+
'- Capture output: `./scripts/tmux/tmux-cli.sh capture "' + sessionName + '" --label "..."`\n' +
96+
'- Stop when done: `./scripts/tmux/tmux-cli.sh stop "' + sessionName + '"`',
97+
},
98+
includeToolCall: false,
99+
}
100+
101+
yield 'STEP_ALL'
102+
},
103+
}
104+
105+
export default definition

.agents/codex-cli.ts

Lines changed: 108 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
import { createCliAgent } from './lib/create-cli-agent'
22

3+
import type { AgentDefinition } from './types/agent-definition'
4+
35
/**
46
* Codex-specific review mode instructions.
57
* Codex CLI has a built-in /review command with an interactive questionnaire.
@@ -8,6 +10,8 @@ const CODEX_REVIEW_MODE_INSTRUCTIONS = `## Review Mode Instructions
810
911
Codex CLI has a built-in \`/review\` command that presents an interactive questionnaire. You must navigate it using arrow keys and Enter.
1012
13+
**Note:** A tmux session will be started for you automatically after your preparation phase. Use the session name from the assistant message that announces it.
14+
1115
### Review Type Mapping
1216
1317
The \`reviewType\` param maps to menu options (1-indexed from top):
@@ -18,25 +22,20 @@ The \`reviewType\` param maps to menu options (1-indexed from top):
1822
1923
### Workflow
2024
21-
1. **Start Codex** with permission bypass:
22-
\`\`\`bash
23-
SESSION=$(./scripts/tmux/tmux-cli.sh start --command "codex -a never -s danger-full-access")
24-
\`\`\`
25-
26-
2. **Wait for CLI to initialize**, then capture:
25+
1. **Wait for CLI to initialize**, then capture:
2726
\`\`\`bash
2827
sleep 3
2928
./scripts/tmux/tmux-cli.sh capture "$SESSION" --label "initial-state"
3029
\`\`\`
3130
32-
3. **Send the /review command**:
31+
2. **Send the /review command**:
3332
\`\`\`bash
3433
./scripts/tmux/tmux-cli.sh send "$SESSION" "/review"
3534
sleep 2
3635
./scripts/tmux/tmux-cli.sh capture "$SESSION" --label "review-menu"
3736
\`\`\`
3837
39-
4. **Navigate to the correct option** using arrow keys:
38+
3. **Navigate to the correct option** using arrow keys:
4039
- The menu starts with Option 1 selected (PR Style)
4140
- Use Down arrow to move to the desired option:
4241
- \`reviewType="pr"\`: No navigation needed, just press Enter
@@ -51,30 +50,30 @@ The \`reviewType\` param maps to menu options (1-indexed from top):
5150
./scripts/tmux/tmux-send.sh "$SESSION" --key Enter
5251
\`\`\`
5352
54-
5. **For "custom" reviewType**, after selecting option 4, you'll need to send the custom instructions from the prompt:
53+
4. **For "custom" reviewType**, after selecting option 4, you'll need to send the custom instructions from the prompt:
5554
\`\`\`bash
5655
sleep 1
5756
./scripts/tmux/tmux-cli.sh send "$SESSION" "[custom instructions from the prompt]"
5857
\`\`\`
5958
60-
6. **Wait for and capture the review output** (reviews take longer):
59+
5. **Wait for and capture the review output** (reviews take longer):
6160
\`\`\`bash
6261
./scripts/tmux/tmux-cli.sh capture "$SESSION" --label "review-output" --wait 60
6362
\`\`\`
6463
65-
7. **Parse the review output** and populate \`reviewFindings\` with:
64+
6. **Parse the review output** and populate \`reviewFindings\` with:
6665
- \`file\`: Path to the file with the issue
6766
- \`severity\`: "critical", "warning", "suggestion", or "info"
6867
- \`line\`: Line number if mentioned
6968
- \`finding\`: Description of the issue
7069
- \`suggestion\`: How to fix it
7170
72-
8. **Clean up**:
71+
7. **Clean up**:
7372
\`\`\`bash
7473
./scripts/tmux/tmux-cli.sh stop "$SESSION"
7574
\`\`\``
7675

77-
export default createCliAgent({
76+
const baseDefinition = createCliAgent({
7877
id: 'codex-cli',
7978
displayName: 'Codex CLI',
8079
cliName: 'Codex',
@@ -93,3 +92,99 @@ export default createCliAgent({
9392
},
9493
reviewModeInstructions: CODEX_REVIEW_MODE_INSTRUCTIONS,
9594
})
95+
96+
// Constants must be inside handleSteps since it gets serialized via .toString()
97+
const definition: AgentDefinition = {
98+
...baseDefinition,
99+
handleSteps: function* ({ prompt, params, logger }) {
100+
const START_COMMAND = 'codex -a never -s danger-full-access'
101+
const CLI_NAME = 'Codex'
102+
103+
yield {
104+
toolName: 'add_message',
105+
input: {
106+
role: 'assistant',
107+
content: 'I\'ll first gather context and prepare before starting the ' + CLI_NAME + ' CLI session.\n\n' +
108+
'Let me read relevant files and understand the task to provide better guidance to the CLI.',
109+
},
110+
includeToolCall: false,
111+
}
112+
113+
yield 'STEP'
114+
115+
logger.info('Starting ' + CLI_NAME + ' tmux session...')
116+
117+
const { toolResult } = yield {
118+
toolName: 'run_terminal_command',
119+
input: {
120+
command: './scripts/tmux/tmux-cli.sh start --command "' + START_COMMAND + '"',
121+
timeout_seconds: 30,
122+
},
123+
}
124+
125+
// Parse response from tmux-cli.sh (outputs plain session name on success, error to stderr on failure)
126+
let sessionName = ''
127+
let parseError = ''
128+
129+
const result = toolResult?.[0]
130+
if (result && result.type === 'json') {
131+
const value = result.value as Record<string, unknown>
132+
const stdout = typeof value?.stdout === 'string' ? value.stdout.trim() : ''
133+
const stderr = typeof value?.stderr === 'string' ? value.stderr.trim() : ''
134+
const exitCode = typeof value?.exitCode === 'number' ? value.exitCode : undefined
135+
136+
if (!stdout && !stderr) {
137+
parseError = 'tmux-cli.sh returned empty output'
138+
} else if (exitCode !== 0 || !stdout) {
139+
parseError = stderr || 'tmux-cli.sh failed with no error message'
140+
} else {
141+
sessionName = stdout
142+
}
143+
} else {
144+
parseError = 'Unexpected result type from run_terminal_command'
145+
}
146+
147+
if (!sessionName) {
148+
const errorMsg = parseError || 'Session name was empty'
149+
logger.error({ parseError: errorMsg }, 'Failed to start tmux session')
150+
yield {
151+
toolName: 'set_output',
152+
input: {
153+
overallStatus: 'failure',
154+
summary: 'Failed to start ' + CLI_NAME + ' tmux session. ' + errorMsg,
155+
sessionName: '',
156+
scriptIssues: [
157+
{
158+
script: 'tmux-cli.sh',
159+
issue: errorMsg,
160+
errorOutput: JSON.stringify(toolResult),
161+
suggestedFix: 'Ensure tmux-cli.sh outputs the session name to stdout and exits with code 0. Check that tmux is installed.',
162+
},
163+
],
164+
captures: [],
165+
},
166+
}
167+
return
168+
}
169+
170+
logger.info('Successfully started tmux session: ' + sessionName)
171+
172+
yield {
173+
toolName: 'add_message',
174+
input: {
175+
role: 'assistant',
176+
content: 'I have started a ' + CLI_NAME + ' tmux session: `' + sessionName + '`\n\n' +
177+
'I will use this session for all CLI interactions. The session name must be included in my final output.\n\n' +
178+
'Now I\'ll proceed with the task using the helper scripts:\n' +
179+
'- Send commands: `./scripts/tmux/tmux-cli.sh send "' + sessionName + '" "..."`\n' +
180+
'- Capture output: `./scripts/tmux/tmux-cli.sh capture "' + sessionName + '" --label "..."`\n' +
181+
'- Stop when done: `./scripts/tmux/tmux-cli.sh stop "' + sessionName + '"`',
182+
},
183+
includeToolCall: false,
184+
}
185+
186+
yield 'STEP_ALL'
187+
},
188+
}
189+
190+
export default definition

0 commit comments

Comments
 (0)