diff --git a/README.md b/README.md index 275ed31cd..c3a74673e 100644 --- a/README.md +++ b/README.md @@ -157,6 +157,74 @@ Learn more about the SDK [here](https://www.npmjs.com/package/@codebuff/sdk). **SDK**: Build Codebuff into your applications. Create custom tools, integrate with CI/CD, or embed coding assistance into your products. +## Advanced Usage + +### Custom Agent Workflows + +Create your own agents with specialized workflows using the `/init` command: + +```bash +codebuff +/init +``` + +This creates a custom agent structure in `.agents/` that you can customize. + +### Using Different Models + +Codebuff supports any model on OpenRouter. Override the default model per task: + +```typescript +const result = await client.run({ + agent: 'editor', + prompt: 'Refactor this function', + model: 'deepseek/deepseek-chat', // Use DeepSeek for this task +}) +``` + +### Multi-Agent Orchestration + +Codebuff's strength is coordinating multiple specialized agents: + +```typescript +const result = await client.run({ + agent: 'commander', // The orchestrator agent + prompt: 'Add authentication to the API - use file-picker to find relevant files, planner to plan changes, editor to make edits, and reviewer to validate', +}) +``` + +### CI/CD Integration + +Integrate Codebuff into your CI pipeline for automated code reviews: + +```bash +# In your CI script +codebuff "Review the changes in this PR for security issues" +``` + +### Environment Variables + +Configure Codebuff behavior via environment variables: + +```bash +# Use a specific OpenRouter API key +export OPENROUTER_API_KEY=sk-or-v1-xxxx + +# Set default model +export CODEBUFF_MODEL=anthropic/claude-3.5-sonnet + +# Enable debug mode +export DEBUG=codebuff* +``` + +### Keyboard Shortcuts (Interactive Mode) + +- `Ctrl+C` - Cancel current operation +- `Ctrl+L` - Clear screen +- `Ctrl+U` - Clear current input +- `Ctrl+P/N` - Navigate command history +- `Tab` - Autocomplete + ## Contributing to Codebuff We ❤️ contributions from the community - whether you're fixing bugs, tweaking our agents, or improving documentation. diff --git a/common/src/env.ts b/common/src/env.ts index f9328f91c..0e30987b7 100644 --- a/common/src/env.ts +++ b/common/src/env.ts @@ -2,7 +2,8 @@ import { clientEnvSchema, clientProcessEnv } from './env-schema' const parsedEnv = clientEnvSchema.safeParse(clientProcessEnv) if (!parsedEnv.success) { - throw parsedEnv.error + console.error('Environment validation failed:', parsedEnv.error.errors) + throw new Error(`Invalid environment configuration: ${parsedEnv.error.message}`) } export const env = parsedEnv.data diff --git a/common/src/util/array.ts b/common/src/util/array.ts index 44ac05dc2..baf141817 100644 --- a/common/src/util/array.ts +++ b/common/src/util/array.ts @@ -1,4 +1,7 @@ -import { compact, flattenDeep, isEqual } from 'lodash' +// Native implementations replace lodash imports to reduce bundle size +// isEqual is kept from lodash for deep equality comparison + +import isEqual from 'lodash/isEqual' export function filterDefined(array: (T | null | undefined)[]) { return array.filter((item) => item !== null && item !== undefined) as T[] @@ -8,7 +11,13 @@ type Falsey = false | undefined | null | 0 | '' type FalseyValueArray = T | Falsey | FalseyValueArray[] export function buildArray(...params: FalseyValueArray[]) { - return compact(flattenDeep(params)) as T[] + // Native implementation replaces lodash compact + flattenDeep + const flatten = (arr: unknown): T[] => { + return Array.isArray(arr) + ? arr.flatMap((item) => flatten(item)) + : [arr] as T[] + } + return flatten(params).filter((item) => item != null) as T[] } export function groupConsecutive(xs: T[], key: (x: T) => U) { diff --git a/common/src/util/object.ts b/common/src/util/object.ts index 0fc0be4df..492555344 100644 --- a/common/src/util/object.ts +++ b/common/src/util/object.ts @@ -1,4 +1,7 @@ -import { isEqual, mapValues, union } from 'lodash' +import isEqual from 'lodash/isEqual' + +// Using native implementations instead of lodash to reduce bundle size +// isEqual is kept from lodash as it handles deep equality complex cases type RemoveUndefined = { [K in keyof T as T[K] extends undefined ? never : K]: Exclude @@ -41,7 +44,8 @@ export const addObjects = ( obj1: T, obj2: T, ): T => { - const keys = union(Object.keys(obj1), Object.keys(obj2)) + // Native implementation replaces lodash union + const keys = [...new Set([...Object.keys(obj1), ...Object.keys(obj2)])] const newObj: { [key: string]: number } = {} for (const key of keys) { @@ -55,7 +59,8 @@ export const subtractObjects = ( obj1: T, obj2: T, ): T => { - const keys = union(Object.keys(obj1), Object.keys(obj2)) + // Native implementation replaces lodash union + const keys = [...new Set([...Object.keys(obj1), ...Object.keys(obj2)])] const newObj: { [key: string]: number } = {} for (const key of keys) { @@ -66,8 +71,11 @@ export const subtractObjects = ( } export const hasChanges = (obj: T, partial: Partial) => { - const currValues = mapValues(partial, (_, key: keyof T) => obj[key]) - return !isEqual(currValues, partial) + // Native implementation replaces lodash mapValues + const currValues = Object.fromEntries( + Object.keys(partial).map((key) => [key, obj[key as keyof T]]) + ) + return JSON.stringify(currValues) !== JSON.stringify(partial) } export const hasSignificantDeepChanges = ( diff --git a/common/src/util/string.ts b/common/src/util/string.ts index 506de962f..d7abb1806 100644 --- a/common/src/util/string.ts +++ b/common/src/util/string.ts @@ -1,4 +1,4 @@ -import { sumBy } from 'lodash' +// Native implementation replaces lodash sumBy to reduce bundle size export const truncateString = (str: string, maxLength: number) => { if (str.length <= maxLength) { @@ -46,7 +46,12 @@ export const truncateStringWithMessage = ({ export const isWhitespace = (character: string) => /\s/.test(character) export const randBoolFromStr = (str: string) => { - return sumBy(str.split(''), (char) => char.charCodeAt(0)) % 2 === 0 + // Native implementation replaces lodash sumBy + let sum = 0 + for (const char of str.split('')) { + sum += char.charCodeAt(0) + } + return sum % 2 === 0 } // Irregular plurals that cannot be derived from rules