34namespace entropic::cli {
44std::filesystem::path default_model_dir()
46 if (
const char* env = std::getenv(
"ENTROPIC_MODEL_DIR"); env && *env) {
47 return std::filesystem::path(env);
49 const char* home = std::getenv(
"HOME");
51 return std::filesystem::path(home) /
".entropic" /
"models";
53 return std::filesystem::path(
"/opt/entropic/models");
64 std::printf(
"%-12s %-6s %s\n",
"KEY",
"SIZE",
"DESCRIPTION");
65 std::printf(
"%-12s %-6s %s\n",
"---",
"----",
"-----------");
66 for (
const auto& [key, entry] : registry.entries()) {
67 std::printf(
"%-12s %4.1fGB %s\n",
68 key.c_str(), entry.size_gb, entry.description.c_str());
86int curl_download(
const std::string& url,
const std::filesystem::path& dest)
90 std::fprintf(stderr,
"fork failed\n");
94 execlp(
"curl",
"curl",
101 static_cast<char*
>(
nullptr));
102 std::fprintf(stderr,
"execlp(curl) failed — is curl installed?\n");
106 waitpid(pid, &status, 0);
107 if (WIFEXITED(status)) {
108 return WEXITSTATUS(status);
117 std::filesystem::path override_dir;
121 bool want_list =
false;
132 int& i,
int argc,
char* argv[], std::string& dst)
134 if (arg == flag && i + 1 < argc) {
169 for (
int i = 1; i < argc; i++) {
170 std::string arg = argv[i];
171 if (arg ==
"--list" || arg ==
"-l") { out.want_list =
true;
continue; }
172 if (arg ==
"--dir" && i + 1 < argc) { out.override_dir = argv[++i];
continue; }
174 if (!arg.empty() && arg[0] !=
'-') { out.key = arg;
continue; }
175 std::fprintf(stderr,
"entropic download: unknown option '%s'\n",
195 if (!args.key.empty()) {
return args.key; }
196 const bool hf = !args.family.empty();
197 const bool hs = !args.size.empty();
198 const bool hq = !args.quant.empty();
199 if (!hf && !hs && !hq) {
return ""; }
201 if (!(hf && hs && hq)) {
202 std::fprintf(stderr,
"entropic download: --family/--size/--quant "
203 "must be given together (or pass a model key).\n");
205 key = registry.
find_by(args.family, args.size, args.quant);
207 std::fprintf(stderr,
"entropic download: no bundled model matches "
208 "--family %s --size %s --quant %s. Try --list.\n",
209 args.family.c_str(), args.size.c_str(),
225 const auto* entry = registry.
get(key);
228 "entropic download: unknown model key '%s'. "
229 "Run `entropic download --list` for available keys.\n",
233 if (entry->url.empty()) {
235 "entropic download: model '%s' has no URL in the registry.\n",
249 const std::filesystem::path& target_dir,
250 const std::string& key)
254 std::filesystem::create_directories(target_dir, ec);
255 auto target_file = target_dir / (entry.
name +
".gguf");
256 const bool already = std::filesystem::exists(target_file)
257 && std::filesystem::file_size(target_file) > 0;
260 std::fprintf(stderr,
"entropic download: cannot create %s: %s\n",
261 target_dir.c_str(), ec.message().c_str());
263 }
else if (already) {
264 std::printf(
"Model '%s' already at %s — nothing to do.\n",
265 key.c_str(), target_file.c_str());
267 std::printf(
"Downloading %s (%.1f GB)\n from: %s\n to: %s\n",
269 entry.
url.c_str(), target_file.c_str());
270 rc = curl_download(entry.
url, target_file);
273 "entropic download: curl exited with status %d\n"
274 "Partial file left at %s — rerun to resume.\n",
275 rc, target_file.c_str());
277 std::printf(
"\nDone. Point the engine at this dir with:\n"
278 " export ENTROPIC_MODEL_DIR=%s\n",
303 const std::filesystem::path& target_dir)
307 if (mm ==
nullptr) {
return 0; }
308 std::printf(
"Fetching paired mmproj '%s' for vision support\n",
333 const bool has_selector = !args.family.empty() || !args.size.empty()
334 || !args.quant.empty();
335 if (args.want_list) {
336 rc = list_models(registry);
341 "Usage: entropic download <model-key>\n"
342 " entropic download --family F --size S --quant Q\n"
343 " entropic download --list\n"
344 " entropic download --dir DIR <model-key>\n");
347 }
else if (
const auto* entry =
resolve_entry(registry, key); !entry) {
350 auto target_dir = args.override_dir.empty()
351 ? default_model_dir() : args.override_dir;
352 rc =
fetch_to(*entry, target_dir, key);
381 "entropic download: cannot find bundled_models.yaml: %s\n"
382 "(Expected under <install-prefix>/share/entropic/ or the source tree's data/.)\n",
Bundled model registry — resolves keys to filesystem paths.
Bundled model registry loaded from bundled_models.yaml.
std::string auto_discover_and_load()
Auto-discover and load bundled_models.yaml.
std::string find_by(const std::string &family, const std::string &size_label, const std::string &quant) const
Look up a registry key by (family, size, quant) (gh#62).
const BundledModelEntry * get(const std::string &key) const
Get entry by key.
const entropic::config::BundledModelEntry * resolve_entry(const entropic::config::BundledModels ®istry, const std::string &key)
Resolve a registry entry by key with user-friendly error output.
int fetch_mmproj_if_paired(const entropic::config::BundledModelEntry &entry, const entropic::config::BundledModels ®istry, const std::filesystem::path &target_dir)
Paired-mmproj follow-up fetch (gh#42, v2.1.8).
static bool match_any_value_flag(const std::string &arg, int &i, int argc, char *argv[], DownloadArgs &out)
Try the gh#62 selector value-flags (–family/–size/–quant).
DownloadArgs parse_download_args(int argc, char *argv[])
Parse command-line args for entropic download.
int run_download(int argc, char *argv[])
Handle entropic download subcommand.
std::string resolve_selector_key(const DownloadArgs &args, const entropic::config::BundledModels ®istry)
Resolve the target model key from an explicit key or a --family/--size/--quant selector (gh#62).
int fetch_to(const entropic::config::BundledModelEntry &entry, const std::filesystem::path &target_dir, const std::string &key)
Download one registry entry to a target directory.
int dispatch(const DownloadArgs &args, const entropic::config::BundledModels ®istry)
Handle entropic download subcommand.
static bool match_value_flag(const std::string &arg, const char *flag, int &i, int argc, char *argv[], std::string &dst)
Match a --flag VALUE pair and consume the value (gh#62).
Entry in the bundled model registry.
std::string url
Download URL.
double size_gb
Model size in GB.
std::string mmproj_key
Paired mmproj registry key, or empty (gh#42, v2.1.8).
std::string name
Model filename stem (e.g., "Qwen3.5-35B-A3B-UD-IQ3_XXS")