Skip to content

Commit 6a107de

Browse files
committed
sdk: add images
1 parent 660fa34 commit 6a107de

File tree

6 files changed

+188
-79
lines changed

6 files changed

+188
-79
lines changed

sdk/CHANGELOG.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,20 +2,36 @@
22

33
All notable changes to the @codebuff/sdk package will be documented in this file.
44

5+
## [0.1.8] - 2025-08-13
6+
7+
### Added
8+
9+
- `withAdditionalMessage` and `withMessageHistory` functions
10+
- Add images, files, or other messages to a previous run
11+
- Modify the history of any run
12+
- `initialSessionState` and `generateInitialRunState` functions
13+
- Create a SessionState or RunState object from scratch
14+
15+
### Removed
16+
17+
- `getInitialSessionState` function
18+
519
## [0.1.7] - 2025-08-12
620

721
### Updated types! AgentConfig has been renamed to AgentDefinition.
822

923
## [0.1.5] - 2025-08-09
1024

1125
### Added
26+
1227
- Complete `CodebuffClient`
1328
- Better docs
1429
- New `run()` api
1530

1631
## [0.0.1] - 2025-08-05
1732

1833
### Added
34+
1935
- Initial release of the Codebuff SDK
2036
- `CodebuffClient` class for interacting with Codebuff agents
2137
- `runNewChat` method for starting new chat sessions

sdk/README.md

Lines changed: 34 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -26,48 +26,75 @@ npm install @codebuff/sdk
2626
```typescript
2727
import * as fs from 'fs'
2828
import * as os from 'os'
29-
import { CodebuffClient } from '@codebuff/sdk'
29+
30+
import {
31+
CodebuffClient,
32+
generateInitialRunState,
33+
withAdditionalMessage,
34+
} from '@codebuff/sdk'
3035

3136
// Available after running `codebuff login`
3237
const apiKey = JSON.parse(
3338
fs
3439
.readFileSync(os.homedir() + '/.config/manicode/credentials.json')
3540
.toString(),
3641
).default.authToken
42+
const cwd = process.cwd()
3743

3844
const client = new CodebuffClient({
3945
apiKey,
40-
cwd: process.cwd(),
46+
cwd,
4147
onError: (e) => console.error('Codebuff error:', e.message),
4248
// Optional: Override the implementation of specific tools.
4349
overrideTools: {},
4450
})
4551

4652
// Single run
53+
const emptyRun = generateInitialRunState({ cwd })
54+
55+
const runWithExampleImage = withAdditionalMessage({
56+
runState: emptyRun,
57+
message: {
58+
role: 'user',
59+
content: [
60+
{
61+
type: 'image',
62+
image: new URL(
63+
'https://upload.wikimedia.org/wikipedia/en/a/a9/Example.jpg',
64+
),
65+
},
66+
],
67+
},
68+
})
69+
4770
const run1 = await client.run({
4871
agent: 'base',
49-
prompt: 'Add console.log("Hello from Codebuff") to src/index.ts',
72+
prompt: 'What is depicted in the attached image?',
73+
previousRun: runWithExampleImage,
74+
handleEvent: (event) => {
75+
console.log('event from run1:', { event })
76+
},
5077
})
5178

5279
// Continue same session with follow‑up
5380
const run2 = await client.run({
5481
agent: 'base',
55-
prompt: 'Create a basic test file for it',
82+
prompt: 'What about the text? (ignoring the pictures)',
5683
previousRun: run1,
5784

5885
// Stream events (optional)
5986
handleEvent: (event) => {
6087
// event includes streamed updates like assistant messages and tool calls
61-
console.log('event:', event)
88+
console.log('event from run2:', event)
6289
},
6390

6491
// Custom agents (optional)
6592
agentDefinitions: [
6693
{
6794
id: 'my-awesome-agent',
6895
model: 'openai/gpt-5',
69-
displayName: 'My awesome agent'
70-
instructionsPrompt: 'Do something awesome'
96+
displayName: 'My awesome agent',
97+
instructionsPrompt: 'Do something awesome',
7198
// ... other AgentDefinition properties
7299
},
73100
],

sdk/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"name": "@codebuff/sdk",
33
"private": false,
44
"access": "public",
5-
"version": "0.1.7",
5+
"version": "0.1.8",
66
"description": "Official SDK for Codebuff — AI coding agent & framework",
77
"license": "MIT",
88
"type": "module",

sdk/src/client.ts

Lines changed: 1 addition & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { execFileSync } from 'child_process'
2-
import os from 'os'
32

43
import { CODEBUFF_BINARY } from './constants'
4+
import { initialSessionState, type RunState } from './run-state'
55
import { changeFile } from './tools/change-file'
66
import { getFiles } from './tools/read-files'
77
import { runTerminalCommand } from './tools/run-terminal-command'
@@ -11,11 +11,9 @@ import {
1111
type ServerAction,
1212
} from '../../common/src/actions'
1313
import { API_KEY_ENV_VAR } from '../../common/src/constants'
14-
import { getInitialSessionState } from '../../common/src/types/session-state'
1514

1615
import type { AgentDefinition } from '../../common/src/templates/initial-agents-dir/types/agent-definition'
1716
import type { PrintModeEvent } from '../../common/src/types/print-mode'
18-
import type { SessionState } from '../../common/src/types/session-state'
1917

2018
type ClientToolName = 'write_file' | 'run_terminal_command'
2119

@@ -39,11 +37,6 @@ export type CodebuffClientOptions = {
3937
>
4038
}
4139

42-
type RunState = {
43-
sessionState: SessionState
44-
toolResults: ServerAction<'prompt-response'>['toolResults']
45-
}
46-
4740
export class CodebuffClient {
4841
public cwd: string
4942

@@ -273,64 +266,3 @@ export class CodebuffClient {
273266
}
274267
}
275268
}
276-
277-
function initialSessionState(
278-
cwd: string,
279-
options: {
280-
// TODO: Parse projectFiles into fileTree, fileTokenScores, tokenCallers
281-
projectFiles?: Record<string, string>
282-
knowledgeFiles?: Record<string, string>
283-
agentDefinitions?: AgentDefinition[]
284-
maxAgentSteps?: number
285-
},
286-
) {
287-
const { knowledgeFiles = {}, agentDefinitions = [] } = options
288-
289-
// Process agentDefinitions array and convert handleSteps functions to strings
290-
const processedAgentTemplates: Record<string, any> = {}
291-
agentDefinitions.forEach((definition) => {
292-
const processedConfig = { ...definition } as Record<string, any>
293-
if (
294-
processedConfig.handleSteps &&
295-
typeof processedConfig.handleSteps === 'function'
296-
) {
297-
processedConfig.handleSteps = processedConfig.handleSteps.toString()
298-
}
299-
if (processedConfig.id) {
300-
processedAgentTemplates[processedConfig.id] = processedConfig
301-
}
302-
})
303-
304-
const initialState = getInitialSessionState({
305-
projectRoot: cwd,
306-
cwd,
307-
fileTree: [],
308-
fileTokenScores: {},
309-
tokenCallers: {},
310-
knowledgeFiles,
311-
userKnowledgeFiles: {},
312-
agentTemplates: processedAgentTemplates,
313-
gitChanges: {
314-
status: '',
315-
diff: '',
316-
diffCached: '',
317-
lastCommitMessages: '',
318-
},
319-
changesSinceLastChat: {},
320-
shellConfigFiles: {},
321-
systemInfo: {
322-
platform: process.platform,
323-
shell: process.platform === 'win32' ? 'cmd.exe' : 'bash',
324-
nodeVersion: process.version,
325-
arch: process.arch,
326-
homedir: os.homedir(),
327-
cpus: os.cpus().length ?? 1,
328-
},
329-
})
330-
331-
if (options.maxAgentSteps) {
332-
initialState.mainAgentState.stepsRemaining = options.maxAgentSteps
333-
}
334-
335-
return initialState
336-
}

sdk/src/index.ts

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,10 @@
11
export { CodebuffClient } from './client'
2+
export {
3+
generateInitialRunState,
4+
initialSessionState,
5+
withAdditionalMessage,
6+
withMessageHistory,
7+
} from './run-state'
28
export { WebSocketHandler } from './websocket-client'
3-
export { getInitialSessionState } from '../../common/src/types/session-state'
4-
export type { AgentDefinition } from '../../common/src/templates/initial-agents-dir/types/agent-definition'
9+
10+
export type { AgentDefinition } from '../../common/src/templates/initial-agents-dir/types/agent-definition'

sdk/src/run-state.ts

Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
import * as os from 'os'
2+
3+
import { getInitialSessionState } from '../../common/src/types/session-state'
4+
5+
import type { ServerAction } from '../../common/src/actions'
6+
import type { AgentDefinition } from '../../common/src/templates/initial-agents-dir/types/agent-definition'
7+
import type { CodebuffMessage } from '../../common/src/types/message'
8+
import type { SessionState } from '../../common/src/types/session-state'
9+
10+
export type RunState = {
11+
sessionState: SessionState
12+
toolResults: ServerAction<'prompt-response'>['toolResults']
13+
}
14+
15+
export function initialSessionState(
16+
cwd: string,
17+
options: {
18+
// TODO: Parse projectFiles into fileTree, fileTokenScores, tokenCallers
19+
projectFiles?: Record<string, string>
20+
knowledgeFiles?: Record<string, string>
21+
agentDefinitions?: AgentDefinition[]
22+
maxAgentSteps?: number
23+
},
24+
) {
25+
const { knowledgeFiles = {}, agentDefinitions = [] } = options
26+
27+
// Process agentDefinitions array and convert handleSteps functions to strings
28+
const processedAgentTemplates: Record<string, any> = {}
29+
agentDefinitions.forEach((definition) => {
30+
const processedConfig = { ...definition } as Record<string, any>
31+
if (
32+
processedConfig.handleSteps &&
33+
typeof processedConfig.handleSteps === 'function'
34+
) {
35+
processedConfig.handleSteps = processedConfig.handleSteps.toString()
36+
}
37+
if (processedConfig.id) {
38+
processedAgentTemplates[processedConfig.id] = processedConfig
39+
}
40+
})
41+
42+
const initialState = getInitialSessionState({
43+
projectRoot: cwd,
44+
cwd,
45+
fileTree: [],
46+
fileTokenScores: {},
47+
tokenCallers: {},
48+
knowledgeFiles,
49+
userKnowledgeFiles: {},
50+
agentTemplates: processedAgentTemplates,
51+
gitChanges: {
52+
status: '',
53+
diff: '',
54+
diffCached: '',
55+
lastCommitMessages: '',
56+
},
57+
changesSinceLastChat: {},
58+
shellConfigFiles: {},
59+
systemInfo: {
60+
platform: process.platform,
61+
shell: process.platform === 'win32' ? 'cmd.exe' : 'bash',
62+
nodeVersion: process.version,
63+
arch: process.arch,
64+
homedir: os.homedir(),
65+
cpus: os.cpus().length ?? 1,
66+
},
67+
})
68+
69+
if (options.maxAgentSteps) {
70+
initialState.mainAgentState.stepsRemaining = options.maxAgentSteps
71+
}
72+
73+
return initialState
74+
}
75+
76+
export function generateInitialRunState({
77+
cwd,
78+
projectFiles,
79+
knowledgeFiles,
80+
agentDefinitions,
81+
maxAgentSteps,
82+
}: {
83+
cwd: string
84+
projectFiles?: Record<string, string>
85+
knowledgeFiles?: Record<string, string>
86+
agentDefinitions?: AgentDefinition[]
87+
maxAgentSteps?: number
88+
}): RunState {
89+
return {
90+
sessionState: initialSessionState(cwd, {
91+
projectFiles,
92+
knowledgeFiles,
93+
agentDefinitions,
94+
maxAgentSteps,
95+
}),
96+
toolResults: [],
97+
}
98+
}
99+
100+
export function withAdditionalMessage({
101+
runState,
102+
message,
103+
}: {
104+
runState: RunState
105+
message: CodebuffMessage
106+
}): RunState {
107+
// Deep copy
108+
const newRunState = JSON.parse(JSON.stringify(runState)) as typeof runState
109+
110+
newRunState.sessionState.mainAgentState.messageHistory.push(message)
111+
112+
return newRunState
113+
}
114+
115+
export function withMessageHistory({
116+
runState,
117+
messages,
118+
}: {
119+
runState: RunState
120+
messages: CodebuffMessage[]
121+
}): RunState {
122+
// Deep copy
123+
const newRunState = JSON.parse(JSON.stringify(runState)) as typeof runState
124+
125+
newRunState.sessionState.mainAgentState.messageHistory = messages
126+
127+
return newRunState
128+
}

0 commit comments

Comments
 (0)