@build0.ai/agent-core 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,146 @@
1
+ # @build0.ai/agent-core
2
+
3
+ Core framework for Build0 autonomous coding agents. This package provides the workflow orchestration engine, plugin system, and utilities needed to build autonomous agents.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install @build0.ai/agent-core
9
+ # or
10
+ pnpm add @build0.ai/agent-core
11
+ ```
12
+
13
+ ## Quick Start
14
+
15
+ ```typescript
16
+ import { Runner, credentialManager } from "@build0.ai/agent-core";
17
+ import { myPlugin } from "./plugins/my-plugin.js";
18
+
19
+ async function main() {
20
+ // Fetch credentials from remote API
21
+ const credentials = await credentialManager.fetchCredentials();
22
+
23
+ // Create runner and register plugins
24
+ const runner = new Runner();
25
+ await runner.registerPlugin(myPlugin, {
26
+ API_KEY: credentials.MY_API_KEY!,
27
+ });
28
+
29
+ // Run workflow
30
+ await runner.runWorkflow("./workflow.json");
31
+ }
32
+
33
+ main();
34
+ ```
35
+
36
+ ## Features
37
+
38
+ - **Declarative Workflows**: Define agent behavior in JSON
39
+ - **Type-Safe Plugin System**: Build plugins with compile-time validation
40
+ - **MCP Tools Integration**: Tools are exposed via Model Context Protocol
41
+ - **Claude Agent SDK**: Leverages Claude for intelligent coding tasks
42
+ - **Credential Management**: Secure remote credential fetching and decryption
43
+ - **Structured Logging**: JSON-formatted logs for easy parsing
44
+
45
+ ## Workflow Format
46
+
47
+ ```json
48
+ {
49
+ "steps": [
50
+ {
51
+ "id": "step_1",
52
+ "type": "tool",
53
+ "tool": "my_tool",
54
+ "args": {
55
+ "param": "value"
56
+ }
57
+ },
58
+ {
59
+ "id": "step_2",
60
+ "type": "ai_agent",
61
+ "args": {
62
+ "prompt": "Analyze the output: {{ step_1.output }}",
63
+ "working_dir": "./workspace"
64
+ }
65
+ }
66
+ ]
67
+ }
68
+ ```
69
+
70
+ ## Creating Plugins
71
+
72
+ ```typescript
73
+ import { McpPlugin, BasePluginConfig, ToolDefinition } from "@build0.ai/agent-core";
74
+ import { z } from "zod";
75
+
76
+ interface MyPluginConfig extends BasePluginConfig {
77
+ API_KEY: string;
78
+ }
79
+
80
+ export const myPlugin: McpPlugin<MyPluginConfig> = {
81
+ name: "my_plugin",
82
+ config: {} as MyPluginConfig,
83
+
84
+ async init(config: MyPluginConfig): Promise<void> {
85
+ if (!config.API_KEY) {
86
+ throw new Error("API_KEY is required");
87
+ }
88
+ this.config = config;
89
+ },
90
+
91
+ registerTools(): ToolDefinition[] {
92
+ return [
93
+ {
94
+ name: "my_tool",
95
+ description: "Does something useful",
96
+ zodSchema: z.object({
97
+ param: z.string().describe("A parameter"),
98
+ }),
99
+ },
100
+ ];
101
+ },
102
+
103
+ async handleToolCall(name, args) {
104
+ if (name === "my_tool") {
105
+ // Implementation
106
+ return {
107
+ content: [{ type: "text", text: "Result" }],
108
+ };
109
+ }
110
+ throw new Error(`Unknown tool: ${name}`);
111
+ },
112
+ };
113
+ ```
114
+
115
+ ## Environment Variables
116
+
117
+ The framework uses these environment variables:
118
+
119
+ - `BUILD0_AGENT_CREDENTIALS_URL` - Remote credentials API endpoint
120
+ - `BUILD0_AGENT_AUTH_TOKEN` - Authentication token for credentials API
121
+ - `BUILD0_AGENT_ENCRYPTION_KEY` - AES-256 key for credential decryption (hex)
122
+ - `BUILD0_TRIGGER_PAYLOAD` - JSON payload from external triggers (auto-injected as `{{ input }}`)
123
+ - `ANTHROPIC_API_KEY` - API key for Claude (required by Claude Agent SDK)
124
+
125
+ ## Exports
126
+
127
+ ### Classes
128
+ - `Runner` - Main workflow orchestration engine
129
+
130
+ ### Singletons
131
+ - `logger` - Structured JSON logger
132
+ - `credentialManager` - Credential fetching service
133
+
134
+ ### Types
135
+ - `McpPlugin<TConfig>` - Plugin interface
136
+ - `BasePluginConfig` - Base plugin configuration
137
+ - `ToolDefinition` - Tool metadata with Zod schema
138
+ - `Workflow` - Workflow definition
139
+ - `WorkflowStep` - Single workflow step
140
+ - `Credential` - Credential structure
141
+ - `AgentResult` - AI agent execution result
142
+ - Various log message types
143
+
144
+ ## License
145
+
146
+ MIT
@@ -0,0 +1,73 @@
1
+ import { SDKMessage } from "@anthropic-ai/claude-agent-sdk";
2
+ export type LogLevel = "info" | "warn" | "error" | "debug";
3
+ export interface BaseLogMessage {
4
+ timestamp: string;
5
+ level: LogLevel;
6
+ type: string;
7
+ stepId?: string;
8
+ message?: string;
9
+ }
10
+ export interface StepStartMessage extends BaseLogMessage {
11
+ type: "step_start";
12
+ stepId: string;
13
+ stepType: "ai_agent" | "tool";
14
+ toolName?: string;
15
+ }
16
+ export interface StepCompleteMessage extends BaseLogMessage {
17
+ type: "step_complete";
18
+ stepId: string;
19
+ duration?: number;
20
+ outputPreview?: string;
21
+ }
22
+ export interface StepErrorMessage extends BaseLogMessage {
23
+ type: "step_error";
24
+ stepId: string;
25
+ error: string;
26
+ }
27
+ export interface StepSkipMessage extends BaseLogMessage {
28
+ type: "step_skip";
29
+ stepId: string;
30
+ reason: string;
31
+ }
32
+ export interface AiAgentPromptMessage extends BaseLogMessage {
33
+ type: "ai_agent_prompt";
34
+ stepId: string;
35
+ promptLength: number;
36
+ truncated: boolean;
37
+ fullPromptPath?: string;
38
+ }
39
+ export interface AiAgentResponseMessage extends BaseLogMessage {
40
+ type: "ai_agent_response";
41
+ stepId: string;
42
+ responseLength: number;
43
+ responsePreview: string;
44
+ }
45
+ export interface ToolCallMessage extends BaseLogMessage {
46
+ type: "tool_call";
47
+ toolCallId: string;
48
+ toolName: string;
49
+ args: Record<string, any>;
50
+ }
51
+ export interface ToolResultMessage extends BaseLogMessage {
52
+ type: "tool_result";
53
+ toolName: string;
54
+ toolCallId: string;
55
+ resultLength: number;
56
+ resultPreview: string;
57
+ hasJsonResult?: boolean;
58
+ }
59
+ export interface ClaudeCodeSdkMessage extends BaseLogMessage {
60
+ type: "claude_code_sdk";
61
+ sdkMessage: SDKMessage;
62
+ }
63
+ export interface ClaudeCodeStderrMessage extends BaseLogMessage {
64
+ type: "claude_code_stderr";
65
+ stderr: string;
66
+ }
67
+ export interface GenericLogMessage extends BaseLogMessage {
68
+ type: "log";
69
+ }
70
+ export type LogMessage = StepStartMessage | StepCompleteMessage | StepErrorMessage | StepSkipMessage | AiAgentPromptMessage | AiAgentResponseMessage | ToolCallMessage | ToolResultMessage | ClaudeCodeSdkMessage | ClaudeCodeStderrMessage | GenericLogMessage;
71
+ export type LogMessageType = LogMessage["type"];
72
+ export declare function createLogMessage<T extends LogMessage>(message: Omit<T, "timestamp">): T;
73
+ //# sourceMappingURL=log-types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"log-types.d.ts","sourceRoot":"","sources":["../../src/core/log-types.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ // Log message types for structured agent progress tracking
2
+ // Helper function to create typed log messages
3
+ export function createLogMessage(message) {
4
+ return {
5
+ ...message,
6
+ timestamp: new Date().toISOString(),
7
+ };
8
+ }
@@ -0,0 +1,26 @@
1
+ import { McpPlugin } from "./types.js";
2
+ /**
3
+ * Framework runner for autonomous agents.
4
+ * Handles workflow execution and plugin management.
5
+ */
6
+ export declare class Runner {
7
+ private plugins;
8
+ private pluginRegistry;
9
+ /**
10
+ * Register a plugin with its configuration.
11
+ * TypeScript will enforce the config type matches the plugin's requirements.
12
+ */
13
+ registerPlugin<TConfig extends Record<string, any>>(plugin: McpPlugin<TConfig>, config: TConfig): Promise<void>;
14
+ /**
15
+ * Validate that all required tools are available and there are no conflicts.
16
+ */
17
+ private validateTools;
18
+ private createMcpServer;
19
+ /**
20
+ * Run a workflow from a file.
21
+ * @param workflowPath - Path to the workflow JSON file
22
+ * @param initialContext - Optional additional context to merge
23
+ */
24
+ runWorkflow(workflowPath: string, initialContext?: Record<string, any>): Promise<void>;
25
+ }
26
+ //# sourceMappingURL=runner.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runner.d.ts","sourceRoot":"","sources":["../../src/core/runner.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAoBvC;;;GAGG;AACH,qBAAa,MAAM;IACjB,OAAO,CAAC,OAAO,CAAmB;IAClC,OAAO,CAAC,cAAc,CAAqC;IAE3D;;;OAGG;IACG,cAAc,CAAC,OAAO,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EACtD,MAAM,EAAE,SAAS,CAAC,OAAO,CAAC,EAC1B,MAAM,EAAE,OAAO,GACd,OAAO,CAAC,IAAI,CAAC;IAchB;;OAEG;IACH,OAAO,CAAC,aAAa;IA8CrB,OAAO,CAAC,eAAe;IA8BvB;;;;OAIG;IACG,WAAW,CACf,YAAY,EAAE,MAAM,EACpB,cAAc,GAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAM,GACvC,OAAO,CAAC,IAAI,CAAC;CAwJjB"}
@@ -0,0 +1,214 @@
1
+ import path from "path";
2
+ import fs from "fs/promises";
3
+ import os from "os";
4
+ import { loadWorkflow } from "../utils/workflow.js";
5
+ import { runAgent } from "../utils/agent.js";
6
+ import { logger } from "../utils/logger.js";
7
+ import { createSdkMcpServer, tool } from "@anthropic-ai/claude-agent-sdk";
8
+ function interpolate(text, context) {
9
+ if (typeof text !== "string")
10
+ return text;
11
+ return text.replace(/\{\{\s*([\w\.]+)\s*\}\}/g, (_, path) => {
12
+ const keys = path.split(".");
13
+ let value = context;
14
+ for (const key of keys) {
15
+ value = value?.[key];
16
+ }
17
+ // If value is an object, stringify it. If string, return as is.
18
+ return value !== undefined
19
+ ? typeof value === "object"
20
+ ? JSON.stringify(value, null, 2)
21
+ : String(value)
22
+ : "";
23
+ });
24
+ }
25
+ /**
26
+ * Framework runner for autonomous agents.
27
+ * Handles workflow execution and plugin management.
28
+ */
29
+ export class Runner {
30
+ plugins = [];
31
+ pluginRegistry = new Map();
32
+ /**
33
+ * Register a plugin with its configuration.
34
+ * TypeScript will enforce the config type matches the plugin's requirements.
35
+ */
36
+ async registerPlugin(plugin, config) {
37
+ await plugin.init(config);
38
+ this.plugins.push(plugin);
39
+ this.pluginRegistry.set(plugin.name, plugin);
40
+ logger.info(`Plugin ${plugin.name} registered with ${plugin.registerTools().length} tools: ${plugin
41
+ .registerTools()
42
+ .map((t) => t.name)
43
+ .join(", ")}`);
44
+ }
45
+ /**
46
+ * Validate that all required tools are available and there are no conflicts.
47
+ */
48
+ validateTools(workflow) {
49
+ // Build a map of all available tools from registered plugins
50
+ const availableTools = new Map(); // toolName -> pluginName
51
+ for (const plugin of this.plugins) {
52
+ const tools = plugin.registerTools();
53
+ for (const tool of tools) {
54
+ if (availableTools.has(tool.name)) {
55
+ const existingPlugin = availableTools.get(tool.name);
56
+ throw new Error(`Duplicate tool name detected: "${tool.name}" is provided by both "${existingPlugin}" and "${plugin.name}" plugins`);
57
+ }
58
+ availableTools.set(tool.name, plugin.name);
59
+ }
60
+ }
61
+ // Check that all tools referenced in workflow steps are available
62
+ const missingTools = [];
63
+ for (const step of workflow.steps) {
64
+ if (step.type === "tool" && step.tool) {
65
+ if (!availableTools.has(step.tool)) {
66
+ missingTools.push(step.tool);
67
+ }
68
+ }
69
+ }
70
+ if (missingTools.length > 0) {
71
+ throw new Error(`Workflow references tools that are not available: ${missingTools.join(", ")}\n` +
72
+ `Available tools: ${Array.from(availableTools.keys()).join(", ")}\n` +
73
+ `Make sure the required plugins are registered in index.ts`);
74
+ }
75
+ logger.info(`✅ All required workflow tools are available:\n${Array.from(availableTools.keys())
76
+ .map((t) => `- ${t}`)
77
+ .join("\n")}`);
78
+ }
79
+ createMcpServer() {
80
+ const tools = [];
81
+ for (const plugin of this.plugins) {
82
+ const pluginTools = plugin.registerTools();
83
+ for (const pluginTool of pluginTools) {
84
+ tools.push(tool(pluginTool.name, pluginTool.description, pluginTool.zodSchema.shape, async (args) => {
85
+ return await plugin.handleToolCall(pluginTool.name, args);
86
+ }));
87
+ }
88
+ }
89
+ const server = createSdkMcpServer({
90
+ name: "agent-tools",
91
+ version: "1.0.0",
92
+ tools,
93
+ });
94
+ logger.info(`✅ MCP server created with ${tools.length} tools:\n${tools
95
+ .map((t) => `- ${t.name}`)
96
+ .join("\n")}`);
97
+ return server;
98
+ }
99
+ /**
100
+ * Run a workflow from a file.
101
+ * @param workflowPath - Path to the workflow JSON file
102
+ * @param initialContext - Optional additional context to merge
103
+ */
104
+ async runWorkflow(workflowPath, initialContext = {}) {
105
+ const workflow = await loadWorkflow(workflowPath);
106
+ logger.info(`Workflow loaded (${workflow.steps.length} steps)`);
107
+ // Validate tools before running
108
+ this.validateTools(workflow);
109
+ const mcpServer = this.createMcpServer();
110
+ // Build initial context with trigger payload from environment
111
+ const context = { ...initialContext };
112
+ // Automatically inject BUILD0_TRIGGER_PAYLOAD as 'input' if present
113
+ if (process.env.BUILD0_TRIGGER_PAYLOAD) {
114
+ try {
115
+ const triggerPayload = JSON.parse(process.env.BUILD0_TRIGGER_PAYLOAD);
116
+ context.input = triggerPayload;
117
+ logger.info(`Trigger payload loaded from BUILD0_TRIGGER_PAYLOAD`);
118
+ }
119
+ catch (e) {
120
+ logger.error(`Failed to parse BUILD0_TRIGGER_PAYLOAD: ${e}`);
121
+ }
122
+ }
123
+ let isFirstAiAgentStep = true;
124
+ for (const step of workflow.steps) {
125
+ logger.stepStart(step.id, step.type, step.tool);
126
+ // Check 'if' condition
127
+ if (step.if) {
128
+ const condition = interpolate(step.if, context);
129
+ if (!condition || condition === "false") {
130
+ logger.stepSkip(step.id, "condition false");
131
+ continue;
132
+ }
133
+ }
134
+ try {
135
+ switch (step.type) {
136
+ case "ai_agent":
137
+ // Extract and interpolate args for ai_agent
138
+ const agentArgs = {};
139
+ if (step.args) {
140
+ for (const [k, v] of Object.entries(step.args)) {
141
+ agentArgs[k] =
142
+ typeof v === "string" ? interpolate(v, context) : v;
143
+ }
144
+ }
145
+ const fullPrompt = agentArgs.prompt || "";
146
+ const workingDir = path.resolve(process.cwd(), agentArgs.working_dir || ".");
147
+ // Write full prompt to a temp file OUTSIDE the working directory
148
+ // to avoid Claude Code scanning it automatically
149
+ const tempPromptFile = path.join(os.tmpdir(), `prompt_${step.id}_${Date.now()}.txt`);
150
+ // Truncate prompt to ~2000 tokens (1 token ≈ 4 chars -> 8000 chars)
151
+ const MAX_CHARS = 2000 * 4;
152
+ await fs.writeFile(tempPromptFile, fullPrompt, "utf-8");
153
+ logger.aiAgentPrompt(step.id, fullPrompt.length, fullPrompt.length > MAX_CHARS, tempPromptFile);
154
+ let truncatedPrompt = fullPrompt.substring(0, MAX_CHARS);
155
+ if (fullPrompt.length > MAX_CHARS) {
156
+ truncatedPrompt += `\n\n[Note: The full prompt was truncated. I have saved the complete details to the file '${tempPromptFile}' (outside the workspace). You can read it if needed, but it is large.]`;
157
+ }
158
+ const result = await runAgent({
159
+ prompt: truncatedPrompt,
160
+ workingDirectory: workingDir,
161
+ mcpServers: {
162
+ "agent-tools": mcpServer,
163
+ },
164
+ shouldContinuePreviousSession: !isFirstAiAgentStep,
165
+ });
166
+ isFirstAiAgentStep = false;
167
+ logger.aiAgentResponse(step.id, result.output.length, result.output.substring(0, 100));
168
+ context[step.id] = { output: result.output };
169
+ break;
170
+ case "tool":
171
+ const toolName = step.tool;
172
+ if (!toolName)
173
+ throw new Error("Tool name missing");
174
+ // Find plugin that provides this tool
175
+ const plugin = this.plugins.find((p) => p.registerTools().some((t) => t.name === toolName));
176
+ if (!plugin)
177
+ throw new Error(`Plugin for tool ${toolName} not found`);
178
+ // Interpolate args
179
+ const args = {};
180
+ if (step.args) {
181
+ for (const [k, v] of Object.entries(step.args)) {
182
+ args[k] =
183
+ typeof v === "string" ? interpolate(v, context) : v;
184
+ }
185
+ }
186
+ const toolCallId = `${step.id}_${toolName}_${Date.now()}`;
187
+ logger.toolCall(toolName, toolCallId, args);
188
+ const toolResult = await plugin.handleToolCall(toolName, args);
189
+ // Extract text content
190
+ const outputText = toolResult.content
191
+ .map((c) => c.text)
192
+ .join("\n");
193
+ logger.toolResult(toolName, toolCallId, outputText.length, outputText.substring(0, 100), true);
194
+ // Try to parse JSON if possible for easier access
195
+ let outputData = outputText;
196
+ try {
197
+ outputData = JSON.parse(outputText);
198
+ }
199
+ catch (e) {
200
+ // ignore
201
+ }
202
+ context[step.id] = { output: outputData };
203
+ // Tool result already logged above
204
+ break;
205
+ }
206
+ logger.stepComplete(step.id);
207
+ }
208
+ catch (error) {
209
+ logger.stepError(step.id, error instanceof Error ? error.message : String(error));
210
+ process.exit(1);
211
+ }
212
+ }
213
+ }
214
+ }
@@ -0,0 +1,29 @@
1
+ import { CallToolResult } from "@modelcontextprotocol/sdk/types.js";
2
+ import { z, ZodRawShape } from "zod";
3
+ /**
4
+ * Base configuration provided to all plugins.
5
+ * Contains credentials fetched from remote API.
6
+ */
7
+ export interface BasePluginConfig {
8
+ [key: string]: string | undefined;
9
+ }
10
+ /**
11
+ * Tool definition with Zod schema for MCP SDK compatibility
12
+ */
13
+ export interface ToolDefinition {
14
+ name: string;
15
+ description: string;
16
+ zodSchema: z.ZodObject<ZodRawShape>;
17
+ }
18
+ /**
19
+ * Generic plugin interface.
20
+ * Each plugin should define its own TConfig interface with required keys.
21
+ */
22
+ export interface McpPlugin<TConfig extends BasePluginConfig = BasePluginConfig> {
23
+ name: string;
24
+ config?: TConfig;
25
+ init(config: TConfig): Promise<void>;
26
+ registerTools(): ToolDefinition[];
27
+ handleToolCall(name: string, args: Record<string, unknown>): Promise<CallToolResult>;
28
+ }
29
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/core/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,oCAAoC,CAAC;AACpE,OAAO,EAAE,CAAC,EAAE,WAAW,EAAE,MAAM,KAAK,CAAC;AAErC;;;GAGG;AACH,MAAM,WAAW,gBAAgB;IAC/B,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC;CACnC;AAED;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,CAAC,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC;CACrC;AAED;;;GAGG;AACH,MAAM,WAAW,SAAS,CACxB,OAAO,SAAS,gBAAgB,GAAG,gBAAgB;IAEnD,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,IAAI,CAAC,MAAM,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACrC,aAAa,IAAI,cAAc,EAAE,CAAC;IAClC,cAAc,CACZ,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC5B,OAAO,CAAC,cAAc,CAAC,CAAC;CAC5B"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,9 @@
1
+ export { Runner } from "./core/runner.js";
2
+ export type { McpPlugin, BasePluginConfig, ToolDefinition, } from "./core/types.js";
3
+ export type { Workflow, WorkflowStep } from "./utils/workflow.js";
4
+ export { logger } from "./utils/logger.js";
5
+ export type { LogMessage, LogLevel, LogMessageType, BaseLogMessage, StepStartMessage, StepCompleteMessage, StepErrorMessage, StepSkipMessage, AiAgentPromptMessage, AiAgentResponseMessage, ToolCallMessage, ToolResultMessage, ClaudeCodeSdkMessage, ClaudeCodeStderrMessage, GenericLogMessage, } from "./core/log-types.js";
6
+ export { credentialManager } from "./services/credential-manager.js";
7
+ export type { Credential } from "./services/credential-manager.js";
8
+ export type { AgentResult } from "./utils/agent.js";
9
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAC1C,YAAY,EACV,SAAS,EACT,gBAAgB,EAChB,cAAc,GACf,MAAM,iBAAiB,CAAC;AAGzB,YAAY,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAGlE,OAAO,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAC3C,YAAY,EACV,UAAU,EACV,QAAQ,EACR,cAAc,EACd,cAAc,EACd,gBAAgB,EAChB,mBAAmB,EACnB,gBAAgB,EAChB,eAAe,EACf,oBAAoB,EACpB,sBAAsB,EACtB,eAAe,EACf,iBAAiB,EACjB,oBAAoB,EACpB,uBAAuB,EACvB,iBAAiB,GAClB,MAAM,qBAAqB,CAAC;AAG7B,OAAO,EAAE,iBAAiB,EAAE,MAAM,kCAAkC,CAAC;AACrE,YAAY,EAAE,UAAU,EAAE,MAAM,kCAAkC,CAAC;AAGnE,YAAY,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,6 @@
1
+ // Core
2
+ export { Runner } from "./core/runner.js";
3
+ // Logger
4
+ export { logger } from "./utils/logger.js";
5
+ // Credentials
6
+ export { credentialManager } from "./services/credential-manager.js";
@@ -0,0 +1,30 @@
1
+ export interface Credential {
2
+ type: string;
3
+ provider: string;
4
+ apiKey?: string;
5
+ access_token?: string;
6
+ raw?: any;
7
+ }
8
+ /**
9
+ * Centralized credential management service.
10
+ * Fetches, decrypts, and caches credentials from remote API.
11
+ * Provides a singleton instance that all parts of the framework can use.
12
+ */
13
+ declare class CredentialManager {
14
+ private credentials;
15
+ private fetchPromise;
16
+ /**
17
+ * Fetch credentials from remote API and cache them.
18
+ * Ensures credentials are only fetched once even if called multiple times.
19
+ * Returns raw credentials - transformation to env vars happens in index.ts
20
+ */
21
+ fetchCredentials(): Promise<Record<string, Credential>>;
22
+ private _performFetch;
23
+ /**
24
+ * Get cached raw credentials. Returns empty object if not yet fetched.
25
+ */
26
+ getCredentials(): Record<string, Credential>;
27
+ }
28
+ export declare const credentialManager: CredentialManager;
29
+ export {};
30
+ //# sourceMappingURL=credential-manager.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"credential-manager.d.ts","sourceRoot":"","sources":["../../src/services/credential-manager.ts"],"names":[],"mappings":"AAMA,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,GAAG,CAAC,EAAE,GAAG,CAAC;CACX;AAyBD;;;;GAIG;AACH,cAAM,iBAAiB;IACrB,OAAO,CAAC,WAAW,CAA2C;IAC9D,OAAO,CAAC,YAAY,CAAoD;IAExE;;;;OAIG;IACG,gBAAgB,IAAI,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;YAsB/C,aAAa;IA8C3B;;OAEG;IACH,cAAc,IAAI,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC;CAG7C;AAGD,eAAO,MAAM,iBAAiB,mBAA0B,CAAC"}
@@ -0,0 +1,94 @@
1
+ import crypto from "crypto";
2
+ import { logger } from "../utils/logger.js";
3
+ const ALGORITHM = "aes-256-gcm";
4
+ const CREDENTIALS_AUTH_KEY = "agent-credentials";
5
+ function decryptCredentials(encryptedData) {
6
+ const encryptionKey = process.env.BUILD0_AGENT_ENCRYPTION_KEY;
7
+ if (!encryptionKey) {
8
+ throw new Error("BUILD0_ENCRYPTION_KEY environment variable is not set. Cannot decrypt credentials.");
9
+ }
10
+ const parts = encryptedData.split(":");
11
+ if (parts.length !== 3) {
12
+ throw new Error("Invalid encrypted data format");
13
+ }
14
+ const [ivHex, authTagHex, encrypted] = parts;
15
+ const key = Buffer.from(encryptionKey, "hex");
16
+ const iv = Buffer.from(ivHex, "hex");
17
+ const authTag = Buffer.from(authTagHex, "hex");
18
+ const decipher = crypto.createDecipheriv(ALGORITHM, key, iv);
19
+ decipher.setAuthTag(authTag);
20
+ decipher.setAAD(Buffer.from(CREDENTIALS_AUTH_KEY));
21
+ let decrypted = decipher.update(encrypted, "hex", "utf8");
22
+ decrypted += decipher.final("utf8");
23
+ return JSON.parse(decrypted);
24
+ }
25
+ /**
26
+ * Centralized credential management service.
27
+ * Fetches, decrypts, and caches credentials from remote API.
28
+ * Provides a singleton instance that all parts of the framework can use.
29
+ */
30
+ class CredentialManager {
31
+ credentials = null;
32
+ fetchPromise = null;
33
+ /**
34
+ * Fetch credentials from remote API and cache them.
35
+ * Ensures credentials are only fetched once even if called multiple times.
36
+ * Returns raw credentials - transformation to env vars happens in index.ts
37
+ */
38
+ async fetchCredentials() {
39
+ // If already fetched, return cached credentials
40
+ if (this.credentials !== null) {
41
+ return this.credentials;
42
+ }
43
+ // If fetch is in progress, wait for it
44
+ if (this.fetchPromise) {
45
+ return this.fetchPromise;
46
+ }
47
+ // Start new fetch
48
+ this.fetchPromise = this._performFetch();
49
+ this.credentials = await this.fetchPromise;
50
+ logger.info(`✅ Credentials fetched successfully:\n${Object.keys(this.credentials)
51
+ .map((key) => `- ${key}`)
52
+ .join("\n")}`);
53
+ return this.credentials;
54
+ }
55
+ async _performFetch() {
56
+ const credentialsUrl = process.env.BUILD0_AGENT_CREDENTIALS_URL;
57
+ const authToken = process.env.BUILD0_AGENT_AUTH_TOKEN;
58
+ if (!credentialsUrl) {
59
+ throw new Error("BUILD0_AGENT_CREDENTIALS_URL environment variable is not set.");
60
+ }
61
+ if (!authToken) {
62
+ throw new Error("BUILD0_AGENT_AUTH_TOKEN environment variable is not set.");
63
+ }
64
+ console.log(`[Credentials] Fetching remote credentials from ${credentialsUrl}...`);
65
+ try {
66
+ const response = await fetch(credentialsUrl, {
67
+ headers: { "x-agent-auth-token": authToken },
68
+ });
69
+ if (!response.ok) {
70
+ throw new Error(`Failed to fetch credentials: ${response.statusText}`);
71
+ }
72
+ const data = await response.json();
73
+ if (!data.encrypted) {
74
+ throw new Error("Invalid response format: missing 'encrypted' field");
75
+ }
76
+ const rawCredentials = decryptCredentials(data.encrypted);
77
+ console.log("[Credentials] Successfully decrypted credentials");
78
+ // Return raw credentials - transformation happens in index.ts
79
+ return rawCredentials;
80
+ }
81
+ catch (error) {
82
+ console.error("[Credentials] Error fetching/decrypting credentials:", error instanceof Error ? error.message : JSON.stringify(error));
83
+ throw error;
84
+ }
85
+ }
86
+ /**
87
+ * Get cached raw credentials. Returns empty object if not yet fetched.
88
+ */
89
+ getCredentials() {
90
+ return this.credentials || {};
91
+ }
92
+ }
93
+ // Singleton instance
94
+ export const credentialManager = new CredentialManager();
@@ -0,0 +1,11 @@
1
+ import { McpSdkServerConfigWithInstance } from "@anthropic-ai/claude-agent-sdk";
2
+ export interface AgentResult {
3
+ output: string;
4
+ }
5
+ export declare function runAgent(params: {
6
+ prompt: string;
7
+ workingDirectory: string;
8
+ mcpServers: Record<string, McpSdkServerConfigWithInstance>;
9
+ shouldContinuePreviousSession?: boolean;
10
+ }): Promise<AgentResult>;
11
+ //# sourceMappingURL=agent.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent.d.ts","sourceRoot":"","sources":["../../src/utils/agent.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,8BAA8B,EAG/B,MAAM,gCAAgC,CAAC;AAGxC,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,wBAAsB,QAAQ,CAAC,MAAM,EAAE;IACrC,MAAM,EAAE,MAAM,CAAC;IACf,gBAAgB,EAAE,MAAM,CAAC;IACzB,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,8BAA8B,CAAC,CAAC;IAC3D,6BAA6B,CAAC,EAAE,OAAO,CAAC;CACzC,GAAG,OAAO,CAAC,WAAW,CAAC,CAsDvB"}
@@ -0,0 +1,46 @@
1
+ import { query, } from "@anthropic-ai/claude-agent-sdk";
2
+ import { logger } from "./logger.js";
3
+ export async function runAgent(params) {
4
+ // Capture stderr to see actual errors from Claude Code process
5
+ const stderrMessages = [];
6
+ const stderrCallback = (message) => {
7
+ stderrMessages.push(message);
8
+ logger.claudeCodeStderr(message);
9
+ };
10
+ const stream = query({
11
+ prompt: params.prompt,
12
+ options: {
13
+ continue: params.shouldContinuePreviousSession ?? false,
14
+ cwd: params.workingDirectory,
15
+ // We can use the default executable (node)
16
+ mcpServers: params.mcpServers,
17
+ // Enable all tools by default
18
+ permissionMode: "bypassPermissions",
19
+ stderr: stderrCallback,
20
+ },
21
+ });
22
+ let finalResult = null;
23
+ try {
24
+ for await (const message of stream) {
25
+ logger.claudeCodeSdkMessage(message);
26
+ if (message.type === "result") {
27
+ finalResult = message;
28
+ }
29
+ }
30
+ }
31
+ catch (error) {
32
+ logger.claudeCodeStderr(error instanceof Error ? error.message : String(error));
33
+ throw error;
34
+ }
35
+ if (finalResult) {
36
+ if (finalResult.subtype === "success") {
37
+ return {
38
+ output: finalResult.result,
39
+ };
40
+ }
41
+ else {
42
+ throw new Error(`Error: ${finalResult.subtype}. Message: ${JSON.stringify(finalResult.errors, null, 2)}`);
43
+ }
44
+ }
45
+ throw new Error("No final result received");
46
+ }
@@ -0,0 +1,29 @@
1
+ import { SDKMessage } from "@anthropic-ai/claude-agent-sdk";
2
+ declare class Logger {
3
+ private currentStepId?;
4
+ private originalConsoleLog;
5
+ private originalConsoleWarn;
6
+ private originalConsoleError;
7
+ private originalConsoleDebug;
8
+ constructor();
9
+ private overrideConsole;
10
+ private log;
11
+ private createMessage;
12
+ stepStart(stepId: string, stepType: "ai_agent" | "tool", toolName?: string): void;
13
+ stepComplete(stepId: string, duration?: number, outputPreview?: string): void;
14
+ stepError(stepId: string, error: string): void;
15
+ stepSkip(stepId: string, reason: string): void;
16
+ aiAgentPrompt(stepId: string, promptLength: number, truncated: boolean, fullPromptPath?: string): void;
17
+ aiAgentResponse(stepId: string, responseLength: number, responsePreview: string): void;
18
+ toolCall(toolName: string, toolCallId: string, args: Record<string, any>): void;
19
+ toolResult(toolName: string, toolCallId: string, resultLength: number, resultPreview: string, hasJsonResult?: boolean): void;
20
+ claudeCodeSdkMessage(message: SDKMessage): void;
21
+ claudeCodeStderr(stderr: string): void;
22
+ info(message: string, data?: Record<string, any>): void;
23
+ warn(message: string, data?: Record<string, any>): void;
24
+ error(message: string, data?: Record<string, any>): void;
25
+ debug(message: string, data?: Record<string, any>): void;
26
+ }
27
+ export declare const logger: Logger;
28
+ export {};
29
+ //# sourceMappingURL=logger.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../src/utils/logger.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,gCAAgC,CAAC;AAiB5D,cAAM,MAAM;IACV,OAAO,CAAC,aAAa,CAAC,CAAS;IAC/B,OAAO,CAAC,kBAAkB,CAAqB;IAC/C,OAAO,CAAC,mBAAmB,CAAsB;IACjD,OAAO,CAAC,oBAAoB,CAAuB;IACnD,OAAO,CAAC,oBAAoB,CAAuB;;IAanD,OAAO,CAAC,eAAe;IAgCvB,OAAO,CAAC,GAAG;IAKX,OAAO,CAAC,aAAa;IAcrB,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,UAAU,GAAG,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM;IAW1E,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,EAAE,aAAa,CAAC,EAAE,MAAM;IAWtE,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM;IAUvC,QAAQ,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM;IAUvC,aAAa,CACX,MAAM,EAAE,MAAM,EACd,YAAY,EAAE,MAAM,EACpB,SAAS,EAAE,OAAO,EAClB,cAAc,CAAC,EAAE,MAAM;IAYzB,eAAe,CACb,MAAM,EAAE,MAAM,EACd,cAAc,EAAE,MAAM,EACtB,eAAe,EAAE,MAAM;IAWzB,QAAQ,CAAC,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC;IAUxE,UAAU,CACR,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,MAAM,EAClB,YAAY,EAAE,MAAM,EACpB,aAAa,EAAE,MAAM,EACrB,aAAa,CAAC,EAAE,OAAO;IAazB,oBAAoB,CAAC,OAAO,EAAE,UAAU;IAQxC,gBAAgB,CAAC,MAAM,EAAE,MAAM;IAW/B,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC;IAWhD,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC;IAWhD,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC;IAWjD,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC;CAUlD;AAED,eAAO,MAAM,MAAM,QAAe,CAAC"}
@@ -0,0 +1,168 @@
1
+ // Logger utility for structured JSON logging
2
+ class Logger {
3
+ currentStepId;
4
+ originalConsoleLog;
5
+ originalConsoleWarn;
6
+ originalConsoleError;
7
+ originalConsoleDebug;
8
+ constructor() {
9
+ // Store original console methods
10
+ this.originalConsoleLog = console.log.bind(console);
11
+ this.originalConsoleWarn = console.warn.bind(console);
12
+ this.originalConsoleError = console.error.bind(console);
13
+ this.originalConsoleDebug = console.debug.bind(console);
14
+ // Override console methods to automatically include step ID
15
+ this.overrideConsole();
16
+ }
17
+ overrideConsole() {
18
+ const self = this;
19
+ console.log = (...args) => {
20
+ const message = args
21
+ .map((arg) => (typeof arg === "string" ? arg : JSON.stringify(arg)))
22
+ .join(" ");
23
+ self.info(message);
24
+ };
25
+ console.warn = (...args) => {
26
+ const message = args
27
+ .map((arg) => (typeof arg === "string" ? arg : JSON.stringify(arg)))
28
+ .join(" ");
29
+ self.warn(message);
30
+ };
31
+ console.error = (...args) => {
32
+ const message = args
33
+ .map((arg) => (typeof arg === "string" ? arg : JSON.stringify(arg)))
34
+ .join(" ");
35
+ self.error(message);
36
+ };
37
+ console.debug = (...args) => {
38
+ const message = args
39
+ .map((arg) => (typeof arg === "string" ? arg : JSON.stringify(arg)))
40
+ .join(" ");
41
+ self.debug(message);
42
+ };
43
+ }
44
+ log(message) {
45
+ // Use original console.log to avoid recursion
46
+ this.originalConsoleLog(JSON.stringify(message));
47
+ }
48
+ createMessage(type, level, data) {
49
+ return {
50
+ timestamp: new Date().toISOString(),
51
+ level,
52
+ type,
53
+ stepId: this.currentStepId,
54
+ ...data,
55
+ };
56
+ }
57
+ stepStart(stepId, stepType, toolName) {
58
+ this.currentStepId = stepId;
59
+ this.log(this.createMessage("step_start", "info", {
60
+ stepId,
61
+ stepType,
62
+ toolName,
63
+ }));
64
+ }
65
+ stepComplete(stepId, duration, outputPreview) {
66
+ this.log(this.createMessage("step_complete", "info", {
67
+ stepId,
68
+ duration,
69
+ outputPreview,
70
+ }));
71
+ this.currentStepId = undefined;
72
+ }
73
+ stepError(stepId, error) {
74
+ this.log(this.createMessage("step_error", "error", {
75
+ stepId,
76
+ error,
77
+ }));
78
+ this.currentStepId = undefined;
79
+ }
80
+ stepSkip(stepId, reason) {
81
+ this.log(this.createMessage("step_skip", "warn", {
82
+ stepId,
83
+ reason,
84
+ }));
85
+ this.currentStepId = undefined;
86
+ }
87
+ aiAgentPrompt(stepId, promptLength, truncated, fullPromptPath) {
88
+ this.log(this.createMessage("ai_agent_prompt", "info", {
89
+ stepId,
90
+ promptLength,
91
+ truncated,
92
+ fullPromptPath,
93
+ }));
94
+ }
95
+ aiAgentResponse(stepId, responseLength, responsePreview) {
96
+ this.log(this.createMessage("ai_agent_response", "info", {
97
+ stepId,
98
+ responseLength,
99
+ responsePreview,
100
+ }));
101
+ }
102
+ toolCall(toolName, toolCallId, args) {
103
+ this.log(this.createMessage("tool_call", "info", {
104
+ toolName,
105
+ toolCallId,
106
+ args,
107
+ }));
108
+ }
109
+ toolResult(toolName, toolCallId, resultLength, resultPreview, hasJsonResult) {
110
+ this.log(this.createMessage("tool_result", "info", {
111
+ toolName,
112
+ toolCallId,
113
+ resultLength,
114
+ resultPreview,
115
+ hasJsonResult,
116
+ }));
117
+ }
118
+ claudeCodeSdkMessage(message) {
119
+ this.log(this.createMessage("claude_code_sdk", "info", {
120
+ sdkMessage: message,
121
+ }));
122
+ }
123
+ claudeCodeStderr(stderr) {
124
+ this.log(this.createMessage("claude_code_stderr", "error", { stderr }));
125
+ }
126
+ // Generic log methods that automatically include current step ID
127
+ info(message, data) {
128
+ this.log({
129
+ timestamp: new Date().toISOString(),
130
+ level: "info",
131
+ type: "log",
132
+ message,
133
+ stepId: this.currentStepId ?? undefined,
134
+ ...data,
135
+ });
136
+ }
137
+ warn(message, data) {
138
+ this.log({
139
+ timestamp: new Date().toISOString(),
140
+ level: "warn",
141
+ type: "log",
142
+ message,
143
+ stepId: this.currentStepId ?? undefined,
144
+ ...data,
145
+ });
146
+ }
147
+ error(message, data) {
148
+ this.log({
149
+ timestamp: new Date().toISOString(),
150
+ level: "error",
151
+ type: "log",
152
+ message,
153
+ stepId: this.currentStepId ?? undefined,
154
+ ...data,
155
+ });
156
+ }
157
+ debug(message, data) {
158
+ this.log({
159
+ timestamp: new Date().toISOString(),
160
+ level: "debug",
161
+ type: "log",
162
+ message,
163
+ stepId: this.currentStepId ?? undefined,
164
+ ...data,
165
+ });
166
+ }
167
+ }
168
+ export const logger = new Logger();
@@ -0,0 +1,12 @@
1
+ export interface WorkflowStep {
2
+ id: string;
3
+ type: "ai_agent" | "tool";
4
+ tool?: string;
5
+ args?: Record<string, any>;
6
+ if?: string;
7
+ }
8
+ export interface Workflow {
9
+ steps: WorkflowStep[];
10
+ }
11
+ export declare function loadWorkflow(filePath: string): Promise<Workflow>;
12
+ //# sourceMappingURL=workflow.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"workflow.d.ts","sourceRoot":"","sources":["../../src/utils/workflow.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,UAAU,GAAG,MAAM,CAAC;IAC1B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC3B,EAAE,CAAC,EAAE,MAAM,CAAC;CACb;AAED,MAAM,WAAW,QAAQ;IACvB,KAAK,EAAE,YAAY,EAAE,CAAC;CACvB;AAED,wBAAsB,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,CAAC,CAGtE"}
@@ -0,0 +1,5 @@
1
+ import fs from "fs/promises";
2
+ export async function loadWorkflow(filePath) {
3
+ const content = await fs.readFile(filePath, "utf-8");
4
+ return JSON.parse(content);
5
+ }
package/package.json ADDED
@@ -0,0 +1,43 @@
1
+ {
2
+ "name": "@build0.ai/agent-core",
3
+ "version": "0.1.0",
4
+ "description": "Core framework for Build0 autonomous coding agents",
5
+ "type": "module",
6
+ "main": "dist/index.js",
7
+ "types": "dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "import": "./dist/index.js",
11
+ "types": "./dist/index.d.ts"
12
+ }
13
+ },
14
+ "files": [
15
+ "dist"
16
+ ],
17
+ "scripts": {
18
+ "build": "tsc",
19
+ "typecheck": "tsc --noEmit",
20
+ "prepublishOnly": "npm run build"
21
+ },
22
+ "dependencies": {
23
+ "@anthropic-ai/claude-agent-sdk": "^0.1.54",
24
+ "@modelcontextprotocol/sdk": "^1.0.1",
25
+ "zod": "^3.22.4"
26
+ },
27
+ "peerDependencies": {
28
+ "@anthropic-ai/sdk": "^0.71.0"
29
+ },
30
+ "devDependencies": {
31
+ "@types/node": "^20.11.0",
32
+ "typescript": "^5.3.3"
33
+ },
34
+ "keywords": [
35
+ "ai",
36
+ "agent",
37
+ "claude",
38
+ "anthropic",
39
+ "autonomous",
40
+ "mcp"
41
+ ],
42
+ "license": "MIT"
43
+ }