Files
valknar f24d138ab4 feat: initial Freepik AI CLI
Sophisticated Python CLI for generating and manipulating images and
video via the Freepik API, built with typer + rich.

Commands:
- generate-image: text-to-image with 8 models (flux-2-pro, mystic, seedream, etc.)
- generate-video: image-to-video with 7 models (kling, minimax, runway, etc.)
- generate-icon: text-to-icon in solid/outline/color/flat/sticker styles
- upscale-image: 3 modes (precision-v2, precision, creative) + 2x/4x scale
- upscale-video: standard/turbo modes
- expand-image: outpainting with per-side pixel offsets
- relight: AI-controlled relighting (Premium)
- style-transfer: artistic style application (Premium)
- describe-image: reverse-engineer an image into a prompt
- config set/get/show/reset: configuration management

Features: Rich Live polling panel, exponential backoff, --wait/--no-wait,
auto-timestamped output filenames, streaming download with progress bar,
FREEPIK_API_KEY env var support, venv-based setup.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-08 10:56:45 +02:00

121 lines
3.6 KiB
Python

"""config set/get/show/reset commands."""
from __future__ import annotations
from typing import Annotated, Optional
import typer
from rich.prompt import Confirm
from freepik_cli.utils.config import CONFIG_FILE, FreepikConfig
from freepik_cli.utils.console import console, print_config_table, print_config_toml, print_error, print_warning
app = typer.Typer(
name="config",
help="[bold]Manage[/bold] Freepik CLI configuration.",
rich_markup_mode="rich",
no_args_is_help=True,
)
@app.command("show")
def config_show(
toml: Annotated[
bool,
typer.Option("--toml", help="Output as TOML syntax instead of a table"),
] = False,
) -> None:
"""[bold]Show[/bold] all current configuration values."""
config = FreepikConfig.load()
d = config.to_display_dict()
if toml:
print_config_toml(d)
else:
print_config_table(d)
console.print(f"\n[dim]Config file:[/dim] {CONFIG_FILE}")
@app.command("get")
def config_get(
key: Annotated[str, typer.Argument(help="Config key to retrieve")],
) -> None:
"""[bold]Get[/bold] the value of a single configuration key."""
config = FreepikConfig.load()
d = config.to_display_dict()
if key not in d:
print_error(
f"Unknown config key: '{key}'",
hint=f"Run [cyan]freepik config show[/cyan] to see all available keys.",
)
raise typer.Exit(1)
value = d[key]
if key == "api_key" and value:
masked = f"{'*' * 8}{str(value)[-4:]}"
console.print(f"[dim]{key}[/dim] = [bold]{masked}[/bold] [dim](masked)[/dim]")
elif value is None:
console.print(f"[dim]{key}[/dim] = [dim]not set[/dim]")
else:
console.print(f"[dim]{key}[/dim] = [bold]{value}[/bold]")
@app.command("set")
def config_set(
key: Annotated[str, typer.Argument(help="Config key to update")],
value: Annotated[str, typer.Argument(help="New value")],
) -> None:
"""
[bold]Set[/bold] a configuration value.
[dim]Examples:[/dim]
freepik config set default_image_model mystic
freepik config set default_output_dir ~/images
freepik config set poll_timeout 300
[dim]Note:[/dim] The API key is never saved to disk. Use the
[cyan]FREEPIK_API_KEY[/cyan] environment variable instead.
"""
config = FreepikConfig.load()
try:
config.set_value(key, value)
console.print(f"[success]✓[/success] Set [cyan]{key}[/cyan] = [bold]{value}[/bold]")
console.print(f"[dim]Saved to:[/dim] {CONFIG_FILE}")
except ValueError as exc:
print_error(str(exc))
raise typer.Exit(1)
@app.command("reset")
def config_reset(
yes: Annotated[
bool,
typer.Option("--yes", "-y", help="Skip confirmation prompt"),
] = False,
) -> None:
"""[bold]Reset[/bold] all configuration to defaults."""
if not yes:
confirmed = Confirm.ask(
"[warning]Reset all configuration to defaults?[/warning]",
console=console,
default=False,
)
if not confirmed:
console.print("[dim]Aborted.[/dim]")
return
if CONFIG_FILE.exists():
CONFIG_FILE.unlink()
console.print(f"[success]✓[/success] Configuration reset. Deleted: [path]{CONFIG_FILE}[/path]")
else:
print_warning("No config file found — already at defaults.")
@app.command("path")
def config_path() -> None:
"""Show the path to the configuration file."""
console.print(f"[path]{CONFIG_FILE}[/path]")
if CONFIG_FILE.exists():
console.print("[dim](file exists)[/dim]")
else:
console.print("[dim](file does not exist — using defaults)[/dim]")