Mock LLM Responder — C++ source
Generate deterministic mock LLM API responses - chat completion JSON, SSE event streams with chunk timing, and a replay curl - for testing clients without an API key.
This is the C++ implementation — the same logic the interactive tool runs, in a shareable, citable form.
// mock-llm-responder — C++ port: deterministic mock LLM responses (seeded PRNG + SSE chunks).
#include <algorithm>
#include <cctype>
#include <cstdint>
#include <cstdio>
#include <string>
#include <vector>
static const std::vector<std::string> POEM_WORDS = {
"cosmos", "nebula", "quantum", "signal", "photon", "drift", "orbit", "vector",
"cipher", "lumen", "aurora", "echo", "helix", "nova", "pulse", "tide",
"vertex", "zenith", "quasar", "ion", "halo", "flux", "prism", "comet",
};
// FNV-1a 32-bit hash — turns the spec into a deterministic seed / id.
static uint32_t hashString(const std::string &s) {
uint32_t h = 0x811c9dc5u;
for (char c : s) { h ^= static_cast<uint8_t>(c); h *= 0x01000193u; }
return h;
}
// mulberry32 — tiny seeded PRNG; same seed, same sequence, forever.
struct Rng {
uint32_t a = 0;
double next() {
a += 0x6d2b79f5u; // uint32 math wraps, mirroring Math.imul + >>> 0
uint32_t t = (a ^ (a >> 15)) * (a | 1u);
t = (t + ((t ^ (t >> 7)) * (t | 61u))) ^ t;
return static_cast<double>(t ^ (t >> 14)) / 4294967296.0;
}
};
// ~4 chars per token, floor of 1 — deterministic, no tokenizer needed.
static int tokenCount(const std::string &text) {
return text.empty() ? 0 : static_cast<int>(std::max<size_t>(1, (text.size() + 3) / 4));
}
// Cut text so it fits in maxTokens tokens (4 chars each).
static std::string truncateToTokens(const std::string &text, int maxTokens) {
if (tokenCount(text) <= maxTokens) return text;
std::string cut{text.substr(0, static_cast<size_t>(maxTokens) * 4)};
while (!cut.empty() && std::isspace(static_cast<unsigned char>(cut.back()))) cut.pop_back();
return cut;
}
// One poem line of 5-7 vocabulary words.
static std::string makeLine(Rng &rng) {
int n = 5 + static_cast<int>(rng.next() * 3);
std::string line; // words joined below; (i ? " " : "") keeps separators exact
for (int i = 0; i < n; i++)
line += (i ? " " : "") + POEM_WORDS[static_cast<size_t>(rng.next() * POEM_WORDS.size())];
return line;
}
// Poem-ish lorem, grown line by line until the token budget is full.
static std::string buildPoem(uint32_t seed, int maxTokens) {
Rng rng{seed};
std::string text;
for (;;) {
std::string candidate = text.empty() ? makeLine(rng) : text + '\n' + makeLine(rng);
if (!text.empty() && tokenCount(candidate) > maxTokens) break;
text = std::move(candidate);
}
return truncateToTokens(text, maxTokens);
}
// Split content into stream chunks (word tokens keep trailing whitespace).
static std::vector<std::string> chunkContent(const std::string &content, size_t perChunk) {
std::vector<std::string> words, chunks;
for (size_t i = 0; i < content.size();) {
size_t j = i; while (j < content.size() && !std::isspace(static_cast<unsigned char>(content[j]))) j++;
while (j < content.size() && std::isspace(static_cast<unsigned char>(content[j]))) j++;
words.push_back(content.substr(i, j - i));
i = j;
}
for (size_t k = 0; k < words.size(); k += perChunk) {
std::string chunk;
for (size_t m = k; m < std::min(k + perChunk, words.size()); m++) chunk += words[m];
chunks.push_back(std::move(chunk));
}
return chunks;
}
int main() {
const std::string spec = "streamed-lorem|mock-gpt-4o-mini|24"; // salted seeds: |id, |poem
std::string poem = buildPoem(hashString(spec + "|poem"), 24);
std::printf("id=chatcmpl-mock-%08x\n%s\n", hashString(spec + "|id"), poem.c_str());
std::printf("tokens=%d chunks=%zu\n", tokenCount(poem), chunkContent(poem, 4).size());
}
Also available in 13 other languages
Every CosmoDev tool ships its pure logic in TypeScript (web) and Go (CLI), with authored implementations in a dozen-plus languages — the same contract, ported. Compare all languages side by side →