Rename config commands to recipe

- upload-config -> upload-recipe
- configs -> recipes
- config -> recipe
- run-config -> run-recipe
- delete-config -> delete-recipe
- Update all API URLs to use /recipes/ endpoints
- Update all display messages and help text

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
gilesb
2026-01-08 14:59:31 +00:00
parent ce90570039
commit f4da1fffb2

116
artdag.py
View File

@@ -876,12 +876,12 @@ def collection_delete(name):
click.echo(f"Deleted collection: {name}") click.echo(f"Deleted collection: {name}")
# ============ Config Commands ============ # ============ Recipe Commands ============
@cli.command("upload-config") @cli.command("upload-recipe")
@click.argument("filepath", type=click.Path(exists=True)) @click.argument("filepath", type=click.Path(exists=True))
def upload_config(filepath): def upload_recipe(filepath):
"""Upload a config YAML file. Requires login.""" """Upload a recipe YAML file. Requires login."""
token_data = load_token() token_data = load_token()
if not token_data.get("access_token"): if not token_data.get("access_token"):
click.echo("Not logged in. Please run: artdag login <username>", err=True) click.echo("Not logged in. Please run: artdag login <username>", err=True)
@@ -890,14 +890,14 @@ def upload_config(filepath):
# Validate YAML locally first # Validate YAML locally first
with open(filepath) as f: with open(filepath) as f:
try: try:
config = yaml.safe_load(f) recipe = yaml.safe_load(f)
except yaml.YAMLError as e: except yaml.YAMLError as e:
click.echo(f"Invalid YAML: {e}", err=True) click.echo(f"Invalid YAML: {e}", err=True)
sys.exit(1) sys.exit(1)
# Check required fields # Check required fields
if not config.get("name"): if not recipe.get("name"):
click.echo("Config must have a 'name' field", err=True) click.echo("Recipe must have a 'name' field", err=True)
sys.exit(1) sys.exit(1)
# Upload # Upload
@@ -905,15 +905,15 @@ def upload_config(filepath):
with open(filepath, "rb") as f: with open(filepath, "rb") as f:
files = {"file": (Path(filepath).name, f)} files = {"file": (Path(filepath).name, f)}
headers = {"Authorization": f"Bearer {token_data['access_token']}"} headers = {"Authorization": f"Bearer {token_data['access_token']}"}
resp = requests.post(f"{get_server()}/configs/upload", files=files, headers=headers) resp = requests.post(f"{get_server()}/recipes/upload", files=files, headers=headers)
if resp.status_code == 401: if resp.status_code == 401:
click.echo("Authentication failed. Please login again.", err=True) click.echo("Authentication failed. Please login again.", err=True)
sys.exit(1) sys.exit(1)
resp.raise_for_status() resp.raise_for_status()
result = resp.json() result = resp.json()
click.echo(f"Uploaded config: {result['name']} v{result.get('version', '1.0')}") click.echo(f"Uploaded recipe: {result['name']} v{result.get('version', '1.0')}")
click.echo(f"Config ID: {result['config_id']}") click.echo(f"Recipe ID: {result['recipe_id']}")
click.echo(f"Variable inputs: {result['variable_inputs']}") click.echo(f"Variable inputs: {result['variable_inputs']}")
click.echo(f"Fixed inputs: {result['fixed_inputs']}") click.echo(f"Fixed inputs: {result['fixed_inputs']}")
except requests.RequestException as e: except requests.RequestException as e:
@@ -921,76 +921,76 @@ def upload_config(filepath):
sys.exit(1) sys.exit(1)
@cli.command("configs") @cli.command("recipes")
@click.option("--limit", "-l", default=10, help="Max configs to show") @click.option("--limit", "-l", default=10, help="Max recipes to show")
def list_configs(limit): def list_recipes(limit):
"""List uploaded configs.""" """List uploaded recipes."""
try: try:
resp = requests.get(f"{get_server()}/configs") resp = requests.get(f"{get_server()}/recipes")
resp.raise_for_status() resp.raise_for_status()
data = resp.json() data = resp.json()
except requests.RequestException as e: except requests.RequestException as e:
click.echo(f"Failed to list configs: {e}", err=True) click.echo(f"Failed to list recipes: {e}", err=True)
sys.exit(1) sys.exit(1)
configs = data.get("configs", []) recipes = data.get("recipes", [])
if not configs: if not recipes:
click.echo("No configs found.") click.echo("No recipes found.")
return return
click.echo(f"{'Name':<20} {'Version':<8} {'Variables':<10} {'Config ID':<24}") click.echo(f"{'Name':<20} {'Version':<8} {'Variables':<10} {'Recipe ID':<24}")
click.echo("-" * 70) click.echo("-" * 70)
for config in configs[:limit]: for recipe in recipes[:limit]:
config_id = config["config_id"][:20] + "..." recipe_id = recipe["recipe_id"][:20] + "..."
var_count = len(config.get("variable_inputs", [])) var_count = len(recipe.get("variable_inputs", []))
click.echo(f"{config['name']:<20} {config['version']:<8} {var_count:<10} {config_id}") click.echo(f"{recipe['name']:<20} {recipe['version']:<8} {var_count:<10} {recipe_id}")
@cli.command("config") @cli.command("recipe")
@click.argument("config_id") @click.argument("recipe_id")
def show_config(config_id): def show_recipe(recipe_id):
"""Show details of a config.""" """Show details of a recipe."""
try: try:
resp = requests.get(f"{get_server()}/configs/{config_id}") resp = requests.get(f"{get_server()}/recipes/{recipe_id}")
if resp.status_code == 404: if resp.status_code == 404:
click.echo(f"Config not found: {config_id}", err=True) click.echo(f"Recipe not found: {recipe_id}", err=True)
sys.exit(1) sys.exit(1)
resp.raise_for_status() resp.raise_for_status()
config = resp.json() recipe = resp.json()
except requests.RequestException as e: except requests.RequestException as e:
click.echo(f"Failed to get config: {e}", err=True) click.echo(f"Failed to get recipe: {e}", err=True)
sys.exit(1) sys.exit(1)
click.echo(f"Name: {config['name']}") click.echo(f"Name: {recipe['name']}")
click.echo(f"Version: {config['version']}") click.echo(f"Version: {recipe['version']}")
click.echo(f"Description: {config.get('description', 'N/A')}") click.echo(f"Description: {recipe.get('description', 'N/A')}")
click.echo(f"Config ID: {config['config_id']}") click.echo(f"Recipe ID: {recipe['recipe_id']}")
click.echo(f"Owner: {config.get('owner', 'N/A')}") click.echo(f"Owner: {recipe.get('owner', 'N/A')}")
click.echo(f"Uploaded: {config['uploaded_at']}") click.echo(f"Uploaded: {recipe['uploaded_at']}")
if config.get("variable_inputs"): if recipe.get("variable_inputs"):
click.echo("\nVariable Inputs:") click.echo("\nVariable Inputs:")
for inp in config["variable_inputs"]: for inp in recipe["variable_inputs"]:
req = "*" if inp.get("required", True) else "" req = "*" if inp.get("required", True) else ""
click.echo(f" - {inp['name']}{req}: {inp.get('description', 'No description')}") click.echo(f" - {inp['name']}{req}: {inp.get('description', 'No description')}")
if config.get("fixed_inputs"): if recipe.get("fixed_inputs"):
click.echo("\nFixed Inputs:") click.echo("\nFixed Inputs:")
for inp in config["fixed_inputs"]: for inp in recipe["fixed_inputs"]:
click.echo(f" - {inp['asset']}: {inp['content_hash'][:16]}...") click.echo(f" - {inp['asset']}: {inp['content_hash'][:16]}...")
@cli.command("run-config") @cli.command("run-recipe")
@click.argument("config_id") @click.argument("recipe_id")
@click.option("--input", "-i", "inputs", multiple=True, help="Input as node_id:content_hash") @click.option("--input", "-i", "inputs", multiple=True, help="Input as node_id:content_hash")
@click.option("--wait", "-w", is_flag=True, help="Wait for completion") @click.option("--wait", "-w", is_flag=True, help="Wait for completion")
def run_config(config_id, inputs, wait): def run_recipe(recipe_id, inputs, wait):
"""Run a config with variable inputs. Requires login. """Run a recipe with variable inputs. Requires login.
CONFIG_ID: The config ID (content hash) RECIPE_ID: The recipe ID (content hash)
Example: artdag run-config abc123 -i source_image:def456 Example: artdag run-recipe abc123 -i source_image:def456
""" """
token_data = load_token() token_data = load_token()
if not token_data.get("access_token"): if not token_data.get("access_token"):
@@ -1010,7 +1010,7 @@ def run_config(config_id, inputs, wait):
try: try:
headers = {"Authorization": f"Bearer {token_data['access_token']}"} headers = {"Authorization": f"Bearer {token_data['access_token']}"}
resp = requests.post( resp = requests.post(
f"{get_server()}/configs/{config_id}/run", f"{get_server()}/recipes/{recipe_id}/run",
json={"inputs": input_dict}, json={"inputs": input_dict},
headers=headers headers=headers
) )
@@ -1022,7 +1022,7 @@ def run_config(config_id, inputs, wait):
click.echo(f"Error: {error}", err=True) click.echo(f"Error: {error}", err=True)
sys.exit(1) sys.exit(1)
if resp.status_code == 404: if resp.status_code == 404:
click.echo(f"Config not found: {config_id}", err=True) click.echo(f"Recipe not found: {recipe_id}", err=True)
sys.exit(1) sys.exit(1)
resp.raise_for_status() resp.raise_for_status()
result = resp.json() result = resp.json()
@@ -1054,24 +1054,24 @@ def run_config(config_id, inputs, wait):
sys.exit(1) sys.exit(1)
@cli.command("delete-config") @cli.command("delete-recipe")
@click.argument("config_id") @click.argument("recipe_id")
@click.option("--force", "-f", is_flag=True, help="Skip confirmation") @click.option("--force", "-f", is_flag=True, help="Skip confirmation")
def delete_config(config_id, force): def delete_recipe(recipe_id, force):
"""Delete a config. Requires login.""" """Delete a recipe. Requires login."""
token_data = load_token() token_data = load_token()
if not token_data.get("access_token"): if not token_data.get("access_token"):
click.echo("Not logged in. Please run: artdag login <username>", err=True) click.echo("Not logged in. Please run: artdag login <username>", err=True)
sys.exit(1) sys.exit(1)
if not force: if not force:
if not click.confirm(f"Delete config {config_id[:16]}...?"): if not click.confirm(f"Delete recipe {recipe_id[:16]}...?"):
click.echo("Cancelled.") click.echo("Cancelled.")
return return
try: try:
headers = {"Authorization": f"Bearer {token_data['access_token']}"} headers = {"Authorization": f"Bearer {token_data['access_token']}"}
resp = requests.delete(f"{get_server()}/configs/{config_id}", headers=headers) resp = requests.delete(f"{get_server()}/recipes/{recipe_id}", headers=headers)
if resp.status_code == 401: if resp.status_code == 401:
click.echo("Authentication failed. Please login again.", err=True) click.echo("Authentication failed. Please login again.", err=True)
sys.exit(1) sys.exit(1)
@@ -1080,14 +1080,14 @@ def delete_config(config_id, force):
click.echo(f"Error: {error}", err=True) click.echo(f"Error: {error}", err=True)
sys.exit(1) sys.exit(1)
if resp.status_code == 404: if resp.status_code == 404:
click.echo(f"Config not found: {config_id}", err=True) click.echo(f"Recipe not found: {recipe_id}", err=True)
sys.exit(1) sys.exit(1)
resp.raise_for_status() resp.raise_for_status()
except requests.RequestException as e: except requests.RequestException as e:
click.echo(f"Delete failed: {e}", err=True) click.echo(f"Delete failed: {e}", err=True)
sys.exit(1) sys.exit(1)
click.echo(f"Deleted config: {config_id[:16]}...") click.echo(f"Deleted recipe: {recipe_id[:16]}...")
if __name__ == "__main__": if __name__ == "__main__":