Rename content_hash to cid in CLI
Update CLI argument names and help text: - Change argument names from content_hash to cid - Update user-facing messages to use CID terminology - Update README examples with CID syntax Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
18
README.md
18
README.md
@@ -75,8 +75,8 @@ export ARTDAG_L2=https://artdag.rose-ash.com
|
||||
# Using asset name
|
||||
./artdag.py run dog cat
|
||||
|
||||
# Using content hash
|
||||
./artdag.py run dog 33268b6e167deaf018cc538de12dbe562612b33e89a749391cef855b320a269b
|
||||
# Using CID
|
||||
./artdag.py run dog Qm33268b6e167deaf018cc538de12dbe562612b33e
|
||||
|
||||
# Wait for completion
|
||||
./artdag.py run dog cat --wait
|
||||
@@ -112,13 +112,13 @@ export ARTDAG_L2=https://artdag.rose-ash.com
|
||||
### View/Download Cached Content
|
||||
```bash
|
||||
# Show info
|
||||
./artdag.py view <content-hash>
|
||||
./artdag.py view <cid>
|
||||
|
||||
# Download to file
|
||||
./artdag.py view <content-hash> -o output.mkv
|
||||
./artdag.py view <cid> -o output.mkv
|
||||
|
||||
# Pipe to mpv (use -o - for stdout)
|
||||
./artdag.py view <content-hash> -o - | mpv -
|
||||
./artdag.py view <cid> -o - | mpv -
|
||||
```
|
||||
|
||||
### Import Local File to Cache
|
||||
@@ -128,10 +128,10 @@ export ARTDAG_L2=https://artdag.rose-ash.com
|
||||
|
||||
### Delete Cached Content
|
||||
```bash
|
||||
./artdag.py delete-cache <content-hash>
|
||||
./artdag.py delete-cache <cid>
|
||||
|
||||
# Skip confirmation
|
||||
./artdag.py delete-cache <content-hash> -f
|
||||
./artdag.py delete-cache <cid> -f
|
||||
```
|
||||
|
||||
Note: Items that are inputs/outputs of runs, or published to L2, cannot be deleted.
|
||||
@@ -151,7 +151,7 @@ Configs are reusable DAG definitions with fixed and variable inputs.
|
||||
./artdag.py config <config-id>
|
||||
|
||||
# Run a config with variable inputs
|
||||
./artdag.py run-config <config-id> -i node_id:content_hash --wait
|
||||
./artdag.py run-config <config-id> -i node_id:cid --wait
|
||||
|
||||
# Delete a config
|
||||
./artdag.py delete-config <config-id>
|
||||
@@ -173,5 +173,5 @@ Configs are reusable DAG definitions with fixed and variable inputs.
|
||||
./artdag.py runs
|
||||
|
||||
# Download the output
|
||||
./artdag.py view <output-hash> -o result.mkv
|
||||
./artdag.py view <output-cid> -o result.mkv
|
||||
```
|
||||
|
||||
106
artdag.py
106
artdag.py
@@ -308,7 +308,7 @@ def run(recipe, input_hash, name, wait):
|
||||
|
||||
if status["status"] == "completed":
|
||||
click.echo(f"Completed!")
|
||||
click.echo(f"Output: {status['output_hash']}")
|
||||
click.echo(f"Output: {status['output_cid']}")
|
||||
else:
|
||||
click.echo(f"Failed: {status.get('error', 'Unknown error')}")
|
||||
|
||||
@@ -327,7 +327,7 @@ def list_runs(limit):
|
||||
click.echo("-" * 80)
|
||||
|
||||
for run in runs[:limit]:
|
||||
output = run.get("output_hash", "")[:16] + "..." if run.get("output_hash") else "-"
|
||||
output = run.get("output_cid", "")[:16] + "..." if run.get("output_cid") else "-"
|
||||
click.echo(f"{run['run_id']} {run['status']:<10} {run['recipe']:<10} {output}")
|
||||
|
||||
|
||||
@@ -353,8 +353,8 @@ def status(run_id):
|
||||
if run.get("completed_at"):
|
||||
click.echo(f"Completed: {run['completed_at']}")
|
||||
|
||||
if run.get("output_hash"):
|
||||
click.echo(f"Output Hash: {run['output_hash']}")
|
||||
if run.get("output_cid"):
|
||||
click.echo(f"Output Hash: {run['output_cid']}")
|
||||
|
||||
if run.get("error"):
|
||||
click.echo(f"Error: {run['error']}")
|
||||
@@ -411,12 +411,12 @@ def delete_run(run_id, force):
|
||||
|
||||
|
||||
@cli.command("delete-cache")
|
||||
@click.argument("content_hash")
|
||||
@click.argument("cid")
|
||||
@click.option("--force", "-f", is_flag=True, help="Skip confirmation")
|
||||
def delete_cache(content_hash, force):
|
||||
def delete_cache(cid, force):
|
||||
"""Delete a cached item. Requires login.
|
||||
|
||||
CONTENT_HASH: The content hash to delete
|
||||
CID: The content identifier (IPFS CID) to delete
|
||||
"""
|
||||
token_data = load_token()
|
||||
if not token_data.get("access_token"):
|
||||
@@ -424,14 +424,14 @@ def delete_cache(content_hash, force):
|
||||
sys.exit(1)
|
||||
|
||||
if not force:
|
||||
click.echo(f"Content hash: {content_hash}")
|
||||
click.echo(f"CID: {cid}")
|
||||
if not click.confirm("Delete this cached item?"):
|
||||
click.echo("Cancelled.")
|
||||
return
|
||||
|
||||
try:
|
||||
headers = {"Authorization": f"Bearer {token_data['access_token']}"}
|
||||
resp = requests.delete(f"{get_server()}/cache/{content_hash}", headers=headers)
|
||||
resp = requests.delete(f"{get_server()}/cache/{cid}", headers=headers)
|
||||
if resp.status_code == 400:
|
||||
click.echo(f"Cannot delete: {resp.json().get('detail', 'Unknown error')}", err=True)
|
||||
sys.exit(1)
|
||||
@@ -439,14 +439,14 @@ def delete_cache(content_hash, force):
|
||||
click.echo("Access denied", err=True)
|
||||
sys.exit(1)
|
||||
if resp.status_code == 404:
|
||||
click.echo(f"Content not found: {content_hash}", err=True)
|
||||
click.echo(f"Content not found: {cid}", err=True)
|
||||
sys.exit(1)
|
||||
resp.raise_for_status()
|
||||
except requests.RequestException as e:
|
||||
click.echo(f"Failed to delete cache item: {e}", err=True)
|
||||
sys.exit(1)
|
||||
|
||||
click.echo(f"Deleted: {content_hash}")
|
||||
click.echo(f"Deleted: {cid}")
|
||||
|
||||
|
||||
@cli.command()
|
||||
@@ -465,14 +465,14 @@ def cache(limit):
|
||||
|
||||
|
||||
@cli.command()
|
||||
@click.argument("content_hash")
|
||||
@click.argument("cid")
|
||||
@click.option("--output", "-o", type=click.Path(), help="Save to file (use - for stdout)")
|
||||
def view(content_hash, output):
|
||||
def view(cid, output):
|
||||
"""View or download cached content.
|
||||
|
||||
Use -o - to pipe to stdout, e.g.: artdag view <hash> -o - | mpv -
|
||||
Use -o - to pipe to stdout, e.g.: artdag view <cid> -o - | mpv -
|
||||
"""
|
||||
url = f"{get_server()}/cache/{content_hash}"
|
||||
url = f"{get_server()}/cache/{cid}"
|
||||
|
||||
try:
|
||||
if output == "-":
|
||||
@@ -495,14 +495,14 @@ def view(content_hash, output):
|
||||
resp.raise_for_status()
|
||||
size = resp.headers.get("content-length", "unknown")
|
||||
content_type = resp.headers.get("content-type", "unknown")
|
||||
click.echo(f"Hash: {content_hash}")
|
||||
click.echo(f"CID: {cid}")
|
||||
click.echo(f"Size: {size} bytes")
|
||||
click.echo(f"Type: {content_type}")
|
||||
click.echo(f"URL: {url}")
|
||||
resp.close()
|
||||
except requests.HTTPError as e:
|
||||
if e.response.status_code == 404:
|
||||
click.echo(f"Not found: {content_hash}", err=True)
|
||||
click.echo(f"Not found: {cid}", err=True)
|
||||
else:
|
||||
raise
|
||||
|
||||
@@ -513,7 +513,7 @@ def import_file(filepath):
|
||||
"""Import a local file to cache (local server only)."""
|
||||
path = str(Path(filepath).resolve())
|
||||
result = api_post("/cache/import", params={"path": path})
|
||||
click.echo(f"Imported: {result['content_hash']}")
|
||||
click.echo(f"Imported: {result['cid']}")
|
||||
|
||||
|
||||
@cli.command()
|
||||
@@ -588,14 +588,14 @@ def publish(run_id, output_name):
|
||||
result = resp.json()
|
||||
click.echo(f"Published to L2!")
|
||||
click.echo(f"Asset: {result['asset']['name']}")
|
||||
click.echo(f"Hash: {result['asset']['content_hash']}")
|
||||
click.echo(f"CID: {result['asset']['cid']}")
|
||||
click.echo(f"Activity: {result['activity']['activity_id']}")
|
||||
|
||||
|
||||
# ============ Metadata Commands ============
|
||||
|
||||
@cli.command()
|
||||
@click.argument("content_hash")
|
||||
@click.argument("cid")
|
||||
@click.option("--origin", type=click.Choice(["self", "external"]), help="Set origin type")
|
||||
@click.option("--origin-url", help="Set external origin URL")
|
||||
@click.option("--origin-note", help="Note about the origin")
|
||||
@@ -607,7 +607,7 @@ def publish(run_id, output_name):
|
||||
@click.option("--publish", "publish_name", help="Publish to L2 with given asset name")
|
||||
@click.option("--publish-type", default="image", help="Asset type for publishing (image, video)")
|
||||
@click.option("--republish", is_flag=True, help="Re-sync with L2 after metadata changes")
|
||||
def meta(content_hash, origin, origin_url, origin_note, description, tags, folder, add_collection, remove_collection, publish_name, publish_type, republish):
|
||||
def meta(cid, origin, origin_url, origin_note, description, tags, folder, add_collection, remove_collection, publish_name, publish_type, republish):
|
||||
"""View or update metadata for a cached item.
|
||||
|
||||
With no options, displays current metadata.
|
||||
@@ -627,7 +627,7 @@ def meta(content_hash, origin, origin_url, origin_note, description, tags, folde
|
||||
if publish_name:
|
||||
try:
|
||||
resp = requests.post(
|
||||
f"{get_server()}/cache/{content_hash}/publish",
|
||||
f"{get_server()}/cache/{cid}/publish",
|
||||
json={"asset_name": publish_name, "asset_type": publish_type},
|
||||
headers=headers
|
||||
)
|
||||
@@ -635,7 +635,7 @@ def meta(content_hash, origin, origin_url, origin_note, description, tags, folde
|
||||
click.echo(f"Error: {resp.json().get('detail', 'Bad request')}", err=True)
|
||||
sys.exit(1)
|
||||
if resp.status_code == 404:
|
||||
click.echo(f"Content not found: {content_hash}", err=True)
|
||||
click.echo(f"Content not found: {cid}", err=True)
|
||||
sys.exit(1)
|
||||
resp.raise_for_status()
|
||||
result = resp.json()
|
||||
@@ -651,14 +651,14 @@ def meta(content_hash, origin, origin_url, origin_note, description, tags, folde
|
||||
if republish:
|
||||
try:
|
||||
resp = requests.patch(
|
||||
f"{get_server()}/cache/{content_hash}/republish",
|
||||
f"{get_server()}/cache/{cid}/republish",
|
||||
headers=headers
|
||||
)
|
||||
if resp.status_code == 400:
|
||||
click.echo(f"Error: {resp.json().get('detail', 'Bad request')}", err=True)
|
||||
sys.exit(1)
|
||||
if resp.status_code == 404:
|
||||
click.echo(f"Content not found: {content_hash}", err=True)
|
||||
click.echo(f"Content not found: {cid}", err=True)
|
||||
sys.exit(1)
|
||||
resp.raise_for_status()
|
||||
result = resp.json()
|
||||
@@ -675,9 +675,9 @@ def meta(content_hash, origin, origin_url, origin_note, description, tags, folde
|
||||
if not has_updates:
|
||||
# GET metadata
|
||||
try:
|
||||
resp = requests.get(f"{get_server()}/cache/{content_hash}/meta", headers=headers)
|
||||
resp = requests.get(f"{get_server()}/cache/{cid}/meta", headers=headers)
|
||||
if resp.status_code == 404:
|
||||
click.echo(f"Content not found: {content_hash}", err=True)
|
||||
click.echo(f"Content not found: {cid}", err=True)
|
||||
sys.exit(1)
|
||||
if resp.status_code == 403:
|
||||
click.echo("Access denied", err=True)
|
||||
@@ -688,7 +688,7 @@ def meta(content_hash, origin, origin_url, origin_note, description, tags, folde
|
||||
click.echo(f"Failed to get metadata: {e}", err=True)
|
||||
sys.exit(1)
|
||||
|
||||
click.echo(f"Content Hash: {content_hash}")
|
||||
click.echo(f"Content Hash: {cid}")
|
||||
click.echo(f"Uploader: {meta.get('uploader', 'unknown')}")
|
||||
click.echo(f"Uploaded: {meta.get('uploaded_at', 'unknown')}")
|
||||
if meta.get("origin"):
|
||||
@@ -715,7 +715,7 @@ def meta(content_hash, origin, origin_url, origin_note, description, tags, folde
|
||||
if origin or origin_url or origin_note:
|
||||
# Get current origin first
|
||||
try:
|
||||
resp = requests.get(f"{get_server()}/cache/{content_hash}/meta", headers=headers)
|
||||
resp = requests.get(f"{get_server()}/cache/{cid}/meta", headers=headers)
|
||||
resp.raise_for_status()
|
||||
current = resp.json()
|
||||
current_origin = current.get("origin", {})
|
||||
@@ -740,7 +740,7 @@ def meta(content_hash, origin, origin_url, origin_note, description, tags, folde
|
||||
if add_collection or remove_collection:
|
||||
# Get current collections
|
||||
try:
|
||||
resp = requests.get(f"{get_server()}/cache/{content_hash}/meta", headers=headers)
|
||||
resp = requests.get(f"{get_server()}/cache/{cid}/meta", headers=headers)
|
||||
resp.raise_for_status()
|
||||
current = resp.json()
|
||||
collections = set(current.get("collections", []))
|
||||
@@ -756,12 +756,12 @@ def meta(content_hash, origin, origin_url, origin_note, description, tags, folde
|
||||
# PATCH metadata
|
||||
try:
|
||||
resp = requests.patch(
|
||||
f"{get_server()}/cache/{content_hash}/meta",
|
||||
f"{get_server()}/cache/{cid}/meta",
|
||||
json=update,
|
||||
headers=headers
|
||||
)
|
||||
if resp.status_code == 404:
|
||||
click.echo(f"Content not found: {content_hash}", err=True)
|
||||
click.echo(f"Content not found: {cid}", err=True)
|
||||
sys.exit(1)
|
||||
if resp.status_code == 400:
|
||||
click.echo(f"Error: {resp.json().get('detail', 'Bad request')}", err=True)
|
||||
@@ -1088,7 +1088,7 @@ def list_effects(limit):
|
||||
for effect in effects:
|
||||
meta = effect.get("meta", {})
|
||||
click.echo(f" {meta.get('name', 'unknown')} v{meta.get('version', '?')}")
|
||||
click.echo(f" Hash: {effect['content_hash'][:32]}...")
|
||||
click.echo(f" Hash: {effect['cid'][:32]}...")
|
||||
click.echo(f" Temporal: {meta.get('temporal', False)}")
|
||||
if meta.get('params'):
|
||||
click.echo(f" Params: {', '.join(p['name'] for p in meta['params'])}")
|
||||
@@ -1155,12 +1155,12 @@ def show_recipe(recipe_id):
|
||||
if recipe.get("fixed_inputs"):
|
||||
click.echo("\nFixed Inputs:")
|
||||
for inp in recipe["fixed_inputs"]:
|
||||
click.echo(f" - {inp['asset']}: {inp['content_hash'][:16]}...")
|
||||
click.echo(f" - {inp['asset']}: {inp['cid'][:16]}...")
|
||||
|
||||
|
||||
@cli.command("run-recipe")
|
||||
@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:cid")
|
||||
@click.option("--wait", "-w", is_flag=True, help="Wait for completion")
|
||||
def run_recipe(recipe_id, inputs, wait):
|
||||
"""Run a recipe with variable inputs. Requires login.
|
||||
@@ -1178,10 +1178,10 @@ def run_recipe(recipe_id, inputs, wait):
|
||||
input_dict = {}
|
||||
for inp in inputs:
|
||||
if ":" not in inp:
|
||||
click.echo(f"Invalid input format: {inp} (expected node_id:content_hash)", err=True)
|
||||
click.echo(f"Invalid input format: {inp} (expected node_id:cid)", err=True)
|
||||
sys.exit(1)
|
||||
node_id, content_hash = inp.split(":", 1)
|
||||
input_dict[node_id] = content_hash
|
||||
node_id, cid = inp.split(":", 1)
|
||||
input_dict[node_id] = cid
|
||||
|
||||
# Run
|
||||
try:
|
||||
@@ -1225,7 +1225,7 @@ def run_recipe(recipe_id, inputs, wait):
|
||||
continue
|
||||
|
||||
if run["status"] == "completed":
|
||||
click.echo(f"Completed! Output: {run.get('output_hash', 'N/A')}")
|
||||
click.echo(f"Completed! Output: {run.get('output_cid', 'N/A')}")
|
||||
break
|
||||
elif run["status"] == "failed":
|
||||
click.echo(f"Failed: {run.get('error', 'Unknown error')}", err=True)
|
||||
@@ -1272,7 +1272,7 @@ def delete_recipe(recipe_id, force):
|
||||
|
||||
@cli.command("plan")
|
||||
@click.argument("recipe_file", type=click.Path(exists=True))
|
||||
@click.option("--input", "-i", "inputs", multiple=True, help="Input as name:content_hash")
|
||||
@click.option("--input", "-i", "inputs", multiple=True, help="Input as name:cid")
|
||||
@click.option("--features", "-f", multiple=True, help="Features to extract (default: beats, energy)")
|
||||
@click.option("--output", "-o", type=click.Path(), help="Save plan JSON to file")
|
||||
def generate_plan(recipe_file, inputs, features, output):
|
||||
@@ -1297,10 +1297,10 @@ def generate_plan(recipe_file, inputs, features, output):
|
||||
input_hashes = {}
|
||||
for inp in inputs:
|
||||
if ":" not in inp:
|
||||
click.echo(f"Invalid input format: {inp} (expected name:content_hash)", err=True)
|
||||
click.echo(f"Invalid input format: {inp} (expected name:cid)", err=True)
|
||||
sys.exit(1)
|
||||
name, content_hash = inp.split(":", 1)
|
||||
input_hashes[name] = content_hash
|
||||
name, cid = inp.split(":", 1)
|
||||
input_hashes[name] = cid
|
||||
|
||||
# Build request
|
||||
request_data = {
|
||||
@@ -1401,7 +1401,7 @@ def execute_plan(plan_file, wait):
|
||||
|
||||
@cli.command("run-v2")
|
||||
@click.argument("recipe_file", type=click.Path(exists=True))
|
||||
@click.option("--input", "-i", "inputs", multiple=True, help="Input as name:content_hash")
|
||||
@click.option("--input", "-i", "inputs", multiple=True, help="Input as name:cid")
|
||||
@click.option("--features", "-f", multiple=True, help="Features to extract (default: beats, energy)")
|
||||
@click.option("--wait", "-w", is_flag=True, help="Wait for completion")
|
||||
def run_recipe_v2(recipe_file, inputs, features, wait):
|
||||
@@ -1433,10 +1433,10 @@ def run_recipe_v2(recipe_file, inputs, features, wait):
|
||||
input_hashes = {}
|
||||
for inp in inputs:
|
||||
if ":" not in inp:
|
||||
click.echo(f"Invalid input format: {inp} (expected name:content_hash)", err=True)
|
||||
click.echo(f"Invalid input format: {inp} (expected name:cid)", err=True)
|
||||
sys.exit(1)
|
||||
name, content_hash = inp.split(":", 1)
|
||||
input_hashes[name] = content_hash
|
||||
name, cid = inp.split(":", 1)
|
||||
input_hashes[name] = cid
|
||||
|
||||
# Build request
|
||||
request_data = {
|
||||
@@ -1473,8 +1473,8 @@ def run_recipe_v2(recipe_file, inputs, features, wait):
|
||||
click.echo(f"Run ID: {run_id}")
|
||||
click.echo(f"Status: {result['status']}")
|
||||
|
||||
if result.get("output_hash"):
|
||||
click.echo(f"Output: {result['output_hash']}")
|
||||
if result.get("output_cid"):
|
||||
click.echo(f"Output: {result['output_cid']}")
|
||||
if result.get("output_ipfs_cid"):
|
||||
click.echo(f"IPFS CID: {result['output_ipfs_cid']}")
|
||||
return
|
||||
@@ -1505,8 +1505,8 @@ def _wait_for_v2_run(token_data: dict, run_id: str):
|
||||
|
||||
if status == "completed":
|
||||
click.echo(f"\nCompleted!")
|
||||
if run.get("output_hash"):
|
||||
click.echo(f"Output: {run['output_hash']}")
|
||||
if run.get("output_cid"):
|
||||
click.echo(f"Output: {run['output_cid']}")
|
||||
if run.get("output_ipfs_cid"):
|
||||
click.echo(f"IPFS CID: {run['output_ipfs_cid']}")
|
||||
if run.get("cached"):
|
||||
@@ -1555,8 +1555,8 @@ def run_status_v2(run_id):
|
||||
click.echo(f"Recipe: {run['recipe']}")
|
||||
if run.get("plan_id"):
|
||||
click.echo(f"Plan ID: {run['plan_id'][:16]}...")
|
||||
if run.get("output_hash"):
|
||||
click.echo(f"Output: {run['output_hash']}")
|
||||
if run.get("output_cid"):
|
||||
click.echo(f"Output: {run['output_cid']}")
|
||||
if run.get("output_ipfs_cid"):
|
||||
click.echo(f"IPFS CID: {run['output_ipfs_cid']}")
|
||||
if run.get("cached") is not None:
|
||||
|
||||
Reference in New Issue
Block a user