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 + token math). */
#include <stdint.h>
#include <stdio.h>
#include <string.h>
static const char *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",
};
#define N_WORDS (sizeof POEM_WORDS / sizeof POEM_WORDS[0])
/* FNV-1a 32-bit hash — turns the spec into a deterministic seed / id. */
static uint32_t hash_string(const char *s) {
uint32_t h = 0x811c9dc5u;
for (; *s; s++) { h ^= (uint8_t)*s; h *= 0x01000193u; }
return h;
}
/* mulberry32 — tiny seeded PRNG; same seed, same sequence, forever. */
typedef struct { uint32_t a; } rng_t;
static double rng_next(rng_t *r) {
r->a += 0x6d2b79f5u;
uint32_t a = r->a;
uint32_t t = (a ^ (a >> 15)) * (a | 1u);
t = (t + ((t ^ (t >> 7)) * (t | 61u))) ^ t;
return (double)(t ^ (t >> 14)) / 4294967296.0;
}
/* ~4 chars per token, floor of 1 — deterministic, no tokenizer needed. */
static int token_count(const char *text) {
size_t len = strlen(text);
return len == 0 ? 0 : (int)((len + 3) / 4);
}
/* Cut text so it fits in max_tokens tokens (4 chars each). */
static void truncate_to_tokens(const char *text, int max_tokens, char *out, size_t outsz) {
if (token_count(text) <= max_tokens) { snprintf(out, outsz, "%s", text); return; }
snprintf(out, outsz, "%.*s", max_tokens * 4, text);
size_t n = strlen(out);
while (n > 0 && (out[n-1]==' '||out[n-1]=='\n'||out[n-1]=='\t')) out[--n] = '\0';
}
/* One poem line of 5-7 vocabulary words. */
static void make_line(rng_t *r, char *out, size_t outsz) {
int n = 5 + (int)(rng_next(r) * 3);
out[0] = '\0';
for (int i = 0; i < n; i++) {
const char *w = POEM_WORDS[(size_t)(rng_next(r) * N_WORDS)];
if (i) strncat(out, " ", outsz - strlen(out) - 1);
strncat(out, w, outsz - strlen(out) - 1);
}
}
/* Poem-ish lorem, grown line by line until the token budget is full. */
static void build_poem(uint32_t seed, int max_tokens, char *out, size_t outsz) {
rng_t r = { seed };
char line[160], candidate[4096], tmp[4096];
out[0] = '\0';
for (;;) {
make_line(&r, line, sizeof line);
snprintf(candidate, sizeof candidate, "%s%s%s", out, *out ? "\n" : "", line);
if (*out && token_count(candidate) > max_tokens) break;
strcpy(out, candidate);
}
truncate_to_tokens(out, max_tokens, tmp, sizeof tmp);
strcpy(out, tmp);
}
int main(void) {
const char *spec = "streamed-lorem|mock-gpt-4o-mini|24";
char id_seed[128], poem_seed[128], poem[4096];
snprintf(id_seed, sizeof id_seed, "%s|id", spec);
snprintf(poem_seed, sizeof poem_seed, "%s|poem", spec);
build_poem(hash_string(poem_seed), 24, poem, sizeof poem);
printf("id=chatcmpl-mock-%08x\n", (unsigned)hash_string(id_seed));
printf("%s\n", poem);
printf("tokens=%d\n", token_count(poem));
return 0;
}
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 →