UNPKG

@codebuff/sdk

Version:

Official SDK for Codebuff — AI coding agent & framework

1,563 lines (1,474 loc) 105 kB
import { createRequire } from "node:module"; var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res); var __require = /* @__PURE__ */ createRequire(import.meta.url); // ../common/src/old-constants.ts var STOP_MARKER, FIND_FILES_MARKER, API_KEY_ENV_VAR = "CODEBUFF_API_KEY", ASKED_CONFIG = "asked_config", SHOULD_ASK_CONFIG = "should_ask_config", ONE_TIME_TAGS, ONE_TIME_LABELS, FILE_READ_STATUS, HIDDEN_FILE_READ_STATUS, MAX_DATE, costModes, openaiModels, geminiModels, openrouterModels, deepseekModels, finetunedVertexModels, finetunedVertexModelNames, models, shortModelNames, providerModelNames, nonCacheableModels; var init_old_constants = __esm(() => { STOP_MARKER = "[" + "END]"; FIND_FILES_MARKER = "[" + "FIND_FILES_PLEASE]"; ONE_TIME_TAGS = []; ONE_TIME_LABELS = [ ...ONE_TIME_TAGS, ASKED_CONFIG, SHOULD_ASK_CONFIG ]; FILE_READ_STATUS = { DOES_NOT_EXIST: "[FILE_DOES_NOT_EXIST]", IGNORED: "[FILE_IGNORED_BY_GITIGNORE_OR_CODEBUFF_IGNORE]", OUTSIDE_PROJECT: "[FILE_OUTSIDE_PROJECT]", TOO_LARGE: "[FILE_TOO_LARGE]", ERROR: "[FILE_READ_ERROR]" }; HIDDEN_FILE_READ_STATUS = [ FILE_READ_STATUS.DOES_NOT_EXIST, FILE_READ_STATUS.IGNORED, FILE_READ_STATUS.OUTSIDE_PROJECT, FILE_READ_STATUS.TOO_LARGE, FILE_READ_STATUS.ERROR ]; MAX_DATE = new Date(86399999999999); costModes = [ "lite", "normal", "max", "experimental", "ask" ]; openaiModels = { gpt4_1: "gpt-4.1-2025-04-14", gpt4o: "gpt-4o-2024-11-20", gpt4omini: "gpt-4o-mini-2024-07-18", o3mini: "o3-mini-2025-01-31", o3: "o3-2025-04-16", o3pro: "o3-pro-2025-06-10", o4mini: "o4-mini-2025-04-16", generatePatch: "ft:gpt-4o-2024-08-06:manifold-markets:generate-patch-batch2:AKYtDIhk" }; geminiModels = { gemini2_5_flash: "gemini-2.5-flash-preview-05-20", gemini2_5_flash_thinking: "gemini-2.5-flash-preview-05-20:thinking", gemini2flash: "gemini-2.0-flash-001", gemini2_5_pro_preview: "gemini-2.5-pro-preview-06-05" }; openrouterModels = { openrouter_claude_sonnet_4: "anthropic/claude-4-sonnet-20250522", openrouter_claude_opus_4: "anthropic/claude-opus-4.1", openrouter_claude_3_5_haiku: "anthropic/claude-3.5-haiku-20241022", openrouter_claude_3_5_sonnet: "anthropic/claude-3.5-sonnet-20240620", openrouter_gpt4o: "openai/gpt-4o-2024-11-20", openrouter_gpt5: "openai/gpt-5", openrouter_gpt5_chat: "openai/gpt-5-chat", openrouter_gpt4o_mini: "openai/gpt-4o-mini-2024-07-18", openrouter_gpt4_1_nano: "openai/gpt-4.1-nano", openrouter_o3_mini: "openai/o3-mini-2025-01-31", openrouter_gemini2_5_pro_preview: "google/gemini-2.5-pro", openrouter_gemini2_5_flash: "google/gemini-2.5-flash", openrouter_gemini2_5_flash_thinking: "google/gemini-2.5-flash-preview:thinking", openrouter_grok_4: "x-ai/grok-4-07-09" }; deepseekModels = { deepseekChat: "deepseek-chat", deepseekReasoner: "deepseek-reasoner" }; finetunedVertexModels = { ft_filepicker_003: "196166068534771712", ft_filepicker_005: "8493203957034778624", ft_filepicker_007: "2589952415784501248", ft_filepicker_topk_001: "3676445825887633408", ft_filepicker_008: "2672143108984012800", ft_filepicker_topk_002: "1694861989844615168", ft_filepicker_010: "3808739064941641728", ft_filepicker_010_epoch_2: "6231675664466968576", ft_filepicker_topk_003: "1502192368286171136" }; finetunedVertexModelNames = { [finetunedVertexModels.ft_filepicker_003]: "ft_filepicker_003", [finetunedVertexModels.ft_filepicker_005]: "ft_filepicker_005", [finetunedVertexModels.ft_filepicker_007]: "ft_filepicker_007", [finetunedVertexModels.ft_filepicker_topk_001]: "ft_filepicker_topk_001", [finetunedVertexModels.ft_filepicker_008]: "ft_filepicker_008", [finetunedVertexModels.ft_filepicker_topk_002]: "ft_filepicker_topk_002", [finetunedVertexModels.ft_filepicker_010]: "ft_filepicker_010", [finetunedVertexModels.ft_filepicker_010_epoch_2]: "ft_filepicker_010_epoch_2", [finetunedVertexModels.ft_filepicker_topk_003]: "ft_filepicker_topk_003" }; models = { ...openaiModels, ...geminiModels, ...deepseekModels, ...openrouterModels, ...finetunedVertexModels }; shortModelNames = { "gemini-2.5-pro": models.openrouter_gemini2_5_pro_preview, "flash-2.5": models.openrouter_gemini2_5_flash, "opus-4": models.openrouter_claude_opus_4, "sonnet-4": models.openrouter_claude_sonnet_4, "sonnet-3.7": models.openrouter_claude_sonnet_4, "sonnet-3.6": models.openrouter_claude_3_5_sonnet, "sonnet-3.5": models.openrouter_claude_3_5_sonnet, "gpt-4.1": models.gpt4_1, "o3-mini": models.o3mini, o3: models.o3, "o4-mini": models.o4mini, "o3-pro": models.o3pro }; providerModelNames = { ...Object.fromEntries(Object.entries(geminiModels).map(([name, model]) => [ model, "gemini" ])), ...Object.fromEntries(Object.entries(openaiModels).map(([name, model]) => [ model, "openai" ])), ...Object.fromEntries(Object.entries(openrouterModels).map(([name, model]) => [ model, "openrouter" ])) }; nonCacheableModels = [ models.openrouter_grok_4 ]; }); // ../packages/code-map/src/parse.ts import * as fs2 from "fs"; import * as path3 from "path"; // ../packages/code-map/src/languages.ts import * as path2 from "path"; import { Language, Parser as Parser2, Query } from "web-tree-sitter"; // ../packages/code-map/src/tree-sitter-queries/tree-sitter-c_sharp-tags.scm var tree_sitter_c_sharp_tags_default = `(class_declaration name: (identifier) @identifier ) (interface_declaration name: (identifier) @identifier ) (method_declaration name: (identifier) @identifier ) ; Method calls (invocation_expression function: (identifier) @call.identifier) (invocation_expression function: (member_access_expression name: (identifier) @call.identifier)) ; Constructor calls (object_creation_expression type: (identifier) @call.identifier)`; // ../packages/code-map/src/tree-sitter-queries/tree-sitter-cpp-tags.scm var tree_sitter_cpp_tags_default = `(struct_specifier name: (type_identifier) @identifier) (declaration type: (union_specifier name: (type_identifier) @identifier)) (function_declarator declarator: (identifier) @identifier) (function_declarator declarator: (field_identifier) @identifier) (function_declarator declarator: (qualified_identifier scope: (namespace_identifier) name: (identifier) @identifier)) (type_definition declarator: (type_identifier) @identifier) (enum_specifier name: (type_identifier) @identifier) (class_specifier name: (type_identifier) @identifier) ; Function calls (call_expression function: (identifier) @call.identifier) (call_expression function: (field_expression field: (field_identifier) @call.identifier)) ; Constructor calls (class_specifier name: (type_identifier) @call.identifier) (new_expression type: (type_identifier) @call.identifier)`; // ../packages/code-map/src/tree-sitter-queries/tree-sitter-go-tags.scm var tree_sitter_go_tags_default = `( (comment)* . (function_declaration name: (identifier) @identifier) ) ( (comment)* . (method_declaration name: (field_identifier) @identifier) ) (type_spec name: (type_identifier) @identifier) (type_identifier) @identifier (call_expression function: [ (identifier) @call.identifier (parenthesized_expression (identifier) @call.identifier) (selector_expression field: (field_identifier) @call.identifier) (parenthesized_expression (selector_expression field: (field_identifier) @call.identifier)) ]) `; // ../packages/code-map/src/tree-sitter-queries/tree-sitter-java-tags.scm var tree_sitter_java_tags_default = `(class_declaration name: (identifier) @identifier) (interface_declaration name: (identifier) @identifier) @definition.interface (method_declaration name: (identifier) @identifier) (method_invocation name: (identifier) @call.identifier) (type_list (type_identifier) @call.identifier) (object_creation_expression type: (type_identifier) @call.identifier) (superclass (type_identifier) @call.identifier) `; // ../packages/code-map/src/tree-sitter-queries/tree-sitter-javascript-tags.scm var tree_sitter_javascript_tags_default = `(function_declaration name: (identifier) @identifier) (class_declaration name: (identifier) @identifier) (method_definition name: (property_identifier) @identifier) (export_statement declaration: (lexical_declaration (variable_declarator name: (identifier) @identifier))) (export_statement declaration: (variable_declaration (variable_declarator name: (identifier) @identifier))) (call_expression function: (identifier) @call.identifier) (call_expression function: (member_expression property: (property_identifier) @call.identifier)) (new_expression constructor: (identifier) @call.identifier) `; // ../packages/code-map/src/tree-sitter-queries/tree-sitter-python-tags.scm var tree_sitter_python_tags_default = `(class_definition name: (identifier) @identifier) (function_definition name: (identifier) @identifier) (call function: (identifier) @call.identifier) (call function: (attribute attribute: (identifier) @call.identifier)) `; // ../packages/code-map/src/tree-sitter-queries/tree-sitter-ruby-tags.scm var tree_sitter_ruby_tags_default = `; Method definitions ( [ (method name: (_) @identifier) (singleton_method name: (_) @identifier) ] ) (alias name: (_) @identifier) ; (setter ; (identifier) @identifier) ; Class definitions ( (comment)* . [ (class name: [ (constant) @identifier (scope_resolution name: (_) @identifier) ]) (singleton_class value: [ (constant) @identifier (scope_resolution name: (_) @identifier) ]) ] ) ; Module definitions ( (module name: [ (constant) @identifier (scope_resolution name: (_) @identifier) ]) ) ; Calls (call method: (identifier) @call.identifier) ( [(identifier) (constant)] @call.identifier (#is-not? local) (#not-match? @call.identifier "^(lambda|load|require|require_relative|__FILE__|__LINE__)$") ) `; // ../packages/code-map/src/tree-sitter-queries/tree-sitter-rust-tags.scm var tree_sitter_rust_tags_default = `(struct_item name: (type_identifier) @identifier) (enum_item name: (type_identifier) @identifier) (union_item name: (type_identifier) @identifier) (type_item name: (type_identifier) @identifier) (trait_item name: (type_identifier) @identifier) (function_item name: (identifier) @identifier) (macro_definition name: (identifier) @identifier) (mod_item name: (identifier) @identifier) (const_item name: (identifier) @identifier) (static_item name: (identifier) @identifier) ; Function and macro calls (call_expression function: (identifier) @call.identifier) (call_expression function: (field_expression field: (field_identifier) @call.identifier)) (macro_invocation macro: (identifier) @call.identifier) ; Struct instantiation (struct_expression (type_identifier) @call.identifier) ; Enum variant usage (scoped_identifier path: (identifier) name: (identifier) @call.identifier) ; implementations (impl_item trait: (type_identifier) @call.identifier) (impl_item type: (type_identifier) @call.identifier !trait)`; // ../packages/code-map/src/tree-sitter-queries/tree-sitter-typescript-tags.scm var tree_sitter_typescript_tags_default = `(function_declaration name: (identifier) @identifier) (class_declaration name: (type_identifier) @identifier) (interface_declaration name: (type_identifier) @identifier) (method_definition name: (property_identifier) @identifier) (export_statement declaration: (function_declaration name: (identifier) @identifier)) (export_statement declaration: (lexical_declaration (variable_declarator name: (identifier) @identifier))) (export_statement declaration: (variable_declaration (variable_declarator name: (identifier) @identifier))) (call_expression function: (identifier) @call.identifier) (call_expression function: (member_expression property: (property_identifier) @call.identifier)) (new_expression constructor: (identifier) @call.identifier) `; // ../packages/code-map/src/init-node.ts import * as path from "path"; import * as fs from "fs"; import { Parser } from "web-tree-sitter"; import { fileURLToPath } from "url"; var __dirname = "/Users/jahooma/codebuff/packages/code-map/src"; function hereDir() { if (typeof __dirname !== "undefined") { return __dirname; } if (typeof import.meta !== "undefined" && import.meta.url) { const dir = path.dirname(fileURLToPath(import.meta.url)); return dir; } return process.cwd(); } async function initTreeSitterForNode() { const dir = hereDir(); const sharedWasm = path.join(dir, "..", "wasm", "tree-sitter.wasm"); await Parser.init({ locateFile: (name, scriptDir) => { if (name === "tree-sitter.wasm") { if (fs.existsSync(sharedWasm)) { return sharedWasm; } const fallback = path.join(scriptDir, name); if (fs.existsSync(fallback)) { return fallback; } return sharedWasm; } return path.join(scriptDir, name); } }); } // ../packages/code-map/src/languages.ts var __dirname = "/Users/jahooma/codebuff/packages/code-map/src"; var WASM_FILES = { "tree-sitter-c-sharp.wasm": "tree-sitter-c-sharp.wasm", "tree-sitter-cpp.wasm": "tree-sitter-cpp.wasm", "tree-sitter-go.wasm": "tree-sitter-go.wasm", "tree-sitter-java.wasm": "tree-sitter-java.wasm", "tree-sitter-javascript.wasm": "tree-sitter-javascript.wasm", "tree-sitter-python.wasm": "tree-sitter-python.wasm", "tree-sitter-ruby.wasm": "tree-sitter-ruby.wasm", "tree-sitter-rust.wasm": "tree-sitter-rust.wasm", "tree-sitter-tsx.wasm": "tree-sitter-tsx.wasm", "tree-sitter-typescript.wasm": "tree-sitter-typescript.wasm" }; var languageTable = [ { extensions: [".ts"], wasmFile: WASM_FILES["tree-sitter-typescript.wasm"], queryText: tree_sitter_typescript_tags_default }, { extensions: [".tsx"], wasmFile: WASM_FILES["tree-sitter-tsx.wasm"], queryText: tree_sitter_typescript_tags_default }, { extensions: [".js", ".jsx"], wasmFile: WASM_FILES["tree-sitter-javascript.wasm"], queryText: tree_sitter_javascript_tags_default }, { extensions: [".py"], wasmFile: WASM_FILES["tree-sitter-python.wasm"], queryText: tree_sitter_python_tags_default }, { extensions: [".java"], wasmFile: WASM_FILES["tree-sitter-java.wasm"], queryText: tree_sitter_java_tags_default }, { extensions: [".cs"], wasmFile: WASM_FILES["tree-sitter-c-sharp.wasm"], queryText: tree_sitter_c_sharp_tags_default }, { extensions: [".cpp", ".hpp"], wasmFile: WASM_FILES["tree-sitter-cpp.wasm"], queryText: tree_sitter_cpp_tags_default }, { extensions: [".rs"], wasmFile: WASM_FILES["tree-sitter-rust.wasm"], queryText: tree_sitter_rust_tags_default }, { extensions: [".rb"], wasmFile: WASM_FILES["tree-sitter-ruby.wasm"], queryText: tree_sitter_ruby_tags_default }, { extensions: [".go"], wasmFile: WASM_FILES["tree-sitter-go.wasm"], queryText: tree_sitter_go_tags_default } ]; var customWasmDir; function setWasmDir(dir) { customWasmDir = dir; } function getWasmDir() { return customWasmDir; } function resolveWasmPath(wasmFileName) { const customWasmDirPath = getWasmDir(); if (customWasmDirPath) { return path2.join(customWasmDirPath, wasmFileName); } const envWasmDir = process.env.CODEBUFF_WASM_DIR; if (envWasmDir) { return path2.join(envWasmDir, wasmFileName); } const moduleDir = (() => { if (typeof __dirname !== "undefined") { return __dirname; } return process.cwd(); })(); const possiblePaths = [ path2.join(moduleDir, "..", "wasm", wasmFileName), path2.join(moduleDir, "wasm", wasmFileName), path2.join(process.cwd(), "dist", "wasm", wasmFileName) ]; for (const wasmPath of possiblePaths) { try { return wasmPath; } catch { continue; } } return possiblePaths[0]; } function tryResolveFromPackage(wasmFileName) { try { return __require.resolve(`@vscode/tree-sitter-wasm/wasm/${wasmFileName}`); } catch { return null; } } class UnifiedLanguageLoader { parserReady; constructor() { this.parserReady = initTreeSitterForNode(); } async initParser() { await this.parserReady; } async loadLanguage(wasmFile) { let wasmPath = resolveWasmPath(wasmFile); let lang; try { lang = await Language.load(wasmPath); } catch (err) { const fallbackPath = tryResolveFromPackage(wasmFile); if (fallbackPath) { lang = await Language.load(fallbackPath); } else { throw err; } } return lang; } } function findLanguageConfigByExtension(filePath) { const ext = path2.extname(filePath); return languageTable.find((c) => c.extensions.includes(ext)); } async function createLanguageConfig(filePath, runtimeLoader) { const cfg = findLanguageConfigByExtension(filePath); if (!cfg) { return; } if (!cfg.parser) { try { await runtimeLoader.initParser(); const lang = await runtimeLoader.loadLanguage(cfg.wasmFile); const parser = new Parser2; parser.setLanguage(lang); cfg.language = lang; cfg.parser = parser; cfg.query = new Query(lang, cfg.queryText); } catch (err) { throw err; } } return cfg; } var unifiedLoader = new UnifiedLanguageLoader; async function getLanguageConfig(filePath) { try { return await createLanguageConfig(filePath, unifiedLoader); } catch (err) { if (DEBUG_PARSING) { console.error("[tree-sitter] Load error for", filePath, err); } return; } } // ../packages/code-map/src/parse.ts var DEBUG_PARSING = false; var IGNORE_TOKENS = ["__init__", "__post_init__", "__call__", "constructor"]; var MAX_CALLERS = 25; async function getFileTokenScores(projectRoot, filePaths, readFile) { const startTime = Date.now(); const tokenScores = {}; const externalCalls = {}; const fileCallsMap = new Map; for (const filePath of filePaths) { const fullPath = path3.join(projectRoot, filePath); const languageConfig = await getLanguageConfig(fullPath); if (languageConfig) { let parseResults; if (readFile) { parseResults = parseTokens(filePath, languageConfig, readFile); } else { parseResults = parseTokens(fullPath, languageConfig); } const { identifiers, calls, numLines } = parseResults; const tokenScoresForFile = {}; tokenScores[filePath] = tokenScoresForFile; const dirs = path3.dirname(fullPath).split(path3.sep); const depth = dirs.length; const tokenBaseScore = 0.8 ** depth * Math.sqrt(numLines / (identifiers.length + 1)); for (const identifier of identifiers) { if (!IGNORE_TOKENS.includes(identifier)) { tokenScoresForFile[identifier] = tokenBaseScore; } } fileCallsMap.set(filePath, calls); for (const call of calls) { if (!tokenScoresForFile[call]) { externalCalls[call] = (externalCalls[call] ?? 0) + 1; } } } } const tokenDefinitionMap = new Map; const highestScores = new Map; for (const [filePath, scores] of Object.entries(tokenScores)) { for (const [token, score] of Object.entries(scores)) { const currentHighestScore = highestScores.get(token) ?? -Infinity; if (score > currentHighestScore) { highestScores.set(token, score); tokenDefinitionMap.set(token, filePath); } } } const tokenCallers = {}; for (const [callingFile, calls] of fileCallsMap.entries()) { for (const call of calls) { const definingFile = tokenDefinitionMap.get(call); if (!definingFile || callingFile === definingFile) { continue; } if (call in {}) { continue; } if (!tokenCallers[definingFile]) { tokenCallers[definingFile] = {}; } if (!tokenCallers[definingFile][call]) { tokenCallers[definingFile][call] = []; } const callerFiles = tokenCallers[definingFile][call]; if (callerFiles.length < MAX_CALLERS && !callerFiles.includes(callingFile)) { callerFiles.push(callingFile); } } } for (const scores of Object.values(tokenScores)) { for (const token of Object.keys(scores)) { const numCalls = externalCalls[token] ?? 0; if (typeof numCalls !== "number") continue; scores[token] *= 1 + Math.log(1 + numCalls); scores[token] = Math.round(scores[token] * 1000) / 1000; } } if (DEBUG_PARSING) { const endTime = Date.now(); console.log(`Parsed ${filePaths.length} files in ${endTime - startTime}ms`); try { fs2.writeFileSync("../debug/debug-parse.json", JSON.stringify({ tokenCallers, tokenScores, fileCallsMap, externalCalls })); } catch {} } return { tokenScores, tokenCallers }; } function parseTokens(filePath, languageConfig, readFile) { const { parser, query } = languageConfig; try { const sourceCode = readFile ? readFile(filePath) : fs2.readFileSync(filePath, "utf8"); if (sourceCode === null) { return { numLines: 0, identifiers: [], calls: [] }; } const numLines = sourceCode.match(/\n/g)?.length ?? 0 + 1; if (!parser || !query) { throw new Error("Parser or query not found"); } const parseResults = parseFile(parser, query, sourceCode); const identifiers = Array.from(new Set(parseResults.identifier)); const calls = Array.from(new Set(parseResults["call.identifier"])); if (DEBUG_PARSING) { console.log(` Parsing ${filePath}:`); console.log("Identifiers:", identifiers); console.log("Calls:", calls); } return { numLines, identifiers: identifiers ?? [], calls: calls ?? [] }; } catch (e) { if (DEBUG_PARSING) { console.error(`Error parsing query: ${e}`); console.log(filePath); } return { numLines: 0, identifiers: [], calls: [] }; } } function parseFile(parser, query, sourceCode) { const tree = parser.parse(sourceCode); if (!tree) { return {}; } const captures = query.captures(tree.rootNode); const result = {}; for (const capture of captures) { const { name, node } = capture; if (!result[name]) { result[name] = []; } result[name].push(node.text); } return result; } // src/client.ts import path8 from "path"; // src/run-state.ts import * as os from "os"; // ../common/src/types/session-state.ts import { z as z8 } from "zod/v4"; // ../common/src/constants/agents.ts var AGENT_PERSONAS = { base: { displayName: "Buffy the Base Agent", purpose: "Base agent that orchestrates the full response." }, ask: { displayName: "Ask Mode Agent", purpose: "Base ask-mode agent that orchestrates the full response." }, thinker: { displayName: "Theo the Theorizer", purpose: "Does deep thinking given the current messages and a specific prompt to focus on. Use this to help you solve a specific problem." }, "file-explorer": { displayName: "Dora The File Explorer", purpose: "Expert at exploring a codebase and finding relevant files." }, "file-picker": { displayName: "Fletcher the File Fetcher", purpose: "Expert at finding relevant files in a codebase." }, researcher: { displayName: "Reid Searcher the Researcher", purpose: "Expert at researching topics using web search and documentation." }, planner: { displayName: "Peter Plan", purpose: "Agent that formulates a comprehensive plan to a prompt.", hidden: true }, reviewer: { displayName: "Nit Pick Nick the Reviewer", purpose: "Reviews file changes and responds with critical feedback. Use this after making any significant change to the codebase; otherwise, no need to use this agent for minor changes since it takes a second." }, "agent-builder": { displayName: "Bob the Agent Builder", purpose: "Creates new agent templates for the codebuff multi-agent system", hidden: false } }; var AGENT_IDS = Object.keys(AGENT_PERSONAS); var AGENT_NAMES = Object.fromEntries(Object.entries(AGENT_PERSONAS).map(([agentType, persona]) => [ agentType, persona.displayName ])); var UNIQUE_AGENT_NAMES = Array.from(new Set(Object.values(AGENT_PERSONAS).filter((persona) => !("hidden" in persona) || !persona.hidden).map((persona) => persona.displayName))); var AGENT_NAME_TO_TYPES = Object.entries(AGENT_NAMES).reduce((acc, [type, name]) => { if (!acc[name]) acc[name] = []; acc[name].push(type); return acc; }, {}); var MAX_AGENT_STEPS_DEFAULT = 25; // ../common/src/util/file.ts import { z as z2 } from "zod/v4"; // ../common/src/json-config/constants.ts import { z } from "zod/v4"; var codebuffConfigFile = "codebuff.json"; var StartupProcessSchema = z.object({ name: z.string().min(1, "Process name is required").describe("A user-friendly name for the process. Should be one word and unique."), command: z.string().min(1, "Command is required").describe("The actual shell command to execute."), cwd: z.string().optional().describe("The working directory from which to run the command."), enabled: z.boolean().optional().default(true).describe("Whether this process should be run"), stdoutFile: z.string().optional().describe("Path to write the process's stdout. If not specified, stderr is not stored."), stderrFile: z.string().optional().describe("Path to write the process's stderr. If not specified, stderr will be put into the stdoutFile.") }).describe("Defines a single startup process."); var FileChangeHook = z.object({ name: z.string().min(1, "Hook name is required").describe("A user-friendly name for the hook. Should be one word and unique."), command: z.string().min(1, "Command is required").describe("The actual shell command to execute."), cwd: z.string().optional().describe("The working directory from which to run the command."), filePattern: z.string().optional().describe("Glob pattern to match files."), enabled: z.boolean().optional().default(true).describe("Whether this command should be run") }).describe("Defines a single file change hook."); var CodebuffConfigSchema = z.looseObject({ description: z.any().optional().describe("Does nothing. Put any thing you want here!"), startupProcesses: z.array(StartupProcessSchema).optional().describe("An array of startup processes."), fileChangeHooks: z.array(FileChangeHook).optional().describe("An array of commands to run on file changes."), maxAgentSteps: z.number().optional().default(MAX_AGENT_STEPS_DEFAULT).describe("Maximum number of turns agent will take before being forced to end"), baseAgent: z.string().optional().describe("Specify default base agent"), addedSpawnableAgents: z.array(z.string()).optional().describe("Specify additional agents that the base agent can spawn"), removedSpawnableAgents: z.array(z.string()).optional().describe("Specify which agents the base agent cannot spawn"), spawnableAgents: z.array(z.string()).optional().describe("Specify complete list of spawnable agents for the base agent") }).describe(`Defines the overall Codebuff configuration file (e.g., ${codebuffConfigFile}). This schema defines the top-level structure of the configuration. This schema can be found at https://www.codebuff.com/config`); // ../common/src/util/file.ts var FileTreeNodeSchema = z2.object({ name: z2.string(), type: z2.enum(["file", "directory"]), children: z2.lazy(() => z2.array(FileTreeNodeSchema).optional()), filePath: z2.string() }); var FileVersionSchema = z2.object({ path: z2.string(), content: z2.string() }); var customToolDefinitionsSchema = z2.record(z2.string(), z2.object({ inputJsonSchema: z2.any(), endsAgentStep: z2.boolean().optional().default(false), description: z2.string().optional(), exampleInputs: z2.record(z2.string(), z2.any()).array().optional() })).default(() => ({})); var ProjectFileContextSchema = z2.object({ projectRoot: z2.string(), cwd: z2.string(), fileTree: z2.array(z2.custom()), fileTokenScores: z2.record(z2.string(), z2.record(z2.string(), z2.number())), tokenCallers: z2.record(z2.string(), z2.record(z2.string(), z2.array(z2.string()))).optional(), knowledgeFiles: z2.record(z2.string(), z2.string()), userKnowledgeFiles: z2.record(z2.string(), z2.string()).optional(), agentTemplates: z2.record(z2.string(), z2.any()).default(() => ({})), customToolDefinitions: customToolDefinitionsSchema, codebuffConfig: CodebuffConfigSchema.optional(), gitChanges: z2.object({ status: z2.string(), diff: z2.string(), diffCached: z2.string(), lastCommitMessages: z2.string() }), changesSinceLastChat: z2.record(z2.string(), z2.string()), shellConfigFiles: z2.record(z2.string(), z2.string()), systemInfo: z2.object({ platform: z2.string(), shell: z2.string(), nodeVersion: z2.string(), arch: z2.string(), homedir: z2.string(), cpus: z2.number() }) }); // ../common/src/types/messages/codebuff-message.ts import z7 from "zod/v4"; // ../common/src/types/messages/content-part.ts import z6 from "zod/v4"; // ../common/src/types/messages/provider-metadata.ts import z4 from "zod/v4"; // ../common/src/types/json.ts import z3 from "zod/v4"; var jsonValueSchema = z3.lazy(() => z3.union([ z3.null(), z3.string(), z3.number(), z3.boolean(), jsonObjectSchema, jsonArraySchema ])); var jsonObjectSchema = z3.lazy(() => z3.record(z3.string(), jsonValueSchema)); var jsonArraySchema = z3.lazy(() => z3.array(jsonValueSchema)); // ../common/src/types/messages/provider-metadata.ts var providerMetadataSchema = z4.record(z4.string(), z4.record(z4.string(), jsonValueSchema)); // ../common/src/types/messages/data-content.ts import z5 from "zod/v4"; var dataContentSchema = z5.union([ z5.string(), z5.instanceof(Uint8Array), z5.instanceof(ArrayBuffer), z5.custom((value) => globalThis.Buffer?.isBuffer(value) ?? false, { message: "Must be a Buffer" }) ]); // ../common/src/types/messages/content-part.ts var textPartSchema = z6.object({ type: z6.literal("text"), text: z6.string(), providerOptions: providerMetadataSchema.optional() }); var imagePartSchema = z6.object({ type: z6.literal("image"), image: z6.union([dataContentSchema, z6.instanceof(URL)]), mediaType: z6.string().optional(), providerOptions: providerMetadataSchema.optional() }); var filePartSchema = z6.object({ type: z6.literal("file"), data: z6.union([dataContentSchema, z6.instanceof(URL)]), filename: z6.string().optional(), mediaType: z6.string(), providerOptions: providerMetadataSchema.optional() }); var reasoningPartSchema = z6.object({ type: z6.literal("reasoning"), text: z6.string(), providerOptions: providerMetadataSchema.optional() }); var toolCallPartSchema = z6.object({ type: z6.literal("tool-call"), toolCallId: z6.string(), toolName: z6.string(), input: z6.record(z6.string(), z6.unknown()), providerOptions: providerMetadataSchema.optional(), providerExecuted: z6.boolean().optional() }); var toolResultOutputSchema = z6.discriminatedUnion("type", [ z6.object({ type: z6.literal("json"), value: jsonValueSchema }), z6.object({ type: z6.literal("media"), data: z6.string(), mediaType: z6.string() }) ]); var toolResultPartSchema = z6.object({ type: z6.literal("tool-result"), toolCallId: z6.string(), toolName: z6.string(), output: toolResultOutputSchema.array(), providerOptions: providerMetadataSchema.optional() }); // ../common/src/types/messages/codebuff-message.ts var auxiliaryDataSchema = z7.object({ providerOptions: providerMetadataSchema.optional(), timeToLive: z7.union([z7.literal("agentStep"), z7.literal("userPrompt")]).optional(), keepDuringTruncation: z7.boolean().optional() }); var systemMessageSchema = z7.object({ role: z7.literal("system"), content: z7.string() }).and(auxiliaryDataSchema); var userMessageSchema = z7.object({ role: z7.literal("user"), content: z7.union([ z7.string(), z7.discriminatedUnion("type", [ textPartSchema, imagePartSchema, filePartSchema ]).array() ]) }).and(auxiliaryDataSchema); var assistantMessageSchema = z7.object({ role: z7.literal("assistant"), content: z7.union([ z7.string(), z7.discriminatedUnion("type", [ textPartSchema, reasoningPartSchema, toolCallPartSchema ]).array() ]) }).and(auxiliaryDataSchema); var toolMessageSchema = z7.object({ role: z7.literal("tool"), content: toolResultPartSchema }).and(auxiliaryDataSchema); var messageSchema = z7.union([ systemMessageSchema, userMessageSchema, assistantMessageSchema, toolMessageSchema ]).and(z7.object({ providerOptions: providerMetadataSchema.optional(), timeToLive: z7.union([z7.literal("agentStep"), z7.literal("userPrompt")]).optional(), keepDuringTruncation: z7.boolean().optional() })); // ../common/src/types/session-state.ts var toolCallSchema = z8.object({ toolName: z8.string(), toolCallId: z8.string(), input: z8.record(z8.string(), z8.any()) }); var subgoalSchema = z8.object({ objective: z8.string().optional(), status: z8.enum(["NOT_STARTED", "IN_PROGRESS", "COMPLETE", "ABORTED"]).optional(), plan: z8.string().optional(), logs: z8.string().array() }); var AgentStateSchema = z8.lazy(() => z8.object({ agentId: z8.string(), agentType: z8.string().nullable(), agentContext: z8.record(z8.string(), subgoalSchema), ancestorRunIds: z8.string().array().default(() => []), runId: z8.string().optional(), subagents: AgentStateSchema.array(), childRunIds: z8.string().array().default(() => []), messageHistory: messageSchema.array(), stepsRemaining: z8.number(), creditsUsed: z8.number().default(0), directCreditsUsed: z8.number().default(0), output: z8.record(z8.string(), z8.any()).optional(), parentId: z8.string().optional() })); var AgentOutputSchema = z8.discriminatedUnion("type", [ z8.object({ type: z8.literal("structuredOutput"), value: z8.record(z8.string(), z8.any()).or(z8.null()) }), z8.object({ type: z8.literal("lastMessage"), value: z8.any() }), z8.object({ type: z8.literal("allMessages"), value: z8.array(z8.any()) }), z8.object({ type: z8.literal("error"), message: z8.string() }) ]); var AgentTemplateTypeList = [ "base", "base_lite", "base_max", "base_experimental", "claude4_gemini_thinking", "superagent", "base_agent_builder", "ask", "planner", "dry_run", "thinker", "file_picker", "file_explorer", "researcher", "reviewer", "agent_builder", "example_programmatic" ]; var AgentTemplateTypes = Object.fromEntries(AgentTemplateTypeList.map((name) => [name, name.replaceAll("_", "-")])); var agentTemplateTypeSchema = z8.enum(AgentTemplateTypeList); var SessionStateSchema = z8.object({ fileContext: ProjectFileContextSchema, mainAgentState: AgentStateSchema }); function getInitialAgentState() { return { agentId: "main-agent", agentType: null, agentContext: {}, ancestorRunIds: [], runId: undefined, subagents: [], childRunIds: [], messageHistory: [], stepsRemaining: MAX_AGENT_STEPS_DEFAULT, creditsUsed: 0, directCreditsUsed: 0, output: undefined, parentId: undefined }; } function getInitialSessionState(fileContext) { return { mainAgentState: getInitialAgentState(), fileContext }; } // src/run-state.ts function processAgentDefinitions(agentDefinitions) { const processedAgentTemplates = {}; agentDefinitions.forEach((definition) => { const processedConfig = { ...definition }; if (processedConfig.handleSteps && typeof processedConfig.handleSteps === "function") { processedConfig.handleSteps = processedConfig.handleSteps.toString(); } if (processedConfig.id) { processedAgentTemplates[processedConfig.id] = processedConfig; } }); return processedAgentTemplates; } function processCustomToolDefinitions(customToolDefinitions) { return Object.fromEntries(customToolDefinitions.map((toolDefinition) => [ toolDefinition.toolName, { inputJsonSchema: toolDefinition.inputJsonSchema, description: toolDefinition.description, endsAgentStep: toolDefinition.endsAgentStep, exampleInputs: toolDefinition.exampleInputs } ])); } async function computeProjectIndex(cwd, projectFiles) { const filePaths = Object.keys(projectFiles).sort(); const fileTree = buildFileTree(filePaths); let fileTokenScores = {}; let tokenCallers = {}; if (filePaths.length > 0) { try { const tokenData = await getFileTokenScores(cwd, filePaths, (filePath) => projectFiles[filePath] || null); fileTokenScores = tokenData.tokenScores; tokenCallers = tokenData.tokenCallers; } catch (error) { console.warn("Failed to generate parsed symbol scores:", error); } } return { fileTree, fileTokenScores, tokenCallers }; } function deriveKnowledgeFiles(projectFiles) { const knowledgeFiles = {}; for (const [filePath, fileContents] of Object.entries(projectFiles)) { const lowercasePathName = filePath.toLowerCase(); if (lowercasePathName.endsWith("knowledge.md") || lowercasePathName.endsWith("claude.md")) { knowledgeFiles[filePath] = fileContents; } } return knowledgeFiles; } async function initialSessionState(cwd, options) { const { projectFiles = {}, agentDefinitions = [] } = options; let { knowledgeFiles } = options; if (knowledgeFiles === undefined) { knowledgeFiles = deriveKnowledgeFiles(projectFiles); } const processedAgentTemplates = processAgentDefinitions(agentDefinitions); const processedCustomToolDefinitions = processCustomToolDefinitions(options.customToolDefinitions ?? []); const { fileTree, fileTokenScores, tokenCallers } = await computeProjectIndex(cwd, projectFiles); const initialState = getInitialSessionState({ projectRoot: cwd, cwd, fileTree, fileTokenScores, tokenCallers, knowledgeFiles, userKnowledgeFiles: {}, agentTemplates: processedAgentTemplates, customToolDefinitions: processedCustomToolDefinitions, gitChanges: { status: "", diff: "", diffCached: "", lastCommitMessages: "" }, changesSinceLastChat: {}, shellConfigFiles: {}, systemInfo: { platform: process.platform, shell: process.platform === "win32" ? "cmd.exe" : "bash", nodeVersion: process.version, arch: process.arch, homedir: os.homedir(), cpus: os.cpus().length ?? 1 } }); if (options.maxAgentSteps) { initialState.mainAgentState.stepsRemaining = options.maxAgentSteps; } return initialState; } async function generateInitialRunState({ cwd, projectFiles, knowledgeFiles, agentDefinitions, customToolDefinitions, maxAgentSteps }) { return { sessionState: await initialSessionState(cwd, { projectFiles, knowledgeFiles, agentDefinitions, customToolDefinitions, maxAgentSteps }), output: { type: "error", message: "No output yet" } }; } function withAdditionalMessage({ runState, message }) { const newRunState = JSON.parse(JSON.stringify(runState)); newRunState.sessionState.mainAgentState.messageHistory.push(message); return newRunState; } function withMessageHistory({ runState, messages }) { const newRunState = JSON.parse(JSON.stringify(runState)); newRunState.sessionState.mainAgentState.messageHistory = messages; return newRunState; } async function applyOverridesToSessionState(cwd, baseSessionState, overrides) { const sessionState = JSON.parse(JSON.stringify(baseSessionState)); if (overrides.maxAgentSteps !== undefined) { sessionState.mainAgentState.stepsRemaining = overrides.maxAgentSteps; } if (overrides.projectFiles !== undefined) { const { fileTree, fileTokenScores, tokenCallers } = await computeProjectIndex(cwd, overrides.projectFiles); sessionState.fileContext.fileTree = fileTree; sessionState.fileContext.fileTokenScores = fileTokenScores; sessionState.fileContext.tokenCallers = tokenCallers; if (overrides.knowledgeFiles === undefined) { sessionState.fileContext.knowledgeFiles = deriveKnowledgeFiles(overrides.projectFiles); } } if (overrides.knowledgeFiles !== undefined) { sessionState.fileContext.knowledgeFiles = overrides.knowledgeFiles; } if (overrides.agentDefinitions !== undefined) { const processedAgentTemplates = processAgentDefinitions(overrides.agentDefinitions); sessionState.fileContext.agentTemplates = { ...sessionState.fileContext.agentTemplates, ...processedAgentTemplates }; } if (overrides.customToolDefinitions !== undefined) { const processedCustomToolDefinitions = processCustomToolDefinitions(overrides.customToolDefinitions); sessionState.fileContext.customToolDefinitions = { ...sessionState.fileContext.customToolDefinitions, ...processedCustomToolDefinitions }; } return sessionState; } function buildFileTree(filePaths) { const tree = {}; for (const filePath of filePaths) { const parts = filePath.split("/"); for (let i = 0;i < parts.length; i++) { const currentPath = parts.slice(0, i + 1).join("/"); const isFile = i === parts.length - 1; if (!tree[currentPath]) { tree[currentPath] = { name: parts[i], type: isFile ? "file" : "directory", filePath: currentPath, children: isFile ? undefined : [] }; } } } const rootNodes = []; const processed = new Set; for (const [path4, node] of Object.entries(tree)) { if (processed.has(path4)) continue; const parentPath = path4.substring(0, path4.lastIndexOf("/")); if (parentPath && tree[parentPath]) { const parent = tree[parentPath]; if (parent.children && !parent.children.some((child) => child.filePath === path4)) { parent.children.push(node); } } else { rootNodes.push(node); } processed.add(path4); } function sortNodes(nodes) { nodes.sort((a, b) => { if (a.type !== b.type) { return a.type === "directory" ? -1 : 1; } return a.name.localeCompare(b.name); }); for (const node of nodes) { if (node.children) { sortNodes(node.children); } } } sortNodes(rootNodes); return rootNodes; } // src/tools/change-file.ts import fs3 from "fs"; import path4 from "path"; import { applyPatch } from "diff"; import z9 from "zod/v4"; var FileChangeSchema = z9.object({ type: z9.enum(["patch", "file"]), path: z9.string(), content: z9.string() }); function changeFile(parameters, cwd) { if (cwd.includes("../")) { throw new Error("cwd cannot include ../"); } const fileChange = FileChangeSchema.parse(parameters); const lines = fileChange.content.split(` `); const { created, modified, invalid, patchFailed } = applyChanges(cwd, [ fileChange ]); const results = []; for (const file of created) { results.push({ file, message: "Created new file", unifiedDiff: lines.join(` `) }); } for (const file of modified) { results.push({ file, message: "Updated file", unifiedDiff: lines.join(` `) }); } for (const file of patchFailed) { results.push({ file, errorMessage: `Failed to apply patch.`, patch: lines.join(` `) }); } for (const file of invalid) { results.push({ file, errorMessage: "Failed to write to file: file path caused an error or file could not be written" }); } if (results.length !== 1) { throw new Error(`Internal error: Unexpected result length while modifying files: ${results.length}`); } return [{ type: "json", value: results[0] }]; } function applyChanges(projectRoot, changes) { const created = []; const modified = []; const patchFailed = []; const invalid = []; for (const change of changes) { const { path: filePath, content, type } = change; try { const fullPath = path4.join(projectRoot, filePath); const fileExists = fs3.existsSync(fullPath); if (!fileExists) { const dirPath = path4.dirname(fullPath); fs3.mkdirSync(dirPath, { recursive: true }); } if (type === "file") { fs3.writeFileSync(fullPath, content); } else { const oldContent = fs3.readFileSync(fullPath, "utf-8"); const newContent = applyPatch(oldContent, content); if (newContent === false) { patchFailed.push(filePath); continue; } fs3.writeFileSync(fullPath, newContent); } if (fileExists) { modified.push(filePath); } else { created.push(filePath); } } catch (error) { console.error(`Failed to apply patch to ${filePath}:`, error, content); invalid.push(filePath); } } return { created, modified, invalid, patchFailed }; } // src/tools/code-search.ts import { spawn } from "child_process"; import * as path5 from "path"; // src/native/ripgrep.ts import { join as join4, dirname as dirname3 } from "path"; import { existsSync as existsSync2 } from "fs"; import { fileURLToPath as fileURLToPath2 } from "url"; var __dirname = "/Users/jahooma/codebuff/sdk/src/native"; function getBundledRgPath(importMetaUrl) { if (process.env.CODEBUFF_RG_PATH) { return process.env.CODEBUFF_RG_PATH; } const platform = process.platform; const arch = process.arch; let platformDir; if (platform === "win32" && arch === "x64") { platformDir = "x64-win32"; } else if (platform === "darwin" && arch === "arm64") { platformDir = "arm64-darwin"; } else if (platform === "darwin" && arch === "x64") { platformDir = "x64-darwin"; } else if (platform === "linux" && arch === "arm64") { platformDir = "arm64-linux"; } else if (platform === "linux" && arch === "x64") { platformDir = "x64-linux"; } else { throw new Error(`Unsupported platform: ${platform}-${arch}`); } const binaryName = platform === "win32" ? "rg.exe" : "rg"; let vendorPath; if (importMetaUrl) { const currentFile = fileURLToPath2(importMetaUrl); const currentDir = dirname3(currentFile); const devPath = join4(currentDir, "..", "..", "vendor", "ripgrep", platformDir, binaryName); if (existsSync2(devPath)) { vendorPath = devPath; } } if (!vendorPath) { if (typeof __dirname !== "undefined") { const cjsPath = join4(__dirname, "..", "..", "vendor", "ripgrep", platformDir, binaryName); if (existsSync2(cjsPath)) { vendorPath = cjsPath; } } } if (vendorPath && existsSync2(vendorPath)) { return vendorPath; } const distVendorPath = join4(process.cwd(), "node_modules", "@codebuff", "sdk", "dist", "vendor", "ripgrep", platformDir, binaryName); if (existsSync2(distVendorPath)) { return distVendorPath; } throw new Error(`Ripgrep binary not found for ${platform}-${arch}. ` + `Expected at: ${vendorPath} or ${distVendorPath}. ` + `Please run 'npm run fetch-ripgrep' or set CODEBUFF_RG_PATH environment variable.`); } // src/tools/code-search.ts function codeSearch({ projectPath, pattern, flags, cwd, maxResults = 30 }) { return new Promise((resolve2) => { let stdout = ""; let stderr = ""; const flagsArray = (flags || "").split(" ").filter(Boolean); let searchCwd = projectPath; if (cwd) { const requestedPath = path5.resolve(projectPath, cwd); if (!requestedPath.startsWith(projectPath)) { resolve2([ { type: "json", value: { errorMessage: `Invalid cwd: Path '${cwd}' is outside the project directory.` } } ]); return; } searchCwd = requestedPath; } const args = [...flagsArray, pattern, "."]; const rgPath = getBundledRgPath(import.meta.url); const childProcess = spawn(rgPath, args, { cwd: searchCwd, stdio: ["ignore", "pipe", "pipe"] }); childProcess.stdout.on("data", (data) => { stdout += data.toString(); }); childProcess.stderr.on("data", (data) => { stderr += data.toString(); }); childProcess.on("close", (code) => { const lines = stdout.split(` `); const limitedLines = lines.slice(0, maxResults); const limitedStdout = limitedLines.join(` `); const finalStdout = lines.length > maxResults ? limitedStdout + ` [Results limited to ${maxResults} of ${lines.length} total matches]` : limitedStdout; const maxLength = 1e4; const truncatedStdout = finalStdout.length > maxLength ? finalStdout.substring(0, maxLength) + ` [Output truncated]` : finalStdout; const maxErrorLength = 1000; const truncatedStderr = stderr.length > maxErrorLength ? stderr.substring(0, maxErrorLength) + ` [Error output truncated]` : stderr; const result = { stdout: truncatedStdout, ...truncatedStderr && { stderr: truncatedStderr }, ...code !== null && { exitCode: code }, message: "Code search completed" }; resolve2([ { type: "json", value: result } ]); }); childProcess.on("error", (error) => { resolve2([ { type: "json", value: { errorMessage: `Failed to execute ripgrep: ${error.message}. Vendored ripgrep not found; ensure @codebuff/sdk