Images - vision gate: text-only models get a note instead of image parts and no view_image tool; unknown models retry once without images on HTTP 400 - paste: Ctrl+V and /attach paste read the clipboard (wl-paste, xclip, pngpaste/osascript, Win32 PNG or CF_DIB converted to PNG); pasting image file paths attaches them - MCP image content is stored in the session and sent with the tool result - attach: rel path validation, base64 decode, /retry keeps images Model registry - built-in src/models_builtin.json embedded at build time, merged with <config>/models.json and cached GET /models metadata (context, vision, pricing); most specific rule wins per field - /model labels, /status source, --list-models [provider] Cache and cost - stable request prefix (frozen tools, notes as messages), DeepSeek prefix completion, OpenAI/Anthropic cache hints, /cost and hit rate in the status
93 lines
3.7 KiB
C
93 lines
3.7 KiB
C
#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. <config>/models.json user overrides and extra providers
|
|
* 2. <config>/models-cache/<provider>.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 <config>/models-cache/<provider>.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);
|
|
|
|
/* 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 <config>. 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
|