Skip to content

Commit 2e18a27

Browse files
committed
Initial commit: C++ Agent Architecture
0 parents  commit 2e18a27

18 files changed

Lines changed: 1382 additions & 0 deletions

.gitignore

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
# Prerequisites
2+
*.d
3+
4+
# Compiled Object files
5+
*.slo
6+
*.lo
7+
*.o
8+
*.obj
9+
10+
# Precompiled Headers
11+
*.gch
12+
*.pch
13+
14+
# Compiled Dynamic libraries
15+
*.so
16+
*.dylib
17+
*.dll
18+
19+
# Fortran module files
20+
*.mod
21+
*.smod
22+
23+
# Compiled Static libraries
24+
*.lai
25+
*.la
26+
*.a
27+
*.lib
28+
29+
# Executables
30+
*.exe
31+
*.out
32+
*.app
33+
34+
# CMake
35+
CMakeCache.txt
36+
CMakeFiles
37+
CMakeScripts
38+
Testing
39+
Makefile
40+
cmake_install.cmake
41+
install_manifest.txt
42+
compile_commands.json
43+
CTestTestfile.cmake
44+
_deps
45+
build/
46+
bin/
47+
out/
48+
49+
# Visual Studio
50+
.vs/
51+
*.sln
52+
*.vcxproj
53+
*.vcxproj.user
54+
*.vcxproj.filters
55+
56+
# CLion
57+
.idea/
58+
cmake-build-*/
59+
60+
# VS Code
61+
.vscode/

CMakeLists.txt

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
cmake_minimum_required(VERSION 3.20)
2+
project(claw-cpp VERSION 0.1.0 LANGUAGES CXX)
3+
4+
set(CMAKE_CXX_STANDARD 20)
5+
set(CMAKE_CXX_STANDARD_REQUIRED ON)
6+
set(CMAKE_CXX_EXTENSIONS OFF)
7+
8+
# ── Dependencies via FetchContent ─────────────────────────────────────────
9+
10+
include(FetchContent)
11+
12+
# nlohmann/json — industry standard JSON library
13+
FetchContent_Declare(json
14+
GIT_REPOSITORY https://github.com/nlohmann/json.git
15+
GIT_TAG v3.11.3
16+
GIT_SHALLOW TRUE
17+
)
18+
19+
# cpp-httplib — lightweight HTTP/HTTPS client
20+
FetchContent_Declare(httplib
21+
GIT_REPOSITORY https://github.com/yhirose/cpp-httplib.git
22+
GIT_TAG v0.15.3
23+
GIT_SHALLOW TRUE
24+
)
25+
26+
# CLI11 — modern CLI argument parser
27+
FetchContent_Declare(cli11
28+
GIT_REPOSITORY https://github.com/CLIUtils/CLI11.git
29+
GIT_TAG v2.4.1
30+
GIT_SHALLOW TRUE
31+
)
32+
33+
# fmt — type-safe formatting (with color support)
34+
FetchContent_Declare(fmt
35+
GIT_REPOSITORY https://github.com/fmtlib/fmt.git
36+
GIT_TAG 10.2.1
37+
GIT_SHALLOW TRUE
38+
)
39+
40+
FetchContent_MakeAvailable(json httplib cli11 fmt)
41+
42+
# ── OpenSSL for HTTPS support ─────────────────────────────────────────────
43+
44+
find_package(OpenSSL QUIET)
45+
if(OPENSSL_FOUND)
46+
message(STATUS "OpenSSL found — HTTPS enabled")
47+
else()
48+
message(WARNING
49+
"OpenSSL NOT found — HTTPS will NOT work.\n"
50+
"Install OpenSSL and re-run cmake, or set OPENSSL_ROOT_DIR.\n"
51+
"On Windows: winget install ShiningLight.OpenSSL"
52+
)
53+
endif()
54+
55+
# ── Core static library ──────────────────────────────────────────────────
56+
57+
add_library(claw_core STATIC
58+
src/api/client.cpp
59+
src/runtime/session.cpp
60+
src/tools/bash_tool.cpp
61+
src/tools/file_read_tool.cpp
62+
src/tools/file_write_tool.cpp
63+
)
64+
65+
target_include_directories(claw_core PUBLIC
66+
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/src>
67+
)
68+
69+
target_link_libraries(claw_core PUBLIC
70+
nlohmann_json::nlohmann_json
71+
httplib::httplib
72+
fmt::fmt
73+
)
74+
75+
# Link OpenSSL if available and enable HTTPS in cpp-httplib
76+
if(OPENSSL_FOUND)
77+
target_compile_definitions(claw_core PUBLIC CPPHTTPLIB_OPENSSL_SUPPORT)
78+
target_link_libraries(claw_core PUBLIC OpenSSL::SSL OpenSSL::Crypto)
79+
endif()
80+
81+
# Platform-specific networking libraries
82+
if(WIN32)
83+
target_link_libraries(claw_core PUBLIC ws2_32 crypt32)
84+
endif()
85+
86+
# ── Main executable ──────────────────────────────────────────────────────
87+
88+
add_executable(claw-cpp
89+
src/cli/main.cpp
90+
)
91+
92+
target_link_libraries(claw-cpp PRIVATE
93+
claw_core
94+
CLI11::CLI11
95+
)

LICENSE

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2024
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

README.md

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
# Claw Code (C++ Edition) 🚀
2+
3+
![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)
4+
![C++20](https://img.shields.io/badge/C++-20-blue.svg)
5+
![Build](https://img.shields.io/badge/build-CMake-green.svg)
6+
7+
A clean-room, highly-performant C++20 reimplementation of the **Claw Code AI Agent Harness**.
8+
9+
Rather than being a simple chatbot that stops after a single reply, this is an **agentic loop architecture**. It integrates deeply with the Anthropic Messages API, sending explicit tool schemas to the model, and recursively executing local tools (like Bash and File I/O) on behalf of the AI until a task is completed.
10+
11+
---
12+
13+
## ⚡ Features
14+
15+
- **True Agentic Tool Loop:** Context-aware routing and recursive API calls.
16+
- **Interactive REPL & One-Shot:** Native slash commands (`/quit`, `/clear`, `/usage`) and one-shot prompt scripts.
17+
- **Built-in Tooling Layer:**
18+
- `BashTool`: Execute local shell scripts with configurable timeouts and output truncation guards.
19+
- `FileReadTool`: Read files up to 512KB to inspect codebases safely.
20+
- `FileWriteTool`: Write strings to files with automatic parent-directory creation.
21+
- **Native Static Binary:** Builds to a fast, statically linked binary. Zero python/npm dependencies.
22+
- **Context Compaction:** Auto-trims history past a certain turn limit to keep token window budgets low.
23+
24+
## 🏗️ Architecture Design
25+
26+
```mermaid
27+
graph TD
28+
User["User Input"] --> CLI["CLI Layer<br/>main.cpp"]
29+
CLI --> |"REPL or one-shot"| Session["Runtime Session<br/>session.cpp"]
30+
Session --> |"messages + tool defs"| API["API Client<br/>client.cpp"]
31+
API --> |"HTTP POST"| Anthropic["Anthropic API"]
32+
Anthropic --> |"stop=end_turn"| Session
33+
Anthropic --> |"stop=tool_use"| ToolLoop["Agentic Tool Loop"]
34+
ToolLoop --> Registry["Tool Registry"]
35+
Registry --> Bash["BashTool"]
36+
Registry --> FileRead["FileReadTool"]
37+
Registry --> FileWrite["FileWriteTool"]
38+
Bash --> |"result"| ToolLoop
39+
FileRead --> |"result"| ToolLoop
40+
FileWrite --> |"result"| ToolLoop
41+
ToolLoop --> |"tool_result message"| Session
42+
Session --> |"final text"| CLI
43+
CLI --> |"display"| User
44+
```
45+
46+
## 📁 Workspace Layout
47+
48+
```
49+
claw-cpp-public/
50+
├── CMakeLists.txt # Modern CMake build instructions
51+
├── LICENSE # MIT License
52+
├── README.md # This file
53+
└── src/
54+
├── api/
55+
│ ├── client.cpp/hpp # HTTPS logic via cpp-httplib
56+
│ └── types.hpp # Rich API content block modeling (Variant)
57+
├── cli/
58+
│ └── main.cpp # REPL CLI Interface & entrypoint
59+
├── runtime/
60+
│ └── session.cpp/hpp # Core agentic recursion loop
61+
└── tools/
62+
├── itool.hpp # Modular Plugin interface
63+
├── tool_registry.hpp # Maps plugin names to logic
64+
├── bash_tool.cpp/hpp # Safe shell execution
65+
├── file_read_tool.cpp/hpp
66+
└── file_write_tool.cpp/hpp
67+
```
68+
69+
## 🚀 Getting Started
70+
71+
### Prerequisites
72+
73+
You need a C++20 compatible compiler and CMake.
74+
For Windows users, you can use Winget:
75+
```powershell
76+
winget install Kitware.CMake
77+
winget install Microsoft.VisualStudio.2022.BuildTools --override "--wait --quiet --add Microsoft.VisualStudio.Workload.VCTools --includeRecommended"
78+
winget install ShiningLight.OpenSSL # Needed for HTTPS network calls
79+
```
80+
81+
### Build Instructions
82+
83+
```bash
84+
mkdir build
85+
cd build
86+
87+
# Configure CMake (it will auto-download cpp-httplib, nlohmann-json, fmt, and CLI11)
88+
cmake ..
89+
90+
# Build the release binary
91+
cmake --build . --config Release
92+
```
93+
94+
### Usage
95+
96+
Export your API Key to the environment:
97+
```powershell
98+
# Windows
99+
$env:ANTHROPIC_API_KEY="sk-ant-..."
100+
101+
# macOS/Linux
102+
export ANTHROPIC_API_KEY="sk-ant-..."
103+
```
104+
105+
Run the REPL:
106+
```bash
107+
./Release/claw-cpp
108+
```
109+
110+
Run a one-shot query:
111+
```bash
112+
./Release/claw-cpp prompt "List the files in this directory and tell me what they are."
113+
```

src/api/client.cpp

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
#include "client.hpp"
2+
#include <httplib.h>
3+
#include <fmt/core.h>
4+
5+
namespace claw::api {
6+
7+
Client::Client(ClientConfig config) : m_config(std::move(config)) {}
8+
9+
std::optional<TurnResponse> Client::send_request(
10+
const std::string& system_prompt,
11+
const std::vector<Message>& messages,
12+
const nlohmann::json& tools_json
13+
) {
14+
// ── Build the HTTP client ────────────────────────────────────────
15+
httplib::Client http(m_config.base_url);
16+
http.set_read_timeout(m_config.timeout_sec, 0);
17+
http.set_connection_timeout(10, 0);
18+
19+
httplib::Headers headers = {
20+
{"x-api-key", m_config.api_key},
21+
{"anthropic-version", m_config.api_version},
22+
{"content-type", "application/json"}
23+
};
24+
25+
// ── Build the JSON payload ───────────────────────────────────────
26+
nlohmann::json payload;
27+
payload["model"] = m_config.model;
28+
payload["max_tokens"] = m_config.max_tokens;
29+
30+
if (!system_prompt.empty()) {
31+
payload["system"] = system_prompt;
32+
}
33+
34+
// Serialize our rich Message objects
35+
nlohmann::json messages_json = nlohmann::json::array();
36+
for (const auto& msg : messages) {
37+
messages_json.push_back(msg.to_json());
38+
}
39+
payload["messages"] = messages_json;
40+
41+
// Include tool definitions if we have any registered tools
42+
if (!tools_json.empty()) {
43+
payload["tools"] = tools_json;
44+
}
45+
46+
// ── Execute the POST request ─────────────────────────────────────
47+
std::string body = payload.dump();
48+
auto res = http.Post("/v1/messages", headers, body, "application/json");
49+
50+
if (!res) {
51+
fmt::print(stderr, "[API Error] Request failed: {}\n",
52+
httplib::to_string(res.error()));
53+
return std::nullopt;
54+
}
55+
56+
if (res->status != 200) {
57+
fmt::print(stderr, "[API Error] Status {}: {}\n",
58+
res->status, res->body);
59+
return std::nullopt;
60+
}
61+
62+
// ── Parse the response ───────────────────────────────────────────
63+
try {
64+
auto response_json = nlohmann::json::parse(res->body);
65+
return TurnResponse::from_json(response_json);
66+
} catch (const nlohmann::json::exception& e) {
67+
fmt::print(stderr, "[API Error] JSON parse failure: {}\n", e.what());
68+
return std::nullopt;
69+
}
70+
}
71+
72+
} // namespace claw::api

0 commit comments

Comments
 (0)