#ifndef CST_MODELS_H #define CST_MODELS_H /* Model registry: what cst-agent knows about providers and models. * * Three layers, highest first, merged field by field: * 1. /models.json user overrides and extra providers * 2. /models-cache/.json GET /models metadata, exact id * 3. built-in data (src/models_builtin.json, embedded at build time) * then defaults (128000 tokens, vision unknown). Model rules match the name * without its "vendor/" prefix, case-insensitively: a plain "match" is a * prefix, one with '*' is a glob, one with '/' is tested against the full * id. Within a layer the most specific rule (most literal characters) that * sets a field wins, so table order does not matter. * * CST_CTX_TOKENS, CST_PRICE, CST_MODELS and CST_NO_CACHE_HINTS still * override everything. */ #include "cst_agent.h" #ifdef __cplusplus extern "C" { #endif typedef struct { long context; /* tokens */ int vision; /* 1 takes images, 0 text only, -1 unknown */ int cache_style; /* cst_cache_style_t */ int reasoning; /* takes OpenAI-style reasoning_effort */ int has_price; cst_price_t price; /* Layers that supplied anything, highest first: "user+api+built-in", * "default", "env+built-in"... */ char source[48]; } cst_model_info_t; /* provider may be NULL: then every provider's fetched cache is searched. */ void cst_model_info(const char *provider, const char *model, cst_model_info_t *out); /* Short picker label: "1M · vision", "200K · text only", "128K". */ void cst_model_info_label(const cst_model_info_t *mi, char *out, size_t n); /* One entry of GET /models, with the optional OpenRouter-style metadata. */ typedef struct { char id[128]; long context; /* 0 = not given */ int vision; /* -1 = not given */ int has_price; /* prices in USD per 1M tokens */ double miss, hit, write, out; } cst_model_meta_t; /* Like cst_llm_list_models, keeping context_length, * architecture.input_modalities (or modalities) and pricing when present. */ int cst_llm_list_models_meta(const char *api_base, const char *api_key, cst_model_meta_t *out, int max_out, char *err, size_t err_sz); #define CST_MODELS_CACHE_TTL (24L * 3600) /* Store a fetched list as /models-cache/.json and use it * from now on. 0 / -1. */ int cst_models_cache_save(const char *provider, const char *api_base, const cst_model_meta_t *list, int n); /* The cached list for provider: count (up to max), or -1 when there is * none. *age_s gets the seconds since it was fetched. */ int cst_models_cache_load(const char *provider, cst_model_meta_t *out, int max, long *age_s); /* The "models" a provider entry lists (built-in or user file). */ int cst_provider_models(const cst_provider_t *p, char out[][128], int max); /* Where a provider entry came from: "built-in" or "user". */ const char *cst_provider_source(const cst_provider_t *p); /* The user file's path (it may not exist). */ int cst_models_user_path(char *out, size_t out_sz); /* Add or replace a provider in the user file (layer 1 above) and reload the * registry: this is how a provider the presets do not know becomes one. * name is 1-31 characters of letters, digits, '.', '_' or '-'; api_base is * required; key_env names the variable its key may come from; default_model * and models[] are what the model picker offers (a fetched /models list still * wins). An entry with a preset's name overrides that preset, everything else * in the file (model rules) is kept. 0, or -1 with err filled. */ int cst_models_user_set_provider(const char *name, const char *api_base, const char *key_env, const char *default_model, const char *const *models, int nmodels, char *err, size_t err_sz); /* Drop a provider from the user file (a preset of the same name stays). * 1 = removed, 0 = it was not there, -1 with err. */ int cst_models_user_drop_provider(const char *name, char *err, size_t err_sz); /* Drop everything and read the built-in data, the user file and the caches * again. Provider pointers stay valid but may name another provider. */ void cst_models_reload(void); /* Tests: load these documents instead of the built-in data and the user * file (NULL = none). Caches still come from . 0, or -1 with err. */ int cst_models_load_json(const char *builtin_json, const char *user_json, char *err, size_t err_sz); /* The embedded built-in document. */ const char *cst_models_builtin_json(void); /* Problems found while loading (bad user file...), or "". */ const char *cst_models_load_error(void); #ifdef __cplusplus } #endif #endif