feat: add Kimi Code and web APIs
This commit is contained in:
+47
-3
@@ -22,6 +22,25 @@
|
||||
#define ERRBODY_MAX 4096
|
||||
#define LLM_MAX_RETRIES 3
|
||||
|
||||
static int api_host_has(const char *base, const char *needle) {
|
||||
return base && needle && strstr(base, needle) != NULL;
|
||||
}
|
||||
|
||||
static int is_kimi_api(const char *base) {
|
||||
return api_host_has(base, "api.moonshot.ai") ||
|
||||
api_host_has(base, "api.moonshot.cn") ||
|
||||
api_host_has(base, "api.kimi.ai") ||
|
||||
api_host_has(base, "api.kimi.com");
|
||||
}
|
||||
|
||||
static int is_kimi_k2(const char *model) {
|
||||
return model && strncmp(model, "kimi-k2", 7) == 0;
|
||||
}
|
||||
|
||||
static int is_kimi_k27(const char *model) {
|
||||
return model && strncmp(model, "kimi-k2.7-code", 14) == 0;
|
||||
}
|
||||
|
||||
static int ca_file_ok(const char *path) {
|
||||
if (!path || !path[0])
|
||||
return 0;
|
||||
@@ -452,8 +471,31 @@ char *cst_llm_build_body(const cst_llm_request_t *req) {
|
||||
return NULL;
|
||||
cJSON *root = cJSON_CreateObject();
|
||||
cJSON_AddStringToObject(root, "model", req->model);
|
||||
if (req->reasoning_effort && req->reasoning_effort[0])
|
||||
const int kimi = is_kimi_api(req->api_base);
|
||||
const int kimi_k2 = kimi && is_kimi_k2(req->model);
|
||||
if (req->reasoning_effort && req->reasoning_effort[0] && !kimi_k2)
|
||||
cJSON_AddStringToObject(root, "reasoning_effort", req->reasoning_effort);
|
||||
if (kimi_k2) {
|
||||
/* K2.6/K2.7 do not understand K3's top-level reasoning_effort. They
|
||||
* expose thinking as an object and require preserved reasoning to be
|
||||
* sent back on the next turn. K2.7-code is always enabled/kept. */
|
||||
cJSON *thinking = cJSON_AddObjectToObject(root, "thinking");
|
||||
cJSON_AddStringToObject(thinking, "type", "enabled");
|
||||
if (req->send_reasoning || is_kimi_k27(req->model))
|
||||
cJSON_AddStringToObject(thinking, "keep", "all");
|
||||
}
|
||||
if (kimi && (!getenv("CST_NO_CACHE_HINTS") ||
|
||||
!getenv("CST_NO_CACHE_HINTS")[0] ||
|
||||
getenv("CST_NO_CACHE_HINTS")[0] == '0')) {
|
||||
/* Kimi's implicit cache defaults to 5m. Agent sessions commonly pause
|
||||
* longer than that, so opt into the 1h tier; users can select 5m/1h. */
|
||||
const char *ttl = getenv("CST_KIMI_CACHE_TTL");
|
||||
if (!ttl || (strcmp(ttl, "5m") != 0 && strcmp(ttl, "1h") != 0))
|
||||
ttl = "1h";
|
||||
cJSON *cache = cJSON_AddObjectToObject(root, "prompt_cache_options");
|
||||
cJSON_AddStringToObject(cache, "mode", "implicit");
|
||||
cJSON_AddStringToObject(cache, "ttl", ttl);
|
||||
}
|
||||
cJSON_AddTrueToObject(root, "stream");
|
||||
const char *nousage = getenv("CST_NO_STREAM_USAGE");
|
||||
if (!nousage || !nousage[0] || nousage[0] == '0') {
|
||||
@@ -586,8 +628,10 @@ char *cst_llm_build_body(const cst_llm_request_t *req) {
|
||||
if (req->send_reasoning && m->reasoning && m->reasoning[0])
|
||||
cJSON_AddItemToObject(o, "reasoning_content",
|
||||
clean_string(m->reasoning, 0));
|
||||
if (m->prefix)
|
||||
cJSON_AddTrueToObject(o, "prefix");
|
||||
if (m->prefix) {
|
||||
/* Kimi calls the OpenAI-style assistant prefill flag `partial`. */
|
||||
cJSON_AddTrueToObject(o, kimi ? "partial" : "prefix");
|
||||
}
|
||||
}
|
||||
cJSON_AddItemToArray(msgs, o);
|
||||
if (role == CST_ROLE_TOOL && n_att)
|
||||
|
||||
Reference in New Issue
Block a user