Skip to content

Commit d23e975

Browse files
committed
Merge remote-tracking branch 'origin/main' into brandon-cli-deploy-work
2 parents 783e239 + 9919719 commit d23e975

File tree

11 files changed

+223
-93
lines changed

11 files changed

+223
-93
lines changed
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
import { SecretAgentDefinition } from 'types/secret-agent-definition'
2+
import { createBase2 } from './base2'
3+
4+
const definition: SecretAgentDefinition = {
5+
...createBase2('fast'),
6+
id: 'base2-with-files-input',
7+
displayName: 'Buffy the Fast Orchestrator',
8+
9+
inputSchema: {
10+
prompt: {
11+
type: 'string',
12+
description: 'A coding task to complete',
13+
},
14+
params: {
15+
type: 'object',
16+
properties: {
17+
maxContextLength: {
18+
type: 'number',
19+
},
20+
filesToRead: {
21+
type: 'array',
22+
items: {
23+
type: 'string',
24+
},
25+
},
26+
},
27+
required: ['filesToRead'],
28+
},
29+
},
30+
31+
handleSteps: function* ({ params }) {
32+
yield {
33+
toolName: 'read_files',
34+
input: { paths: params?.filesToRead || [] },
35+
}
36+
37+
let steps = 0
38+
while (true) {
39+
steps++
40+
// Run context-pruner before each step
41+
yield {
42+
toolName: 'spawn_agent_inline',
43+
input: {
44+
agent_type: 'context-pruner',
45+
params: params ?? {},
46+
},
47+
includeToolCall: false,
48+
} as any
49+
50+
const { stepsComplete } = yield 'STEP'
51+
if (stepsComplete) break
52+
}
53+
},
54+
}
55+
export default definition

.agents/orchestrator/iterative-orchestrator/iterative-orchestrator-step.ts

Lines changed: 22 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -37,15 +37,27 @@ const definition: SecretAgentDefinition = {
3737
type: 'object',
3838
properties: {
3939
title: { type: 'string' },
40-
prompt: { type: 'string' },
40+
prompt: {
41+
type: 'string',
42+
description:
43+
'The exact prompt that will be sent to the agent that will implement or decide the step',
44+
},
4145
type: { type: 'string', enum: ['implementation', 'decision'] },
42-
successCriteria: { type: 'array', items: { type: 'string' } },
43-
filesToReadHints: { type: 'array', items: { type: 'string' } },
46+
filesToReadHints: {
47+
type: 'array',
48+
items: { type: 'string' },
49+
description:
50+
'Include paths to files that will help the agent implement or decide the step',
51+
},
4452
},
4553
required: ['title', 'prompt', 'type'],
4654
},
4755
},
48-
notes: { type: 'string' },
56+
notes: {
57+
type: 'string',
58+
description:
59+
'Any notes for the future orchestator agent. What you want to accomplish with these steps, why you chose them, and what you want to accomplish next. Also, estimate the remaining number of steps needed to complete the task.',
60+
},
4961
},
5062
required: ['isDone', 'nextSteps', 'notes'],
5163
},
@@ -61,20 +73,12 @@ Important: you *must* make at least one tool call, via <codebuff_tool_call> synt
6173
- If only one step is needed next, return a single-item array.
6274
- Mark isDone=true only when the overall task is truly complete.
6375
64-
Return JSON via set_output with:
65-
{
66-
isDone: boolean,
67-
nextSteps: [
68-
{
69-
title: string,
70-
prompt: string, // exact prompt to give to the implementor or decision maker
71-
type: 'implementation' | 'decision', // whether this is a coding task or decision
72-
successCriteria?: string[] // 3-6 bullet checks that show this step is done
73-
filesToReadHints?: string[] // optional globs/paths hints
74-
}
75-
],
76-
notes: string // short rationale for these steps
77-
}
76+
## Guidelines
77+
- It's better to make small changes at a time and validate them as you go. Writing a lot of code without testing it or typechecking it or validating it in some way is not good!
78+
- Keep the scope of your changes as small as possible.
79+
- Try to complete your task in as few steps as possible.
80+
- There is a time limit on the number of steps you can take. If you reach the limit, you will be cut off prematurely before the task is complete.
81+
- Prefer not to parallelize steps if they are at all related, because you can get a better result by doing them sequentially.
7882
`,
7983
stepPrompt: `Important: you *must* make at least one tool call, via <codebuff_tool_call> syntax, in every response message!`,
8084
}

.agents/orchestrator/iterative-orchestrator/iterative-orchestrator.ts

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ type StepInfo = {
99
title: string
1010
prompt: string
1111
type: 'implementation' | 'decision'
12-
successCriteria?: string[]
1312
filesToReadHints?: string[]
1413
}
1514

@@ -22,7 +21,7 @@ const definition: SecretAgentDefinition = {
2221
'Orchestrates the completion of a large task through batches of independent steps.',
2322
outputMode: 'structured_output',
2423
toolNames: ['spawn_agents', 'set_output'],
25-
spawnableAgents: ['iterative-orchestrator-step', 'base2-fast'],
24+
spawnableAgents: ['iterative-orchestrator-step', 'base2-with-files-input'],
2625

2726
inputSchema: {
2827
prompt: { type: 'string', description: 'Overall task to complete' },
@@ -38,8 +37,10 @@ const definition: SecretAgentDefinition = {
3837
}[] = []
3938
let completed = false
4039
let iteration = 0
40+
const maxIterations = 15
4141

42-
while (!completed) {
42+
while (!completed && iteration < maxIterations) {
43+
const remainingIterations = maxIterations - iteration
4344
iteration++
4445
// 1) Plan next step
4546
const planningBundle = [
@@ -93,18 +94,23 @@ const definition: SecretAgentDefinition = {
9394
break
9495
}
9596

97+
const reminder =
98+
remainingIterations <= 5
99+
? `<reminder>You are approaching the MAXIMUM NUMBER OF ITERATIONS! You have ${remainingIterations} iterations left to complete the task, or at least get it into a working state. You must try to wrap up the task in the remaining iterations or be cut off!</system_remender>`
100+
: `<reminder>You have ${remainingIterations} steps left to complete the task.</reminder>`
101+
96102
// 3) Execute all steps in parallel
97103
const executionAgents = steps.map((step) => {
98104
if (step.type === 'decision') {
99105
return {
100-
agent_type: 'base2-fast',
101-
prompt: `DECISION TASK: ${step.prompt}\n\nThis is a decision-making step, not an implementation step. Your job is to research options, analyze trade-offs, and make a clear recommendation with rationale. Write out your decision in the last message. Do not create a file with your decision.`,
106+
agent_type: 'base2-with-files-input',
107+
prompt: `DECISION TASK: ${step.prompt}\n\nThis is a decision-making step, not an implementation step. Your job is to research options, analyze trade-offs, and make a clear recommendation with rationale. Write out your decision in the last message. Do not create a file with your decision. ${reminder}`,
102108
params: { filesToRead: step.filesToReadHints || [] },
103109
}
104110
} else {
105111
return {
106-
agent_type: 'base2-fast',
107-
prompt: step.prompt,
112+
agent_type: 'base2-with-files-input',
113+
prompt: `${step.prompt}\n\n${reminder}`,
108114
params: { filesToRead: step.filesToReadHints || [] },
109115
}
110116
}

common/src/types/contracts/database.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ export type FinishAgentRunFn = (params: {
7777
}) => Promise<void>
7878

7979
export type AddAgentStepFn = (params: {
80+
apiKey: string
8081
userId: string | undefined
8182
agentRunId: string
8283
stepNumber: number
@@ -87,6 +88,6 @@ export type AddAgentStepFn = (params: {
8788
errorMessage?: string
8889
startTime: Date
8990
logger: Logger
90-
}) => Promise<string>
91+
}) => Promise<string | null>
9192

9293
export type DatabaseAgentCache = Map<string, AgentTemplate | null>

npm-app/release/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "codebuff",
3-
"version": "1.0.502",
3+
"version": "1.0.503",
44
"description": "AI coding agent",
55
"license": "MIT",
66
"bin": {

packages/agent-runtime/src/run-agent-step.ts

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -450,6 +450,20 @@ export async function loopAgentSteps(
450450
ParamsExcluding<
451451
FinishAgentRunFn,
452452
'runId' | 'status' | 'totalSteps' | 'directCredits' | 'totalCredits'
453+
> &
454+
ParamsExcluding<
455+
typeof runAgentStep,
456+
'agentState' | 'prompt' | 'spawnParams' | 'system'
457+
> &
458+
ParamsExcluding<
459+
AddAgentStepFn,
460+
| 'agentRunId'
461+
| 'stepNumber'
462+
| 'credits'
463+
| 'childRunIds'
464+
| 'messageId'
465+
| 'status'
466+
| 'startTime'
453467
>,
454468
): Promise<{
455469
agentState: AgentState
@@ -677,14 +691,6 @@ export async function loopAgentSteps(
677691
messageId,
678692
} = await runAgentStep({
679693
...params,
680-
userId,
681-
userInputId,
682-
clientSessionId,
683-
fingerprintId,
684-
onResponseChunk,
685-
localAgentTemplates,
686-
agentType,
687-
fileContext,
688694
agentState: currentAgentState,
689695
prompt: currentPrompt,
690696
spawnParams: currentParams,
@@ -693,15 +699,14 @@ export async function loopAgentSteps(
693699

694700
if (newAgentState.runId) {
695701
await addAgentStep({
696-
userId,
702+
...params,
697703
agentRunId: newAgentState.runId,
698704
stepNumber: totalSteps,
699705
credits: newAgentState.directCreditsUsed - creditsBefore,
700706
childRunIds: newAgentState.childRunIds.slice(childrenBefore),
701707
messageId,
702708
status: 'completed',
703709
startTime,
704-
logger,
705710
})
706711
} else {
707712
logger.error('No runId found for agent state after finishing agent run')

sdk/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "@codebuff/sdk",
33
"private": false,
4-
"version": "0.4.4",
4+
"version": "0.4.5",
55
"description": "Official SDK for Codebuff — AI coding agent & framework",
66
"license": "Apache-2.0",
77
"type": "module",

sdk/src/impl/agent-runtime.ts

Lines changed: 49 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { trackEvent } from '@codebuff/common/analytics'
22
import { success } from '@codebuff/common/util/error'
33

44
import {
5+
addAgentStep,
56
fetchAgentFromDatabase,
67
finishAgentRun,
78
getUserInfoFromApiKey,
@@ -12,10 +13,13 @@ import type {
1213
AgentRuntimeDeps,
1314
AgentRuntimeScopedDeps,
1415
} from '@codebuff/common/types/contracts/agent-runtime'
16+
import type { Logger } from '@codebuff/common/types/contracts/logger'
1517

16-
export const CLI_AGENT_RUNTIME_IMPL: Omit<
18+
export function getAgentRuntimeImpl(params: {
19+
logger?: Logger
20+
apiKey: string
21+
}): Omit<
1722
AgentRuntimeDeps & AgentRuntimeScopedDeps,
18-
| 'addAgentStep'
1923
| 'promptAiSdkStream'
2024
| 'promptAiSdk'
2125
| 'promptAiSdkStructured'
@@ -26,50 +30,54 @@ export const CLI_AGENT_RUNTIME_IMPL: Omit<
2630
| 'requestOptionalFile'
2731
| 'sendAction'
2832
| 'sendSubagentChunk'
29-
> = {
30-
// Database
31-
getUserInfoFromApiKey,
32-
fetchAgentFromDatabase,
33-
startAgentRun,
34-
finishAgentRun,
35-
// addAgentStep: AddAgentStepFn
33+
> {
34+
const { logger, apiKey } = params
35+
36+
return {
37+
// Database
38+
getUserInfoFromApiKey,
39+
fetchAgentFromDatabase,
40+
startAgentRun,
41+
finishAgentRun,
42+
addAgentStep,
3643

37-
// Billing
38-
consumeCreditsWithFallback: async () =>
39-
success({
40-
chargedToOrganization: false,
41-
}),
44+
// Billing
45+
consumeCreditsWithFallback: async () =>
46+
success({
47+
chargedToOrganization: false,
48+
}),
4249

43-
// LLM
44-
// promptAiSdkStream: PromptAiSdkStreamFn,
45-
// promptAiSdk: PromptAiSdkFn,
46-
// promptAiSdkStructured: PromptAiSdkStructuredFn,
50+
// LLM
51+
// promptAiSdkStream: PromptAiSdkStreamFn,
52+
// promptAiSdk: PromptAiSdkFn,
53+
// promptAiSdkStructured: PromptAiSdkStructuredFn,
4754

48-
// Mutable State
49-
databaseAgentCache: new Map(),
50-
liveUserInputRecord: {},
51-
sessionConnections: {},
55+
// Mutable State
56+
databaseAgentCache: new Map(),
57+
liveUserInputRecord: {},
58+
sessionConnections: {},
5259

53-
// Analytics
54-
trackEvent,
60+
// Analytics
61+
trackEvent,
5562

56-
// Other
57-
logger: {
58-
info: () => {},
59-
debug: () => {},
60-
warn: () => {},
61-
error: () => {},
62-
},
63-
fetch: globalThis.fetch,
63+
// Other
64+
logger: logger ?? {
65+
info: () => {},
66+
debug: () => {},
67+
warn: () => {},
68+
error: () => {},
69+
},
70+
fetch: globalThis.fetch,
6471

65-
// Client (WebSocket)
66-
// handleStepsLogChunk: HandleStepsLogChunkFn,
67-
// requestToolCall: RequestToolCallFn,
68-
// requestMcpToolData: RequestMcpToolDataFn,
69-
// requestFiles: RequestFilesFn,
70-
// requestOptionalFile: RequestOptionalFileFn,
71-
// sendAction: SendActionFn,
72-
// sendSubagentChunk: SendSubagentChunkFn,
72+
// Client (WebSocket)
73+
// handleStepsLogChunk: HandleStepsLogChunkFn,
74+
// requestToolCall: RequestToolCallFn,
75+
// requestMcpToolData: RequestMcpToolDataFn,
76+
// requestFiles: RequestFilesFn,
77+
// requestOptionalFile: RequestOptionalFileFn,
78+
// sendAction: SendActionFn,
79+
// sendSubagentChunk: SendSubagentChunkFn,
7380

74-
apiKey: process.env.CODEBUFF_API_KEY ?? '',
81+
apiKey,
82+
}
7583
}

0 commit comments

Comments
 (0)