init commit
This commit is contained in:
+195
@@ -0,0 +1,195 @@
|
||||
/* Bantam: tiny, powerful, DIY AI agent — modern C++20 port
|
||||
* Created by Luxferre in 2026, released into the public domain.
|
||||
*
|
||||
* This is a C++20 rewrite of the pure-C port (bantam-c). It talks to any
|
||||
* OpenAI-compatible /chat/completions API and implements the same agentic
|
||||
* loop, tools, session management, markdown terminal rendering and
|
||||
* raw-terminal line editor.
|
||||
*
|
||||
* Design goals relative to the C port:
|
||||
* - Use standard, safe C++ containers (std::string, std::vector,
|
||||
* std::map, std::span) instead of raw memory areas.
|
||||
* - Eliminate hand-rolled allocation/string code; rely on RAII so there
|
||||
* is far less room for memory-allocation related vulnerabilities.
|
||||
* - Depend only on libcurl (HTTP) plus the vendored single-header
|
||||
* nlohmann/json library; the unsafe json-c C API is no longer used.
|
||||
*
|
||||
* Feature macros: we rely on POSIX.1-2008 interfaces. */
|
||||
#ifndef BANTAM_HPP
|
||||
#define BANTAM_HPP
|
||||
|
||||
#include <cstdarg>
|
||||
#include <cstdint>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <span>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <vector>
|
||||
|
||||
/* Markdown renderer state (code-fence tracking). */
|
||||
struct MdState {
|
||||
bool in_code = false;
|
||||
};
|
||||
|
||||
/* ------------------------------------------------------------------ */
|
||||
/* Tool call / message / usage / config structures. */
|
||||
/* ------------------------------------------------------------------ */
|
||||
struct ToolCall {
|
||||
std::string id;
|
||||
std::string name;
|
||||
std::string arguments; /* raw JSON text of the arguments object */
|
||||
};
|
||||
|
||||
struct Message {
|
||||
std::string role;
|
||||
std::string content; /* empty when absent */
|
||||
std::string reasoning; /* empty when absent */
|
||||
std::vector<ToolCall> calls;
|
||||
std::string tool_call_id; /* empty when absent (tool role only) */
|
||||
int calls_shown = 0;
|
||||
};
|
||||
|
||||
struct Messages {
|
||||
std::vector<Message> items;
|
||||
};
|
||||
|
||||
struct Usage {
|
||||
int prompt_tokens = 0;
|
||||
int completion_tokens = 0;
|
||||
int total_tokens = 0;
|
||||
int cached_tokens = 0;
|
||||
int context_tokens = 0;
|
||||
std::string model;
|
||||
};
|
||||
|
||||
struct Cfg {
|
||||
std::string endpoint;
|
||||
std::string model;
|
||||
std::string api_key;
|
||||
std::string color;
|
||||
double temperature = 0.7;
|
||||
int timeout = 300;
|
||||
int shell_timeout = 120;
|
||||
int max_al_iterations = 1000;
|
||||
int stream = 1; /* 0/1 */
|
||||
int force_stream = -1; /* -1 = auto, 0/1 = force (compaction) */
|
||||
int context_window = 262144;
|
||||
int max_tool_res = 65536;
|
||||
std::map<std::string, std::string> raw; /* raw key/value map */
|
||||
};
|
||||
|
||||
struct Session {
|
||||
std::string id;
|
||||
std::string created;
|
||||
std::string summary;
|
||||
Messages messages;
|
||||
};
|
||||
|
||||
/* ------------------------------------------------------------------ */
|
||||
/* Globals. */
|
||||
/* ------------------------------------------------------------------ */
|
||||
extern int g_col; /* color enabled (0/1) */
|
||||
extern volatile int g_interrupted; /* SIGINT flag */
|
||||
|
||||
/* ------------------------------------------------------------------ */
|
||||
/* util.cpp */
|
||||
/* ------------------------------------------------------------------ */
|
||||
void setup_signal_handler();
|
||||
int is_terminal(int fd);
|
||||
int to_int_val(std::string_view s, int def);
|
||||
|
||||
std::string sfmt(const char *fmt, ...);
|
||||
void str_appendf(std::string &s, const char *fmt, ...);
|
||||
|
||||
/* UTF-8 helpers. */
|
||||
int utf8_decode(const unsigned char *p, size_t avail, size_t *plen);
|
||||
std::string_view utf8_truncate(std::string_view s, size_t max_bytes);
|
||||
|
||||
std::string filter_text(std::string_view s);
|
||||
int color_enabled(const Cfg &cfg);
|
||||
std::string cstr(std::string_view text, std::span<const int> codes);
|
||||
void cprint(std::string_view text, std::span<const int> codes);
|
||||
int visible_len(std::string_view s);
|
||||
int rune_width(int cp);
|
||||
|
||||
void mkdir_p(std::string_view dir);
|
||||
std::string project_id();
|
||||
std::string bantam_tmp_dir();
|
||||
std::string tool_res_dir();
|
||||
std::string md5_hex(std::string_view data);
|
||||
|
||||
/* ------------------------------------------------------------------ */
|
||||
/* config.cpp */
|
||||
/* ------------------------------------------------------------------ */
|
||||
const std::string *cfg_raw_get(const Cfg &c, std::string_view k);
|
||||
bool internal_key(std::string_view k);
|
||||
Cfg get_cfg(std::string_view path);
|
||||
int set_cfg(std::string_view path, std::string_view key, std::string_view val);
|
||||
std::string config_path();
|
||||
int fetch_context_window(Cfg &cfg);
|
||||
std::string list_models(Cfg &cfg, int *errout);
|
||||
std::string tools_dir(const Cfg &c);
|
||||
std::string skills_dir(const Cfg &c);
|
||||
|
||||
/* ------------------------------------------------------------------ */
|
||||
/* json.cpp — request building & response parsing (nlohmann/json). */
|
||||
/* ------------------------------------------------------------------ */
|
||||
std::string build_request_json(const Cfg &cfg, const Messages &msgs,
|
||||
bool use_tools, bool stream);
|
||||
bool parse_nonstream_response(std::string_view body, Message &out, Usage &usage);
|
||||
|
||||
/* ------------------------------------------------------------------ */
|
||||
/* llm.cpp — HTTP client (libcurl), headers, backoff, dispatch. */
|
||||
/* ------------------------------------------------------------------ */
|
||||
int http_get(Cfg &cfg, std::string_view url, std::string &body, long &code,
|
||||
std::string &errmsg);
|
||||
int llm(Cfg &cfg, Messages &msgs, bool use_tools, Message &out, Usage &usage,
|
||||
std::string &errmsg, volatile int *interrupted);
|
||||
|
||||
/* ------------------------------------------------------------------ */
|
||||
/* tools.cpp */
|
||||
/* ------------------------------------------------------------------ */
|
||||
std::string shell_with_workdir(std::string_view cmd, std::string_view workdir,
|
||||
int timeout, volatile int *interrupted);
|
||||
std::string read_file_or_dir(std::string_view path, int offset, int limit,
|
||||
int *style);
|
||||
std::string write_file(std::string_view path, int offset, int del_bytes,
|
||||
std::string_view content, int *err);
|
||||
std::string offload_tool_result(std::string_view res, int max_res,
|
||||
std::vector<std::string> &tmps);
|
||||
void cleanup_temps(std::vector<std::string> &tmps);
|
||||
|
||||
/* ------------------------------------------------------------------ */
|
||||
/* session.cpp */
|
||||
/* ------------------------------------------------------------------ */
|
||||
void save_session(const Messages &msgs, std::string_view sid,
|
||||
std::string *out_id, std::string *out_summary);
|
||||
std::vector<Session> sessions_load();
|
||||
std::unique_ptr<Messages> load_session(std::string_view sid, std::string *err);
|
||||
std::unique_ptr<Session> find_project_session();
|
||||
void autosave(const Messages &msgs);
|
||||
std::unique_ptr<Messages> compact(Cfg &cfg, const Messages &msgs,
|
||||
std::string *summary, std::string *err,
|
||||
volatile int *interrupted);
|
||||
std::string summary_of(const Messages &msgs);
|
||||
|
||||
/* ------------------------------------------------------------------ */
|
||||
/* render.cpp — terminal markdown rendering. */
|
||||
/* ------------------------------------------------------------------ */
|
||||
void render_md_print(std::string_view text);
|
||||
void render_md_line_print(std::string_view line, MdState &st);
|
||||
void render_table_print(const std::vector<std::string> &lines);
|
||||
bool is_table_line(std::string_view line);
|
||||
|
||||
/* ------------------------------------------------------------------ */
|
||||
/* editor.cpp — GNU readline line editor + history (+ term helpers). */
|
||||
/* ------------------------------------------------------------------ */
|
||||
void load_history();
|
||||
void save_history();
|
||||
void add_history(std::string_view s);
|
||||
std::string read_line(std::string_view prompt, bool &ok);
|
||||
std::string read_plain(std::string_view prompt, bool &ok);
|
||||
int term_width();
|
||||
|
||||
#endif /* BANTAM_HPP */
|
||||
Reference in New Issue
Block a user