Skip to content

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 →