Differentially verified against tai.py (4890 cases incl. real pty runs). Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
97 lines
5.1 KiB
C++
97 lines
5.1 KiB
C++
#include "../src/cli/cli.h"
|
|
#include "../src/shell/sandbox.h"
|
|
#include "../src/shell/session.h"
|
|
#include "../src/shell/pty.h"
|
|
#include "../src/shell/spinner.h"
|
|
#include "../src/shell/livestream.h"
|
|
#include "../src/shell/lanes.h"
|
|
#include "../src/shell/runlive.h"
|
|
#include "../src/shell/targets.h"
|
|
#include "../src/shell/glow.h"
|
|
#include "../src/llm/llm.h"
|
|
#include "../src/util/ansi.h"
|
|
#include "../src/util/text.h"
|
|
#include "../src/config/config.h"
|
|
#include "../src/config/consts.h"
|
|
#include <cassert>
|
|
#include <filesystem>
|
|
#include <cstdio>
|
|
using detz::llm::ChatClient;
|
|
using detz::llm::ChatRequest;
|
|
int main() {
|
|
detz::cli::Parser p;
|
|
const char* a0 = "detz";
|
|
auto c = p.parse(1, (char**)&a0);
|
|
assert(c.name == "--help");
|
|
assert(c.run() == 0);
|
|
// shell (full coverage: tests/shell_test.cpp, differential: tests/shell_parity.py)
|
|
assert(!detz::shell::CurlHint("curl http://x").empty());
|
|
assert(detz::shell::CurlHint("echo hi").empty());
|
|
assert(detz::shell::ShellTargets::Segment({"rm", "a"}).size() == 1);
|
|
{ detz::shell::RunLiveOptions o; auto r = detz::shell::RunLive::Run(detz::shell::Command::Shell("echo hi"), o);
|
|
assert(r.code == 0 && r.output == "hi\n" && !r.timedOut); }
|
|
{ detz::shell::LiveStream ls(4, 40, nullptr, false); ls.Feed("x"); assert(ls.shown() == 0); }
|
|
assert(detz::shell::Glow::Ellipsis("short", 60) == "short");
|
|
assert(detz::shell::Sandbox::kName == std::string("tai-box"));
|
|
// llm mocked transport
|
|
auto mock = [](const std::string&, const std::string&, const std::map<std::string,std::string>&) {
|
|
return std::string("{\"content\":\"hello\"}");
|
|
};
|
|
ChatClient cc("openai", "m", mock);
|
|
auto cr = cc.chat(ChatRequest{"m", {{"user", "hi"}}, false});
|
|
assert(cr.text == "hello");
|
|
auto smock = [](const std::string&, const std::string&, const std::map<std::string,std::string>&) {
|
|
return std::string("data: {\"content\":\"a\"}\n\ndata: [DONE]\n\n");
|
|
};
|
|
ChatClient cs("anthropic", "m", smock);
|
|
std::vector<std::string> got;
|
|
cs.chat_stream(ChatRequest{"m", {}, true}, [&](const std::string& d) { got.push_back(d); return true; });
|
|
assert(got.size() == 1);
|
|
bool threw = false;
|
|
try { ChatClient bad("openai", "m"); bad.chat(ChatRequest{}); } catch (const detz::llm::BackendError&) { threw = true; }
|
|
assert(threw);
|
|
detz::llm::ModelHealth h; h.record("a", false, 5); h.record("b", true, 9);
|
|
assert(h.size() == 2 && h.best()->model == "b");
|
|
assert(detz::llm::provider_names().find("openrouter") != std::string::npos);
|
|
assert(detz::llm::provider_info("xai").base_url.find("x.ai") != std::string::npos);
|
|
detz::llm::Opencode oc("http://localhost:9", mock);
|
|
assert(oc.complete("m", {}).text == "hello");
|
|
bool be = false;
|
|
try { detz::llm::Opencode no; no.complete("m", {}); } catch (const detz::llm::BackendError&) { be = true; }
|
|
assert(be);
|
|
// M2 util+config
|
|
assert(detz::Consts::kTotalStepCap == 500 && detz::Consts::kAuditMaxChars == 20000);
|
|
assert(std::string(detz::kDefaultModel) == "muse");
|
|
assert(!detz::ZenFreeModels().empty() && !detz::PollinationsModels().empty());
|
|
assert(detz::Paint("x", detz::Ansi::kRed).find("x") != std::string::npos);
|
|
assert(detz::Truncate("abc", 1500, 500) == "abc");
|
|
std::string big(3000, 'a');
|
|
assert(detz::Truncate(big, 100, 100).find("chars truncated") != std::string::npos);
|
|
assert(detz::TruncMarker(5).find("5") != std::string::npos);
|
|
assert(detz::CappedText(std::string("hi")).text == "hi");
|
|
assert(detz::ChunkLines("").empty());
|
|
assert(detz::ChunkLines("a\nb").size() == 1);
|
|
assert(detz::CollapseRepeatedLines("x\nx\nx").find("repeated 2") != std::string::npos);
|
|
assert(detz::CollapseRepeatedLines("a\nb").find("repeated") == std::string::npos);
|
|
{ auto [tags, rest] = detz::SplitLeadingTags("@a @b hello"); assert(tags.size() == 2 && rest == "hello"); }
|
|
{ auto [tags, rest] = detz::SplitLeadingTags("hi"); assert(tags.empty() && rest == "hi"); }
|
|
{ auto dir = std::filesystem::temp_directory_path().string();
|
|
std::string f = dir + "/detz_m2_test.txt"; FILE* fh = std::fopen(f.c_str(), "w"); std::fputs("x", fh); std::fclose(fh);
|
|
assert(detz::ExpandFileMentions("@detz_m2_test.txt", dir).find("detz_m2_test") != std::string::npos);
|
|
assert(detz::ExpandFileMentions("see @nope-missing-xyz", dir).find("@nope") != std::string::npos);
|
|
auto cf = detz::CompleteFiles("detz_m2_test", dir); assert(!cf.empty());
|
|
assert(detz::CompleteFiles("zzz-no-match-xyz", dir).empty());
|
|
std::filesystem::remove(f); }
|
|
{ detz::Config cfg = detz::Config::FromEnv(); assert(!cfg.model.empty());
|
|
assert(!detz::SettingsCatalog().empty());
|
|
assert(!detz::SplitModels("a, b;c").empty());
|
|
auto ids = detz::KnownModelIds(cfg); assert(!ids.empty());
|
|
auto rt = detz::ResolveTag("auto", {}, ids, "/tmp"); assert(rt.first == "auto");
|
|
auto ru = detz::ResolveTag("zzz-unknown-xyz", {}, ids, "/tmp"); assert(ru.first == "unknown");
|
|
std::map<std::string,std::string> bots = {{"bob", "BotBob"}};
|
|
auto rb = detz::ResolveTag("bob", bots, ids, "/tmp"); assert(rb.first == "bot"); }
|
|
std::puts("M2 OK");
|
|
std::puts("M4+M5 OK");
|
|
return 0;
|
|
}
|