#define _DEFAULT_SOURCE #include "cst_agent.h" #include "os_compat.h" #include #include #include #include #ifdef _WIN32 #include #else #include #endif /* Config dir via os_compat: ~/.config/cst-agent or %APPDATA%\cst-agent */ static int credentials_path(char *out, size_t n) { char dir[OS_PATH_MAX]; if (os_config_dir(dir, sizeof(dir)) != 0) return -1; return os_path_join(out, n, dir, "credentials"); } int cst_creds_load_api_key(char *out, size_t out_sz) { if (!out || out_sz < 2) return -1; out[0] = 0; char path[OS_PATH_MAX]; if (credentials_path(path, sizeof(path)) != 0) return -1; FILE *fp = fopen(path, "r"); if (!fp) return -1; char line[1024]; while (fgets(line, sizeof(line), fp)) { if (strncmp(line, "api_key=", 8) != 0) continue; char *v = line + 8; size_t len = strlen(v); while (len > 0 && (v[len - 1] == '\n' || v[len - 1] == '\r')) v[--len] = 0; if (len == 0 || len + 1 > out_sz) { fclose(fp); return -1; } memcpy(out, v, len + 1); fclose(fp); return 0; } fclose(fp); return -1; } int cst_creds_save_api_key(const char *key) { if (!key || !key[0]) return -1; char dir[OS_PATH_MAX], path[OS_PATH_MAX]; if (os_config_dir(dir, sizeof(dir)) != 0) return -1; if (os_mkdir(dir, 0700) != 0) return -1; if (credentials_path(path, sizeof(path)) != 0) return -1; FILE *fp = fopen(path, "w"); if (!fp) return -1; fprintf(fp, "api_key=%s\n", key); fprintf(fp, "api_base=https://api.minimax.cn/v1\n"); fprintf(fp, "model=MiniMax-M2.7\n"); fclose(fp); (void)os_chmod_private(path); return 0; } /* Zenity on Unix; stdin prompt elsewhere / when zenity missing. */ int cst_creds_prompt_api_key(char *out, size_t out_sz) { if (!out || out_sz < 2) return -1; out[0] = 0; #ifndef _WIN32 FILE *fp = popen( "zenity --password --title='CST-Agent / MiniMax' " "--text='请输入 MiniMax API Key(将保存到配置目录 credentials)' " "2>/dev/null", "r"); if (fp) { if (fgets(out, (int)out_sz, fp)) { int st = pclose(fp); size_t len = strlen(out); while (len > 0 && (out[len - 1] == '\n' || out[len - 1] == '\r')) out[--len] = 0; if (st == 0 && len > 0) return 0; } else { pclose(fp); } out[0] = 0; } #endif /* Fallback: console prompt (headless / Windows / no zenity). */ fprintf(stderr, "CST-Agent: enter MiniMax API Key (saved to config dir): "); fflush(stderr); if (!fgets(out, (int)out_sz, stdin)) { out[0] = 0; return -1; } size_t len = strlen(out); while (len > 0 && (out[len - 1] == '\n' || out[len - 1] == '\r')) out[--len] = 0; if (len == 0) { out[0] = 0; return -1; } return 0; } int cst_creds_ensure_api_key(char *out, size_t out_sz) { const char *env = getenv("CST_API_KEY"); if (!env || !env[0]) env = getenv("MINIMAX_API_KEY"); if (!env || !env[0]) env = getenv("OPENAI_API_KEY"); if (env && env[0]) { snprintf(out, out_sz, "%s", env); return 0; } if (cst_creds_load_api_key(out, out_sz) == 0 && out[0]) return 0; if (cst_creds_prompt_api_key(out, out_sz) != 0) return -1; if (cst_creds_save_api_key(out) != 0) fprintf(stderr, "warning: failed to save credentials file\n"); else fprintf(stderr, "saved API key to config directory\n"); return 0; }