@assethub/cli 0.1.25 → 0.1.28

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -22,7 +22,7 @@ type CommandContext = {
22
22
  */
23
23
  args: string[];
24
24
  };
25
- export declare const usage = "AssetHub CLI\n\nCLI and MCP are available to all AssetHub users. Workspace permissions and feature availability apply.\n\nUsage:\n assethub --version\n assethub doctor [--mcp] [--profile <name>] [--timeout-ms <n>]\n assethub mcp tools [tool-name] [--account] [--profile <name>] [--timeout-ms <n>]\n assethub mcp config --client cursor|codex [--account] [--base-url <url>]\n assethub auth login --api-key <key> [--base-url <url>] [--profile <name>]\n assethub auth login --api-key-stdin [--base-url <url>] [--profile <name>]\n assethub auth login --access-token-stdin [--base-url <url>] [--profile <name>]\n assethub auth status [--profile <name>]\n assethub auth logout [--profile <name>]\n assethub workspace list [--query <text>] [--limit <1-100>] [--cursor <cursor>]\n assethub workspace get\n assethub workspace create --name <name> [--operation-id <uuid>]\n assethub workspace use <workspace-id>\n assethub workspace members [--workspace <id>]\n assethub workspace invite --email <email> [--role user|admin] [--resend] [--workspace <id>]\n assethub workspace set-role <user-id> --role user|admin [--workspace <id>]\n assethub workspace remove-member <user-id> [--workspace <id>]\n assethub workspace prepare|sync|analyze|verify --internal --manifest <json> --state <json>\n assethub workspace self-check --internal\n assethub workspace context put --internal --org <uuid> --actor <uuid> --canvas <id> --file <json> [--if-version <n>] [--order <uuid>]\n assethub workspace context get --internal --org <uuid> --actor <uuid> --canvas <id> [--out <json>] [--order <uuid>]\n assethub project ingest <source-dir> --out-dir <directory> [--exclude-dir <relative-path>...]\n assethub language text|vision --input-json @<json> --operation-id <uuid> [--out <json>]\n assethub canvas download --canvas <id> --out-dir <directory> [--mesh <mesh_asset_id>]\n assethub canvas nodes --canvas <id>\n assethub canvas import --canvas <id> --file <image> [--name <name>]\n assethub canvas context get --canvas <id> [--out <json>]\n assethub canvas context put --canvas <id> --file <json> [--if-version <n>]\n assethub canvas layout --canvas <id> --input-json @<json>\n assethub canvas compare --canvas <id> --source-id <asset-id> --asset-id <asset-id> --out <html>\n assethub moodboard create --input-json @<json> [--operation-id <uuid>]\n assethub moodboard list|get|update|archive [<board-id>] [--input-json @<json>]\n assethub moodboard analyze <board-id> [--revision <uuid>] [--wait]\n assethub image generate --canvas <id> --context <id> [--context-version <n>] [--context-source <key>] [--moodboard-revision <uuid>] --prompt <text> --wait\n assethub models list [--domain <domain>] [--ids-only] [--limit <n>]\n assethub models get <model-id>\n assethub files import <url> --media-type image|mesh\n assethub files upload <file> --media-type image|mesh\n assethub source create (--file <path> | --source-url <url> | --source-id <id> | --stdin | --stdin-base64 | --stdin-data-uri | --stdin-json | --source-json <json|@file|@-> | --data-uri <uri> | --clipboard) --media-type image|mesh [--file-name <name>] [--content-type <type>]\n assethub capabilities\n assethub api search [query]\n assethub api describe \"<METHOD /path>\"\n assethub api call \"<METHOD /path>\" [--path-json <json|@file>] [--query-json <json|@file>] [--input-json <json|@file|@->] [--operation-id <uuid>]\n assethub skills list [--cursor <cursor>]\n assethub skills get <skill-id> [--revision <n>]\n assethub skills learn --input-json <json|@file|@-> --operation-id <uuid>\n assethub skills update <skill-id> --input-json <json|@file|@->\n assethub skills controls <skill-id> --revision <n> --grant-revision <n> --mode automatic|manual|off [--share]\n assethub skills prepare --input-json <json|@file|@->\n assethub skills proposal <proposal-id>\n assethub skills accept <proposal-id> --input-json <json|@file|@->\n assethub composer models\n assethub composer refine --list-modes\n assethub composer refine --from-run <run-id> --instruction <text> [--mode standard|thorough|placement|workshop|blender|codex] [--max-rounds <n>] [--transforms-json <json|@file>] [--wait] [--download --out-dir <dir>]\n assethub composer refine --input-json <json|@file> [--canvas <id>] [--operation-id <uuid>] [--wait] [--download --out-dir <dir>]\n assethub composer run --part <mesh-asset-id> [--part <mesh-asset-id>...] --reference <image-asset-id> [--model <id>] [--mode quick|quality] [--transforms-json <json|@file>] [--canvas <id>] [--wait]\n assethub composer run --input-json <json|@file> [--canvas <id>] [--operation-id <uuid>] [--wait] [--download --out-dir <dir>]\n assethub composer run --from-run <run-id> [--transforms-json <json|@file>] [--mode quick|quality] [--wait]\n assethub composer run --node <shape:id> --canvas <id> [--model <id>] [--mode quick|quality] [--operation-id <uuid>] [--wait]\n assethub canvas create [--name <name>] [--operation-id <uuid>]\n assethub canvas list [--cursor <cursor>] [--limit <n>]\n assethub canvas get|use|open [<id>]\n assethub runs list [--canvas <id>] [--cursor <cursor>] [--limit <n>]\n assethub runs get|watch <run-id> [--timeout-ms <n>]\n assethub runs resume <operation-id> [--wait]\n assethub graph list [--cursor <cursor>] [--limit <n>]\n assethub graph show|export [--canvas <id> | --graph <id>] [--source generated|upload] [--artifact <node-id>] [--out <path>] [--allow-truncated]\n assethub graph lineage --artifact <node-id> [--canvas <id> | --graph <id>] [--source generated|upload] [--direction ancestors|descendants|both] [--depth <n>] [--out <path>]\n assethub evaluate list\n assethub evaluations submit --artifact <asset-id> --report <json|file|@file|@-> [--agent <name>] [--canvas <id>] [--reference <asset-id>...] [--run <run-id>] [--operation-id <uuid>] [--require-pass]\n assethub evaluations list [--canvas <id>] [--artifact <asset-id>]\n assethub evaluations get <evaluation-id>\n assethub image generate --input-json <json|@file|@-> [--canvas <id>] [--operation-id <uuid>] [--agent <name>] [--derived-from-run <run-id>] [--from-node <graphId/nodeId> --graph-revision <rev>] [--wait]\n assethub mesh generate --input-json <json|@file|@-> [--canvas <id>] [--operation-id <uuid>] [--agent <name>] [--derived-from-run <run-id>] [--from-node <graphId/nodeId> --graph-revision <rev>] [--wait]\n assethub mesh generate --node <shape:id> --canvas <id> [--model-id <id>] [--params-json <json|@file>] [--operation-id <uuid>] [--wait]\n assethub mesh list [--query <text>] [--cursor <cursor>] [--limit <n>]\n assethub mesh get <mesh-asset-id>\n assethub mesh download <mesh-asset-id> --out-dir <directory>\n assethub image generate --prompt <text> [--file <path> | --source-url <url> | --stdin | --stdin-base64 | --stdin-data-uri | --stdin-json | --source-json <json|@file|@-> | --data-uri <uri> | --clipboard] [--file-name <name>] [--content-type <type>] [--model-id <id>] [--batch-size <n>] [--wait] [--download --out-dir <dir>] [--canvas <id>] [--operation-id <uuid>] [--api-version v2]\n assethub image generate --prompt <text> --source-resource-id <id> --api-version v2 [--model-id <id>] [--batch-size <n>] [--wait]\n assethub mesh generate (--file <path> | --source-url <url> | --source-resource-id <id> | --file-ref-json <json> | --stdin | --stdin-base64 | --stdin-data-uri | --stdin-json | --source-json <json|@file|@-> | --data-uri <uri>) [--file-name <name>] [--content-type <type>] [--model-id <id>] [--name <name>] [--wait] [--download --out-dir <dir>]\n assethub mesh retopo (--source-resource-id <id> | --source-url <url> | --file-ref-json <json> | --stdin | --stdin-base64 | --stdin-data-uri | --stdin-json | --source-json <json|@file|@-> | --data-uri <uri>) --model-id <id> [--file-name <name>] [--content-type <type>] [--wait] [--download --out-dir <dir>]\n assethub rig check (--file <path> | --source-url <url> | --source-resource-id <id> | --file-ref-json <json> | --stdin | --stdin-base64 | --stdin-data-uri | --stdin-json | --source-json <json|@file|@-> | --data-uri <uri>) [--name <name>] [--wait] [--download --out-dir <dir>]\n assethub rig create (--file <path> | --source-url <url> | --source-resource-id <id> | --file-ref-json <json> | --stdin | --stdin-base64 | --stdin-data-uri | --stdin-json | --source-json <json|@file|@-> | --data-uri <uri>) [--model v1.0-20240301|v2.5-20260210] [--rig-type biped|quadruped|hexapod|octopod|avian|serpentine|aquatic] [--spec tripo|mixamo] [--out-format glb|fbx] [--name <name>] [--wait] [--download --out-dir <dir>]\n assethub animate presets [--model v1.0-20240301|v2.5-20260210] [--rig-type <type>]\n assethub animate retarget --resource-id <id> --animation <preset-id> [--animation <preset-id>... up to 5 total] [--out-format glb|fbx] [--bake-animation true|false] [--export-with-geometry true|false] [--animate-in-place true|false] [--name <name>] [--wait] [--download --out-dir <dir>]\n assethub jobs get <job-id> [--download --out-dir <dir>]\n assethub jobs watch <job-id> [--interval-ms <ms>] [--timeout-ms <ms>] [--download --out-dir <dir>]\n assethub production analyze (--file <path> | --source-url <url> | --source-id <id> | --image-url <url> | --file-ref-json <json> | --stdin | --stdin-base64 | --stdin-data-uri | --stdin-json | --source-json <json|@file|@-> | --data-uri <uri> | --clipboard) [--file-name <name>] [--content-type <type>] [--part-extractor <name>] [--name <name>] [--skill-mode auto|manual|off] [--skill-id <id>...] [--context <canvas-id> --context-version <n>] [--wait] [--download --out-dir <dir>]\n assethub production agents\n assethub production automation --input-json <json|@file|@-> [--canvas <id>] [--operation-id <uuid>] [--wait]\n assethub production status <order-id> [--wait] [--download --out-dir <dir>]\n assethub production execute --order-id <id> --mission-id <id> --task-id <id> [--task-id <id>...] [--part-extractor <name>] [--part-extraction-mode fast|high_quality] [--wait] [--download --out-dir <dir>]\n assethub production run --order-id <id> --mission-id <id> [--run-mode full_auto|approval] [--task-id <id>...] [--part-extractor <name>] [--part-extraction-mode fast|high_quality] [--allowed-model-id <id>...] [--max-iterations <n>] [--max-cost-credits <n>] [--wait] [--download --out-dir <dir>]\n assethub production watch <order-id> [--interval-ms <ms>] [--timeout-ms <ms>] [--download --out-dir <dir>]\n assethub production intervene <order-id> (--exclude <target-id> | --include <target-id> | --add-part <name> | --rename <target-id>=<name> | --reject <target-id>[=<reason>] | --regenerate <target-id>=<mode> | --set-param <key>=<value> | --ops-json <json|@file|@->)... [--idempotency-key <key>]\n assethub production interventions <order-id>\n assethub runs upload <path> [--graph-id <id>] [--stream-id <id>] [--rev <n>] [--description <text>] [--tag <tag>...] [--skip-register] [--dry-run]\n assethub parts split (--file <path> | --source-url <url> | --source-id <id> | --image-url <url> | --file-ref-json <json> | --stdin | --stdin-base64 | --stdin-data-uri | --stdin-json | --source-json <json|@file|@-> | --data-uri <uri> | --clipboard | --order-id <id>) [--file-name <name>] [--content-type <type>] [--part-extractor <name>] [--skill-mode auto|manual|off] [--skill-id <id>...] [--wait] [--task-id <id>...] [--mission-id <id>] [--all-ready] [--download --out-dir <dir>]\n assethub parts compare (--file <path> | --source-url <url> | --source-id <id> | --image-url <url> | --file-ref-json <json> | --stdin | --stdin-base64 | --stdin-data-uri | --stdin-json | --source-json <json|@file|@-> | --data-uri <uri> | --clipboard) [--file-name <name>] [--content-type <type>] [--preprocess-prompt <text>] [--preprocess-model-id <id>] [--fail-on-preprocess-error] [--part-extractor <name>] [--wait] [--task-id <id>...] [--mission-id <id>] [--all-ready] [--download --out-dir <dir>]\n assethub autopilot [<image>] --demo [--yolo] [--json] [--max-regen <n>] [--stall-rounds <n>] [--tie-epsilon <x>] [--multiview 2-view|4-view|6-view] [--ab-mode serial|cross] [--credit-budget <n>]\n\nGlobal options:\n --api-key <key> Overrides saved auth and ASSETHUB_API_KEY.\n --base-url <url> Override the selected API origin. Default: https://app.assethub.io.\n --profile <name> Select this saved profile ahead of environment credentials and origin.\n --workspace <id> Select workspace scope for this command without changing saved selection.\n --config <path> Auth config path. Defaults to ~/.assethub/config.json.\n --version Show installed package version.\n --help Show help.\n\nExamples:\n ASSETHUB_API_KEY=ah_live_xxx assethub models list\n assethub auth login --api-key-stdin\n assethub models list --ids-only\n assethub files upload ./input.png --media-type image\n assethub source create --file ./input.png --media-type image\n pbpaste | assethub source create --stdin-data-uri --media-type image\n assethub source create --clipboard --media-type image --file-name clipboard.png\n printf '{\"image_url\":{\"url\":\"data:image/png;base64,...\"}}' | assethub parts split --stdin-json --part-extractor \"V1.5\" --wait\n base64 -i ./input.png | assethub parts split --stdin-base64 --file-name input.png --content-type image/png --part-extractor \"V1.5\" --wait\n cat ./input.png | assethub parts split --stdin --file-name input.png --part-extractor \"V1.5\" --wait\n assethub image generate --prompt \"stylized prop concept\" --wait\n assethub mesh generate --file ./input.png --wait\n assethub animate presets --rig-type biped\n assethub rig create --source-resource-id mesh_x --rig-type biped --wait\n assethub animate retarget --resource-id rig_x --animation preset:idle --wait\n assethub production analyze --file ./input.png --part-extractor \"V1.5\" --wait\n assethub production run --order-id ord_x --mission-id ms_x --run-mode full_auto --max-cost-credits 200 --wait\n assethub production watch ord_x\n assethub production intervene ord_x --exclude 7 --rename 3=\"left wing\" --idempotency-key review-2026-07-29\n assethub production interventions ord_x\n assethub runs upload ./out/pluffy-run-2026-07-30 --dry-run\n assethub runs upload ./out/pluffy-run-2026-07-30 --tag pluffy --description \"V3 humanoid, 18 parts\"\n assethub parts split --file ./input.png --part-extractor \"V1.5\" --wait --all-ready\n assethub parts compare --file ./input.png --preprocess-prompt \"clean white background, centered product photo\" --part-extractor \"V1.5\" --wait --all-ready\n";
25
+ export declare const usage = "AssetHub CLI\n\nCLI and MCP are available to all AssetHub users. Workspace permissions and feature availability apply.\n\nUsage:\n assethub --version\n assethub doctor [--mcp] [--profile <name>] [--timeout-ms <n>]\n assethub init [--agent claude-code|codex|cursor...] [--project] [--dry-run] [--base-url <url>] [--workspace <id>] [--profile <name>]\n assethub mcp tools [tool-name] [--account] [--profile <name>] [--timeout-ms <n>]\n assethub mcp config --client cursor|codex [--account] [--base-url <url>]\n assethub auth login --api-key <key> [--base-url <url>] [--profile <name>]\n assethub auth login --api-key-stdin [--base-url <url>] [--profile <name>]\n assethub auth login --access-token-stdin [--base-url <url>] [--profile <name>]\n assethub auth status [--profile <name>]\n assethub auth logout [--profile <name>]\n assethub workspace list [--query <text>] [--limit <1-100>] [--cursor <cursor>]\n assethub workspace get\n assethub workspace create --name <name> [--operation-id <uuid>]\n assethub workspace use <workspace-id>\n assethub workspace members [--workspace <id>]\n assethub workspace invite --email <email> [--role user|admin] [--resend] [--workspace <id>]\n assethub workspace set-role <user-id> --role user|admin [--workspace <id>]\n assethub workspace remove-member <user-id> [--workspace <id>]\n assethub workspace prepare|sync|analyze|verify --internal --manifest <json> --state <json>\n assethub workspace self-check --internal\n assethub workspace context put --internal --org <uuid> --actor <uuid> --canvas <id> --file <json> [--if-version <n>] [--order <uuid>]\n assethub workspace context get --internal --org <uuid> --actor <uuid> --canvas <id> [--out <json>] [--order <uuid>]\n assethub project ingest <source-dir> --out-dir <directory> [--exclude-dir <relative-path>...]\n assethub language text|vision --input-json @<json> --operation-id <uuid> [--out <json>]\n assethub canvas download --canvas <id> --out-dir <directory> [--mesh <mesh_asset_id>]\n assethub canvas nodes --canvas <id>\n assethub canvas import --canvas <id> --file <image> [--name <name>]\n assethub canvas context get --canvas <id> [--out <json>]\n assethub canvas context put --canvas <id> --file <json> [--if-version <n>]\n assethub canvas layout --canvas <id> --input-json @<json>\n assethub canvas compare --canvas <id> --source-id <asset-id> --asset-id <asset-id> --out <html>\n assethub moodboard create --input-json @<json> [--operation-id <uuid>]\n assethub moodboard list|get|update|archive [<board-id>] [--input-json @<json>]\n assethub moodboard analyze <board-id> [--revision <uuid>] [--wait]\n assethub image generate --canvas <id> --context <id> [--context-version <n>] [--context-source <key>] [--moodboard-revision <uuid>] --prompt <text> --wait\n assethub models list [--domain <domain>] [--ids-only] [--limit <n>]\n assethub models get <model-id>\n assethub files import <url> --media-type image|mesh\n assethub files upload <file> --media-type image|mesh\n assethub source create (--file <path> | --source-url <url> | --source-id <id> | --stdin | --stdin-base64 | --stdin-data-uri | --stdin-json | --source-json <json|@file|@-> | --data-uri <uri> | --clipboard) --media-type image|mesh [--file-name <name>] [--content-type <type>]\n assethub capabilities\n assethub api search [query]\n assethub api describe \"<METHOD /path>\"\n assethub api call \"<METHOD /path>\" [--path-json <json|@file>] [--query-json <json|@file>] [--input-json <json|@file|@->] [--operation-id <uuid>]\n assethub skills list [--cursor <cursor>]\n assethub skills get <skill-id> [--revision <n>]\n assethub skills learn --input-json <json|@file|@-> --operation-id <uuid>\n assethub skills update <skill-id> --input-json <json|@file|@->\n assethub skills controls <skill-id> --revision <n> --grant-revision <n> --mode automatic|manual|off [--share]\n assethub skills prepare --input-json <json|@file|@->\n assethub skills proposal <proposal-id>\n assethub skills accept <proposal-id> --input-json <json|@file|@->\n assethub composer models\n assethub composer refine --list-modes\n assethub composer refine --from-run <run-id> --instruction <text> [--mode standard|thorough|placement|workshop|blender|codex] [--max-rounds <n>] [--transforms-json <json|@file>] [--wait] [--download --out-dir <dir>]\n assethub composer refine --input-json <json|@file> [--canvas <id>] [--operation-id <uuid>] [--wait] [--download --out-dir <dir>]\n assethub composer run --part <mesh-asset-id>[:<part-image-asset-id>] [--part <mesh-asset-id>[:<part-image-asset-id>]...] --reference <image-asset-id> [--model <id>] [--mode quick|quality] [--transforms-json <json|@file>] [--canvas <id>] [--wait]\n assethub composer run --input-json <json|@file> [--canvas <id>] [--operation-id <uuid>] [--wait] [--download --out-dir <dir>]\n assethub composer run --from-run <run-id> [--transforms-json <json|@file>] [--mode quick|quality] [--wait]\n assethub composer run --node <shape:id> --canvas <id> [--model <id>] [--mode quick|quality] [--operation-id <uuid>] [--wait]\n assethub canvas create [--name <name>] [--operation-id <uuid>]\n assethub canvas list [--cursor <cursor>] [--limit <n>]\n assethub canvas get|use|open [<id>]\n assethub runs list [--canvas <id>] [--cursor <cursor>] [--limit <n>]\n assethub runs get|watch|wait <run-id> [--interval-ms <ms>] [--timeout-ms <n>] [--summary]\n assethub runs resume <operation-id> [--wait]\n assethub graph list [--cursor <cursor>] [--limit <n>]\n assethub graph show|export [--canvas <id> | --graph <id>] [--source generated|upload] [--artifact <node-id>] [--out <path>] [--allow-truncated]\n assethub graph lineage --artifact <node-id> [--canvas <id> | --graph <id>] [--source generated|upload] [--direction ancestors|descendants|both] [--depth <n>] [--out <path>]\n assethub evaluate list\n assethub evaluations submit --artifact <asset-id> --report <json|file|@file|@-> [--agent <name>] [--canvas <id>] [--reference <asset-id>...] [--run <run-id>] [--operation-id <uuid>] [--require-pass]\n assethub evaluations list [--canvas <id>] [--artifact <asset-id>]\n assethub evaluations get <evaluation-id>\n assethub image generate --input-json <json|@file|@-> [--canvas <id>] [--operation-id <uuid>] [--agent <name>] [--derived-from-run <run-id>] [--from-node <graphId/nodeId> --graph-revision <rev>] [--wait]\n assethub mesh generate --input-json <json|@file|@-> [--canvas <id>] [--operation-id <uuid>] [--agent <name>] [--derived-from-run <run-id>] [--from-node <graphId/nodeId> --graph-revision <rev>] [--wait]\n assethub mesh generate --node <shape:id> --canvas <id> [--model-id <id>] [--params-json <json|@file>] [--operation-id <uuid>] [--wait]\n assethub mesh list [--query <text>] [--cursor <cursor>] [--limit <n>]\n assethub mesh get <mesh-asset-id>\n assethub mesh download <mesh-asset-id> --out-dir <directory>\n assethub image generate --prompt <text> [--file <path> | --source-url <url> | --stdin | --stdin-base64 | --stdin-data-uri | --stdin-json | --source-json <json|@file|@-> | --data-uri <uri> | --clipboard] [--file-name <name>] [--content-type <type>] [--model-id <id>] [--batch-size <n>] [--wait] [--download --out-dir <dir>] [--canvas <id>] [--operation-id <uuid>] [--api-version v2]\n assethub image generate --prompt <text> --source-resource-id <id> --api-version v2 [--model-id <id>] [--batch-size <n>] [--wait]\n assethub mesh generate (--file <path> | --source-url <url> | --source-resource-id <id> | --file-ref-json <json> | --stdin | --stdin-base64 | --stdin-data-uri | --stdin-json | --source-json <json|@file|@-> | --data-uri <uri>) [--file-name <name>] [--content-type <type>] [--model-id <id>] [--name <name>] [--wait] [--download --out-dir <dir>]\n assethub mesh retopo (--source-resource-id <id> | --source-url <url> | --file-ref-json <json> | --stdin | --stdin-base64 | --stdin-data-uri | --stdin-json | --source-json <json|@file|@-> | --data-uri <uri>) --model-id <id> [--file-name <name>] [--content-type <type>] [--wait] [--download --out-dir <dir>]\n assethub rig check (--file <path> | --source-url <url> | --source-resource-id <id> | --file-ref-json <json> | --stdin | --stdin-base64 | --stdin-data-uri | --stdin-json | --source-json <json|@file|@-> | --data-uri <uri>) [--name <name>] [--wait] [--download --out-dir <dir>]\n assethub rig create (--file <path> | --source-url <url> | --source-resource-id <id> | --file-ref-json <json> | --stdin | --stdin-base64 | --stdin-data-uri | --stdin-json | --source-json <json|@file|@-> | --data-uri <uri>) [--model v1.0-20240301|v2.5-20260210] [--rig-type biped|quadruped|hexapod|octopod|avian|serpentine|aquatic] [--spec tripo|mixamo] [--out-format glb|fbx] [--name <name>] [--wait] [--download --out-dir <dir>]\n assethub animate presets [--model v1.0-20240301|v2.5-20260210] [--rig-type <type>]\n assethub animate retarget --resource-id <id> --animation <preset-id> [--animation <preset-id>... up to 5 total] [--out-format glb|fbx] [--bake-animation true|false] [--export-with-geometry true|false] [--animate-in-place true|false] [--name <name>] [--wait] [--download --out-dir <dir>]\n assethub jobs get <job-id> [--download --out-dir <dir>]\n assethub jobs watch <job-id> [--interval-ms <ms>] [--timeout-ms <ms>] [--download --out-dir <dir>]\n assethub production analyze (--file <path> | --source-url <url> | --source-id <id> | --image-url <url> | --file-ref-json <json> | --stdin | --stdin-base64 | --stdin-data-uri | --stdin-json | --source-json <json|@file|@-> | --data-uri <uri> | --clipboard) [--file-name <name>] [--content-type <type>] [--part-extractor <name>] [--name <name>] [--skill-mode auto|manual|off] [--skill-id <id>...] [--context <canvas-id> --context-version <n>] [--wait] [--download --out-dir <dir>]\n assethub production agents\n assethub production automation --input-json <json|@file|@-> [--canvas <id>] [--operation-id <uuid>] [--wait]\n assethub production status <order-id> [--wait] [--download --out-dir <dir>]\n assethub production execute --order-id <id> --mission-id <id> --task-id <id> [--task-id <id>...] [--part-extractor <name>] [--part-extraction-mode fast|high_quality] [--wait] [--download --out-dir <dir>]\n assethub production run --order-id <id> --mission-id <id> [--run-mode full_auto|approval] [--task-id <id>...] [--part-extractor <name>] [--part-extraction-mode fast|high_quality] [--allowed-model-id <id>...] [--max-iterations <n>] [--max-cost-credits <n>] [--wait] [--download --out-dir <dir>]\n assethub production run --image <file|asset-id> [--canvas <id>] [--part-extractor <name>] [--compose v6|none] [--mesh-model <id>] [--max-parts <n>] [--max-cost <credits>] [--estimate] [--wait] [--download --out-dir <dir>] [--json]\n assethub production watch <order-id> [--interval-ms <ms>] [--timeout-ms <ms>] [--download --out-dir <dir>]\n assethub production intervene <order-id> (--exclude <target-id> | --include <target-id> | --add-part <name> | --rename <target-id>=<name> | --reject <target-id>[=<reason>] | --regenerate <target-id>=<mode> | --set-param <key>=<value> | --ops-json <json|@file|@->)... [--idempotency-key <key>]\n assethub production interventions <order-id>\n assethub runs upload <path> [--graph-id <id>] [--stream-id <id>] [--rev <n>] [--description <text>] [--tag <tag>...] [--skip-register] [--dry-run]\n assethub parts split (--file <path> | --source-url <url> | --source-id <id> | --image-url <url> | --file-ref-json <json> | --stdin | --stdin-base64 | --stdin-data-uri | --stdin-json | --source-json <json|@file|@-> | --data-uri <uri> | --clipboard | --order-id <id>) [--file-name <name>] [--content-type <type>] [--part-extractor <name>] [--skill-mode auto|manual|off] [--skill-id <id>...] [--wait] [--task-id <id>...] [--mission-id <id>] [--all-ready] [--download --out-dir <dir>]\n assethub parts compare (--file <path> | --source-url <url> | --source-id <id> | --image-url <url> | --file-ref-json <json> | --stdin | --stdin-base64 | --stdin-data-uri | --stdin-json | --source-json <json|@file|@-> | --data-uri <uri> | --clipboard) [--file-name <name>] [--content-type <type>] [--preprocess-prompt <text>] [--preprocess-model-id <id>] [--fail-on-preprocess-error] [--part-extractor <name>] [--wait] [--task-id <id>...] [--mission-id <id>] [--all-ready] [--download --out-dir <dir>]\n assethub autopilot [<image>] --demo [--yolo] [--json] [--max-regen <n>] [--stall-rounds <n>] [--tie-epsilon <x>] [--multiview 2-view|4-view|6-view] [--ab-mode serial|cross] [--credit-budget <n>]\n\nGlobal options:\n --api-key <key> Overrides saved auth and ASSETHUB_API_KEY.\n --base-url <url> Override the selected API origin. Default: https://app.assethub.io.\n --profile <name> Select this saved profile ahead of environment credentials and origin.\n --workspace <id> Select workspace scope for this command without changing saved selection.\n --config <path> Auth config path. Defaults to ~/.assethub/config.json.\n --version Show installed package version.\n --help Show help.\n\nExamples:\n ASSETHUB_API_KEY=ah_live_xxx assethub models list\n assethub auth login --api-key-stdin\n assethub init --dry-run\n assethub models list --ids-only\n assethub files upload ./input.png --media-type image\n assethub source create --file ./input.png --media-type image\n pbpaste | assethub source create --stdin-data-uri --media-type image\n assethub source create --clipboard --media-type image --file-name clipboard.png\n printf '{\"image_url\":{\"url\":\"data:image/png;base64,...\"}}' | assethub parts split --stdin-json --part-extractor \"V1.5\" --wait\n base64 -i ./input.png | assethub parts split --stdin-base64 --file-name input.png --content-type image/png --part-extractor \"V1.5\" --wait\n cat ./input.png | assethub parts split --stdin --file-name input.png --part-extractor \"V1.5\" --wait\n assethub image generate --prompt \"stylized prop concept\" --wait\n assethub mesh generate --file ./input.png --wait\n assethub animate presets --rig-type biped\n assethub rig create --source-resource-id mesh_x --rig-type biped --wait\n assethub animate retarget --resource-id rig_x --animation preset:idle --wait\n assethub production analyze --file ./input.png --part-extractor \"V1.5\" --wait\n assethub production run --order-id ord_x --mission-id ms_x --run-mode full_auto --max-cost-credits 200 --wait\n assethub production run --image ./character.png --estimate\n assethub production run --image ./character.png --compose v6 --max-cost 500 --wait --download --out-dir ./out/asset\n assethub production watch ord_x\n assethub runs get run_x --summary\n assethub runs wait run_x --timeout-ms 3600000\n assethub production intervene ord_x --exclude 7 --rename 3=\"left wing\" --idempotency-key review-2026-07-29\n assethub production interventions ord_x\n assethub runs upload ./out/pluffy-run-2026-07-30 --dry-run\n assethub runs upload ./out/pluffy-run-2026-07-30 --tag pluffy --description \"V3 humanoid, 18 parts\"\n assethub parts split --file ./input.png --part-extractor \"V1.5\" --wait --all-ready\n assethub parts compare --file ./input.png --preprocess-prompt \"clean white background, centered product photo\" --part-extractor \"V1.5\" --wait --all-ready\n";
26
26
  export declare const commandSkills: (subcommand: string | undefined, positionals: string[], ctx: CommandContext) => Promise<void>;
27
27
  /**
28
28
  * The `animate retarget` request, built from flags alone.
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AA4BA,OAAO,EAQL,KAAK,wBAAwB,EAO7B,KAAK,YAAY,EAEjB,KAAK,UAAU,EAef,oBAAoB,EACrB,MAAM,sBAAsB,CAAA;AAc7B,OAAO,EAAC,kBAAkB,EAAc,MAAM,gCAAgC,CAAA;AAI9E,KAAK,KAAK,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,GAAG,MAAM,EAAE,CAAC,CAAA;AAuBxD,KAAK,YAAY,GAAG;IAClB,MAAM,EAAE,MAAM,CAAA;IACd,cAAc,CAAC,EAAE,UAAU,CAAA;IAC3B,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,OAAO,EAAE,MAAM,CAAA;IACf,OAAO,EAAE,MAAM,CAAA;IACf,MAAM,EAAE,MAAM,GAAG,KAAK,GAAG,SAAS,CAAA;CACnC,CAAA;AAED,KAAK,cAAc,GAAG;IACpB,MAAM,EAAE,UAAU,CAAC,OAAO,oBAAoB,CAAC,CAAA;IAC/C,KAAK,EAAE,KAAK,CAAA;IACZ,IAAI,EAAE,YAAY,CAAA;IAClB;;;;;OAKG;IACH,IAAI,EAAE,MAAM,EAAE,CAAA;CACf,CAAA;AA4HD,eAAO,MAAM,KAAK,wvcA6IjB,CAAA;AAi/CD,eAAO,MAAM,aAAa,GACxB,YAAY,MAAM,GAAG,SAAS,EAC9B,aAAa,MAAM,EAAE,EACrB,KAAK,cAAc,KAClB,OAAO,CAAC,IAAI,CA6Hd,CAAA;AAi2CD;;;;;;GAMG;AACH,eAAO,MAAM,6BAA6B,GACxC,OAAO,KAAK,KACX,wBA0BF,CAAA;AAED;;;;GAIG;AACH,eAAO,MAAM,qBAAqB,GAChC,OAAO,KAAK,KACX,IAAI,CAAC,UAAU,EAAE,QAAQ,CAM1B,CAAA;AA6fF;;;;;;;;;;;;;;;;;;GAkBG;AACH,eAAO,MAAM,uBAAuB,GAClC,MAAM,SAAS,MAAM,EAAE,KACtB,YAAY,EAuGd,CAAA;AA+tCD,MAAM,MAAM,cAAc,GAAG;IAC3B,UAAU,EAAE,MAAM,CAAA;IAClB,OAAO,EAAE,MAAM,GAAG,SAAS,CAAA;IAC3B,QAAQ,EAAE,MAAM,GAAG,SAAS,CAAA;IAC5B,GAAG,EAAE,MAAM,GAAG,SAAS,CAAA;IACvB,WAAW,EAAE,MAAM,CAAA;IACnB,IAAI,EAAE,MAAM,EAAE,CAAA;IACd,MAAM,EAAE,OAAO,CAAA;IACf,YAAY,EAAE,OAAO,CAAA;CACtB,CAAA;AAED;;;;GAIG;AACH,eAAO,MAAM,mBAAmB,GAC9B,YAAY,MAAM,GAAG,SAAS,EAC9B,aAAa,MAAM,EAAE,EACrB,OAAO,KAAK,KACX,cAoBF,CAAA;AAED,KAAK,iBAAiB,GAAG,IAAI,CAC3B,OAAO,CAAC,UAAU,CAAC,OAAO,kBAAkB,CAAC,CAAC,EAC5C,SAAS,GACT,UAAU,GACV,KAAK,GACL,WAAW,GACX,QAAQ,GACR,OAAO,GACP,OAAO,GACP,UAAU,CACb,CAAA;AAED,eAAO,MAAM,iBAAiB,GAC5B,WAAW,MAAM,EACjB,MAAM,iBAAiB;;;;;;;;;;;;;;CAUvB,CAAA;AAEF,eAAO,MAAM,sBAAsB,GACjC,SAAS,UAAU,CAAC,OAAO,iBAAiB,CAAC,EAC7C,MAAM,iBAAiB,EACvB,SAAS,MAAM;;;;;;;;;;;;;;;;;;;;;;;CAYf,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AA6BA,OAAO,EAQL,KAAK,wBAAwB,EAO7B,KAAK,YAAY,EAEjB,KAAK,UAAU,EAkBf,oBAAoB,EACrB,MAAM,sBAAsB,CAAA;AAc7B,OAAO,EAAC,kBAAkB,EAAc,MAAM,gCAAgC,CAAA;AAoB9E,KAAK,KAAK,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,GAAG,MAAM,EAAE,CAAC,CAAA;AAuBxD,KAAK,YAAY,GAAG;IAClB,MAAM,EAAE,MAAM,CAAA;IACd,cAAc,CAAC,EAAE,UAAU,CAAA;IAC3B,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,OAAO,EAAE,MAAM,CAAA;IACf,OAAO,EAAE,MAAM,CAAA;IACf,MAAM,EAAE,MAAM,GAAG,KAAK,GAAG,SAAS,CAAA;CACnC,CAAA;AAED,KAAK,cAAc,GAAG;IACpB,MAAM,EAAE,UAAU,CAAC,OAAO,oBAAoB,CAAC,CAAA;IAC/C,KAAK,EAAE,KAAK,CAAA;IACZ,IAAI,EAAE,YAAY,CAAA;IAClB;;;;;OAKG;IACH,IAAI,EAAE,MAAM,EAAE,CAAA;CACf,CAAA;AA4ID,eAAO,MAAM,KAAK,s+dAoJjB,CAAA;AA2gDD,eAAO,MAAM,aAAa,GACxB,YAAY,MAAM,GAAG,SAAS,EAC9B,aAAa,MAAM,EAAE,EACrB,KAAK,cAAc,KAClB,OAAO,CAAC,IAAI,CA6Hd,CAAA;AA61CD;;;;;;GAMG;AACH,eAAO,MAAM,6BAA6B,GACxC,OAAO,KAAK,KACX,wBA0BF,CAAA;AAED;;;;GAIG;AACH,eAAO,MAAM,qBAAqB,GAChC,OAAO,KAAK,KACX,IAAI,CAAC,UAAU,EAAE,QAAQ,CAM1B,CAAA;AA6fF;;;;;;;;;;;;;;;;;;GAkBG;AACH,eAAO,MAAM,uBAAuB,GAClC,MAAM,SAAS,MAAM,EAAE,KACtB,YAAY,EAuGd,CAAA;AAy7CD,MAAM,MAAM,cAAc,GAAG;IAC3B,UAAU,EAAE,MAAM,CAAA;IAClB,OAAO,EAAE,MAAM,GAAG,SAAS,CAAA;IAC3B,QAAQ,EAAE,MAAM,GAAG,SAAS,CAAA;IAC5B,GAAG,EAAE,MAAM,GAAG,SAAS,CAAA;IACvB,WAAW,EAAE,MAAM,CAAA;IACnB,IAAI,EAAE,MAAM,EAAE,CAAA;IACd,MAAM,EAAE,OAAO,CAAA;IACf,YAAY,EAAE,OAAO,CAAA;CACtB,CAAA;AAED;;;;GAIG;AACH,eAAO,MAAM,mBAAmB,GAC9B,YAAY,MAAM,GAAG,SAAS,EAC9B,aAAa,MAAM,EAAE,EACrB,OAAO,KAAK,KACX,cAoBF,CAAA;AAED,KAAK,iBAAiB,GAAG,IAAI,CAC3B,OAAO,CAAC,UAAU,CAAC,OAAO,kBAAkB,CAAC,CAAC,EAC5C,SAAS,GACT,UAAU,GACV,KAAK,GACL,WAAW,GACX,QAAQ,GACR,OAAO,GACP,OAAO,GACP,UAAU,CACb,CAAA;AAED,eAAO,MAAM,iBAAiB,GAC5B,WAAW,MAAM,EACjB,MAAM,iBAAiB;;;;;;;;;;;;;;CAUvB,CAAA;AAEF,eAAO,MAAM,sBAAsB,GACjC,SAAS,UAAU,CAAC,OAAO,iBAAiB,CAAC,EAC7C,MAAM,iBAAiB,EACvB,SAAS,MAAM;;;;;;;;;;;;;;;;;;;;;;;CAYf,CAAA"}
package/dist/index.js CHANGED
@@ -1,6 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import { setTimeout as delay } from 'node:timers/promises';
3
3
  import { cliVersion, diagnose, mcpConfig } from './setup.js';
4
+ import { AGENT_IDS, initAgents, syncInstalledSkill } from './agentSetup.js';
4
5
  import { ingestProjectSources } from './projectSources.js';
5
6
  import { downloadCanvas } from './canvasDownload.js';
6
7
  import { executeNodeMeshBatch, resumeNodeMeshBatch, } from './nodeMeshBatch.js';
@@ -21,6 +22,8 @@ import { activeExecution, childOperationId, CliExecutionError, executeRecorded,
21
22
  import { buildRunUploadPlan, formatBytes } from './runsUpload/buildRunUpload.js';
22
23
  import { readGraphFolder } from './runsUpload/graphFolder.js';
23
24
  import { uploadRun } from './runsUpload/uploadRun.js';
25
+ import { existsSync } from 'node:fs';
26
+ import { DEFAULT_MAX_PARTS, buildAutomationConfig, buildComposerPartsFromMeshExecutions, detectOneShotImageInput, estimateOneShotCost, exceedsMaxCost, formatExecutionSummaryLines, parseComposeFlag, pollAutomationBatch, readServerCostBreakdown, resolveFullBodyImageAssetId, serverSupportsV6Compose, withErrorHint, } from './productionOneShot.js';
24
27
  const defaultBaseUrl = 'https://app.assethub.io';
25
28
  // Mirrors PUBLIC_IMAGE_GENERATE_DEFAULT_MODEL_ID in apps/frontend
26
29
  // (src/feature/imageGen/util/publicImageGenDefaultModel.ts). This package does
@@ -30,15 +33,6 @@ const defaultImageModelId = 'imageGen.nanoBanana2.openrouter';
30
33
  const defaultMeshModelId = 'meshGen.hunyuan31';
31
34
  const defaultProfileName = 'default';
32
35
  const defaultPartExtractorName = 'V1.5';
33
- const artifactGraphPartExtractorApiValues = new Set([
34
- 'ah_agent_graph_v3_6_1',
35
- 'ah_agent_graph_v3_6_3',
36
- 'ah_agent_graph_v3_6_4',
37
- 'ah_agent_graph_v3_6_5',
38
- 'ah_agent_graph_pluffy_v3_1',
39
- 'ah_agent_graph_v3_7',
40
- 'ah_agent_graph_v3_7_1',
41
- ]);
42
36
  const partExtractorOptions = [
43
37
  {
44
38
  publicName: 'V1.5',
@@ -80,17 +74,34 @@ const partExtractorOptions = [
80
74
  apiValue: 'ah_agent_graph_pluffy_v3_1',
81
75
  aliases: ['pluffy', 'pluffy v3.1', 'pluffy 3.1'],
82
76
  },
77
+ {
78
+ publicName: 'V3.0.9 Garment Boundaries',
79
+ apiValue: 'ah_agent_graph_v3_7_2',
80
+ aliases: ['v3.0.9', '3.0.9'],
81
+ },
83
82
  {
84
83
  publicName: 'V3.7 Artist Skills',
85
84
  apiValue: 'ah_agent_graph_v3_7',
86
- aliases: ['v3.7', '3.7'],
85
+ // The web picker and `production agents` call it V3.0.7.
86
+ aliases: ['v3.7', '3.7', 'v3.0.7 artist skills', 'v3.0.7', '3.0.7'],
87
87
  },
88
88
  {
89
89
  publicName: 'V3.7.1 Building Modules',
90
90
  apiValue: 'ah_agent_graph_v3_7_1',
91
- aliases: ['v3.7.1', '3.7.1'],
91
+ // The web picker and `production agents` call it V3.0.8.
92
+ aliases: ['v3.7.1', '3.7.1', 'v3.0.8 building modules', 'v3.0.8', '3.0.8'],
93
+ },
94
+ {
95
+ publicName: 'Humanoid Assembly (internal)',
96
+ apiValue: 'ah_agent_graph_humanoid_assembly_auto',
97
+ aliases: ['humanoid assembly', 'humanoid-assembly', 'humanoid_assembly_auto'],
92
98
  },
93
99
  ];
100
+ // Graph-engine extractors run through the artifact-graph endpoint. Derived from
101
+ // the option list so a newly listed graph agent cannot miss the graph path.
102
+ const artifactGraphPartExtractorApiValues = new Set(partExtractorOptions
103
+ .map(option => option.apiValue)
104
+ .filter(apiValue => apiValue.startsWith('ah_agent_graph_')));
94
105
  const partExtractorPublicNames = partExtractorOptions
95
106
  .map(option => option.publicName)
96
107
  .join(', ');
@@ -100,7 +111,12 @@ const partExtractorByInput = new Map(partExtractorOptions.flatMap(option => [
100
111
  ...option.aliases.map(alias => [normalizePartExtractorName(alias), option]),
101
112
  ]));
102
113
  const partExtractorPublicNameByApiValue = new Map(partExtractorOptions.map(option => [option.apiValue, option.publicName]));
103
- const isInternalPartExtractorId = (value) => value.trim().includes('_');
114
+ // Every registered internal apiValue is an `ah_...` id (see partExtractorOptions
115
+ // above). Matching that prefix instead of a blanket "contains an underscore"
116
+ // check keeps this from rejecting a public alias that happens to use
117
+ // underscores (e.g. 'humanoid_assembly_auto', mirroring the engine profile
118
+ // name) while still catching every real internal id.
119
+ const isInternalPartExtractorId = (value) => value.trim().toLowerCase().startsWith('ah_');
104
120
  const execFileAsync = promisify(execFile);
105
121
  export const usage = `AssetHub CLI
106
122
 
@@ -109,6 +125,7 @@ CLI and MCP are available to all AssetHub users. Workspace permissions and featu
109
125
  Usage:
110
126
  assethub --version
111
127
  assethub doctor [--mcp] [--profile <name>] [--timeout-ms <n>]
128
+ assethub init [--agent claude-code|codex|cursor...] [--project] [--dry-run] [--base-url <url>] [--workspace <id>] [--profile <name>]
112
129
  assethub mcp tools [tool-name] [--account] [--profile <name>] [--timeout-ms <n>]
113
130
  assethub mcp config --client cursor|codex [--account] [--base-url <url>]
114
131
  assethub auth login --api-key <key> [--base-url <url>] [--profile <name>]
@@ -162,7 +179,7 @@ Usage:
162
179
  assethub composer refine --list-modes
163
180
  assethub composer refine --from-run <run-id> --instruction <text> [--mode standard|thorough|placement|workshop|blender|codex] [--max-rounds <n>] [--transforms-json <json|@file>] [--wait] [--download --out-dir <dir>]
164
181
  assethub composer refine --input-json <json|@file> [--canvas <id>] [--operation-id <uuid>] [--wait] [--download --out-dir <dir>]
165
- assethub composer run --part <mesh-asset-id> [--part <mesh-asset-id>...] --reference <image-asset-id> [--model <id>] [--mode quick|quality] [--transforms-json <json|@file>] [--canvas <id>] [--wait]
182
+ assethub composer run --part <mesh-asset-id>[:<part-image-asset-id>] [--part <mesh-asset-id>[:<part-image-asset-id>]...] --reference <image-asset-id> [--model <id>] [--mode quick|quality] [--transforms-json <json|@file>] [--canvas <id>] [--wait]
166
183
  assethub composer run --input-json <json|@file> [--canvas <id>] [--operation-id <uuid>] [--wait] [--download --out-dir <dir>]
167
184
  assethub composer run --from-run <run-id> [--transforms-json <json|@file>] [--mode quick|quality] [--wait]
168
185
  assethub composer run --node <shape:id> --canvas <id> [--model <id>] [--mode quick|quality] [--operation-id <uuid>] [--wait]
@@ -170,7 +187,7 @@ Usage:
170
187
  assethub canvas list [--cursor <cursor>] [--limit <n>]
171
188
  assethub canvas get|use|open [<id>]
172
189
  assethub runs list [--canvas <id>] [--cursor <cursor>] [--limit <n>]
173
- assethub runs get|watch <run-id> [--timeout-ms <n>]
190
+ assethub runs get|watch|wait <run-id> [--interval-ms <ms>] [--timeout-ms <n>] [--summary]
174
191
  assethub runs resume <operation-id> [--wait]
175
192
  assethub graph list [--cursor <cursor>] [--limit <n>]
176
193
  assethub graph show|export [--canvas <id> | --graph <id>] [--source generated|upload] [--artifact <node-id>] [--out <path>] [--allow-truncated]
@@ -201,6 +218,7 @@ Usage:
201
218
  assethub production status <order-id> [--wait] [--download --out-dir <dir>]
202
219
  assethub production execute --order-id <id> --mission-id <id> --task-id <id> [--task-id <id>...] [--part-extractor <name>] [--part-extraction-mode fast|high_quality] [--wait] [--download --out-dir <dir>]
203
220
  assethub production run --order-id <id> --mission-id <id> [--run-mode full_auto|approval] [--task-id <id>...] [--part-extractor <name>] [--part-extraction-mode fast|high_quality] [--allowed-model-id <id>...] [--max-iterations <n>] [--max-cost-credits <n>] [--wait] [--download --out-dir <dir>]
221
+ assethub production run --image <file|asset-id> [--canvas <id>] [--part-extractor <name>] [--compose v6|none] [--mesh-model <id>] [--max-parts <n>] [--max-cost <credits>] [--estimate] [--wait] [--download --out-dir <dir>] [--json]
204
222
  assethub production watch <order-id> [--interval-ms <ms>] [--timeout-ms <ms>] [--download --out-dir <dir>]
205
223
  assethub production intervene <order-id> (--exclude <target-id> | --include <target-id> | --add-part <name> | --rename <target-id>=<name> | --reject <target-id>[=<reason>] | --regenerate <target-id>=<mode> | --set-param <key>=<value> | --ops-json <json|@file|@->)... [--idempotency-key <key>]
206
224
  assethub production interventions <order-id>
@@ -221,6 +239,7 @@ Global options:
221
239
  Examples:
222
240
  ASSETHUB_API_KEY=ah_live_xxx assethub models list
223
241
  assethub auth login --api-key-stdin
242
+ assethub init --dry-run
224
243
  assethub models list --ids-only
225
244
  assethub files upload ./input.png --media-type image
226
245
  assethub source create --file ./input.png --media-type image
@@ -236,7 +255,11 @@ Examples:
236
255
  assethub animate retarget --resource-id rig_x --animation preset:idle --wait
237
256
  assethub production analyze --file ./input.png --part-extractor "V1.5" --wait
238
257
  assethub production run --order-id ord_x --mission-id ms_x --run-mode full_auto --max-cost-credits 200 --wait
258
+ assethub production run --image ./character.png --estimate
259
+ assethub production run --image ./character.png --compose v6 --max-cost 500 --wait --download --out-dir ./out/asset
239
260
  assethub production watch ord_x
261
+ assethub runs get run_x --summary
262
+ assethub runs wait run_x --timeout-ms 3600000
240
263
  assethub production intervene ord_x --exclude 7 --rename 3="left wing" --idempotency-key review-2026-07-29
241
264
  assethub production interventions ord_x
242
265
  assethub runs upload ./out/pluffy-run-2026-07-30 --dry-run
@@ -728,6 +751,25 @@ const assertFlagHasValue = (value, flagDescription) => {
728
751
  }
729
752
  return value;
730
753
  };
754
+ /**
755
+ * Parses one `--part` value for `composer run`/`composer refine` into a
756
+ * composer part. Plain `<mesh-asset-id>` composes without a part-reference
757
+ * image (Composer V6 then requires it via `--input-json` or falls back to
758
+ * the mesh's own thumbnail, if enabled). `<mesh-asset-id>:<part-image-asset-id>`
759
+ * attaches the image the part's mesh was generated from, matching what the
760
+ * canvas node graph supplies automatically for UI-driven runs.
761
+ */
762
+ const parsePartFlagValue = (raw) => {
763
+ const value = assertFlagHasValue(raw, '--part <mesh-asset-id>[:<part-image-asset-id>]');
764
+ const separatorIndex = value.indexOf(':');
765
+ if (separatorIndex === -1)
766
+ return { assetId: value };
767
+ const assetId = value.slice(0, separatorIndex);
768
+ const partImageAssetId = value.slice(separatorIndex + 1);
769
+ if (!assetId || !partImageAssetId)
770
+ throw new Error('--part must be <mesh-asset-id> or <mesh-asset-id>:<part-image-asset-id>');
771
+ return { assetId, partImageAssetId };
772
+ };
731
773
  const sourceInputCount = (flags) => [
732
774
  getSourceResourceIdFlag(flags) != null,
733
775
  getSourceUrlFlag(flags) != null,
@@ -2243,9 +2285,7 @@ const commandComposerRefine = async (ctx) => {
2243
2285
  : previous
2244
2286
  ? composerInputFromRun(previous, 'mesh.refine')
2245
2287
  : {
2246
- parts: parts.map(assetId => ({
2247
- assetId: assertFlagHasValue(assetId, '--part <asset-id>'),
2248
- })),
2288
+ parts: parts.map(parsePartFlagValue),
2249
2289
  fullBodyImageAssetId: requireFlag(ctx.flags, 'reference'),
2250
2290
  };
2251
2291
  delete input.executionContext;
@@ -2354,9 +2394,7 @@ const commandComposer = async (subcommand, ctx) => {
2354
2394
  : json
2355
2395
  ? await readJsonArgument(json, '--input-json')
2356
2396
  : {
2357
- parts: parts.map(assetId => ({
2358
- assetId: assertFlagHasValue(assetId, '--part <asset-id>'),
2359
- })),
2397
+ parts: parts.map(parsePartFlagValue),
2360
2398
  fullBodyImageAssetId: requireFlag(ctx.flags, 'reference'),
2361
2399
  };
2362
2400
  delete input.executionContext;
@@ -3079,6 +3117,155 @@ const productionSession = (ctx, operation, canvasId = selectedCanvasId(ctx.flags
3079
3117
  canvasId,
3080
3118
  operation,
3081
3119
  });
3120
+ /**
3121
+ * `production run --image <file|assetId>`: the one-shot "image -> finished
3122
+ * asset" command. A thin wrapper around `production automation` (which
3123
+ * already does split -> mesh x N -> compose server-side) plus waiting,
3124
+ * cost estimation and downloads — it never re-implements the manual
3125
+ * split/mesh/compose dance. See productionOneShot.ts for the pure,
3126
+ * independently-tested pieces (image-flag resolution, cost estimate math,
3127
+ * batch-status polling, the V6 compose fallback's mesh<->image pairing, and
3128
+ * error hints); this function only wires them to the client and to flags.
3129
+ */
3130
+ const commandProductionRunOneShot = async (ctx) => {
3131
+ if (sourceInputCount(ctx.flags) > 0) {
3132
+ throw new Error('--image already resolves a source; do not combine it with --file/--source-id/--source-url/other source flags.');
3133
+ }
3134
+ const imageValue = requireFlag(ctx.flags, 'image');
3135
+ const detected = detectOneShotImageInput(imageValue, existsSync);
3136
+ const sourceFlags = {
3137
+ ...ctx.flags,
3138
+ ...(detected.kind === 'file'
3139
+ ? { file: detected.path }
3140
+ : { 'source-id': detected.resourceId }),
3141
+ };
3142
+ const compose = parseComposeFlag(getFlag(ctx.flags, 'compose'));
3143
+ const meshModelId = getFlag(ctx.flags, 'mesh-model') ?? defaultMeshModelId;
3144
+ const maxParts = getFlag(ctx.flags, 'max-parts') == null
3145
+ ? DEFAULT_MAX_PARTS
3146
+ : parsePositiveIntegerFlag(ctx.flags, 'max-parts', 1);
3147
+ const maxCostCredits = getFlag(ctx.flags, 'max-cost') == null
3148
+ ? undefined
3149
+ : parsePositiveIntegerFlag(ctx.flags, 'max-cost', 1);
3150
+ const agentVersion = resolvePartExtractorForAnalyze(ctx.flags);
3151
+ // Every number below comes from a side-effect-free GET; nothing here
3152
+ // starts real (billable) work, so this runs whether or not --estimate was
3153
+ // passed and gates --max-cost before the real automation call below.
3154
+ const [models, composerCapabilities] = await Promise.all([
3155
+ ctx.client.v2.listModels({ domain: 'meshGen' }),
3156
+ ctx.client.v2.getMeshComposers(),
3157
+ ]);
3158
+ const meshModel = models.find(model => model.id === meshModelId);
3159
+ const composeCredits = compose === 'v6'
3160
+ ? (composerCapabilities.quotes?.find(quote => quote.agentVersion === 'v6')
3161
+ ?.credits ?? null)
3162
+ : undefined;
3163
+ const estimate = estimateOneShotCost({
3164
+ meshModel,
3165
+ maxParts,
3166
+ composeRequested: compose === 'v6',
3167
+ composeCredits,
3168
+ });
3169
+ if (exceedsMaxCost(estimate.totalCredits, maxCostCredits)) {
3170
+ throw new Error(`Estimated cost ${estimate.totalCredits} credits exceeds --max-cost ${maxCostCredits}; refusing to run before spending anything. ${estimate.notes.join(' ')}`);
3171
+ }
3172
+ if (hasFlag(ctx.flags, 'estimate')) {
3173
+ print({ estimate });
3174
+ return;
3175
+ }
3176
+ const session = await productionSession(ctx, 'production.automation');
3177
+ const source = await recordedSource(ctx, await requireSource({
3178
+ flags: sourceFlags,
3179
+ client: ctx.client,
3180
+ fileMediaType: 'image',
3181
+ preferUploadId: true,
3182
+ }));
3183
+ const analyzeImage = productionAnalyzeSourceFromSource(source);
3184
+ const config = buildAutomationConfig(compose);
3185
+ const body = {
3186
+ images: [analyzeImage],
3187
+ agentVersion,
3188
+ ...(config ? { config } : {}),
3189
+ ...(maxCostCredits != null ? { maxCostCredits } : {}),
3190
+ };
3191
+ const queued = (await executeRecorded(session, 'production.automation', body, executionOptions(ctx.flags)));
3192
+ stderr.write(`[run] batch=${queued.batchId}\n`);
3193
+ // `estimatedCostBreakdown`'s presence on the automation response itself
3194
+ // (assethub-web #8179) is the proof that this server understood
3195
+ // `partComposerAgentVersion` and already ran Composer V6 server-side, in
3196
+ // the same call — no client-side fallback compose is needed. Its absence
3197
+ // means an older, currently-deployed server silently ignored that field,
3198
+ // so the CLI still has to pair parts and run compose itself below.
3199
+ const serverHandledV6Compose = compose === 'v6' &&
3200
+ serverSupportsV6Compose(queued);
3201
+ const needsFallbackCompose = compose === 'v6' && !serverHandledV6Compose;
3202
+ let batchStatus;
3203
+ if (hasFlag(ctx.flags, 'wait') || needsFallbackCompose) {
3204
+ batchStatus = await pollAutomationBatch({
3205
+ getStatus: () => ctx.client.v1.getProductionAutomationStatus(queued.batchId),
3206
+ sleep: ms => delay(ms),
3207
+ intervalMs: parsePositiveIntegerFlag(ctx.flags, 'interval-ms', 5000),
3208
+ timeoutMs: parsePositiveIntegerFlag(ctx.flags, 'timeout-ms', 1800000),
3209
+ onProgress: lines => lines.forEach(line => stderr.write(`${line}\n`)),
3210
+ });
3211
+ }
3212
+ let composeExecution;
3213
+ if (needsFallbackCompose) {
3214
+ const order = queued.images[0];
3215
+ if (!order)
3216
+ throw new Error('Automation did not return an order for the requested image.');
3217
+ if (batchStatus?.images.find(image => image.orderId === order.orderId)
3218
+ ?.status === 'failed')
3219
+ throw new Error(`Automation failed for order ${order.orderId}; there is nothing to compose.`);
3220
+ const runs = await ctx.client.v2.listCanvasRuns(session.canvas.id, { limit: 200 });
3221
+ const parts = buildComposerPartsFromMeshExecutions(runs.items, order.orderId);
3222
+ const fullBodyImageAssetId = resolveFullBodyImageAssetId(runs.items, order.orderId) ??
3223
+ (detected.kind === 'resourceId' ? detected.resourceId : undefined);
3224
+ if (parts.length === 0 || fullBodyImageAssetId == null) {
3225
+ throw withErrorHint(new Error('Could not find mesh part outputs (and the source image they were generated from) to compose for this order.'));
3226
+ }
3227
+ try {
3228
+ const composeQueued = await executeRecorded(session, 'mesh.compose', {
3229
+ parts,
3230
+ fullBodyImageAssetId,
3231
+ agentVersion: 'v6',
3232
+ }, executionOptions(ctx.flags));
3233
+ composeExecution = composeQueued.execution;
3234
+ }
3235
+ catch (error) {
3236
+ throw error instanceof Error ? withErrorHint(error) : error;
3237
+ }
3238
+ }
3239
+ // The automation receipt (`queued.execution`) is only the split stage's own
3240
+ // execution row; the real completion signal for the whole order (mesh gen
3241
+ // across every part, plus compose when the server ran it) is the batch
3242
+ // status polled above. Once that says the order is done, re-fetch the
3243
+ // execution so `--download`/the printed summary reflect the final state
3244
+ // rather than the split-stage snapshot from right after submission.
3245
+ const finalExecution = composeExecution ??
3246
+ (batchStatus != null
3247
+ ? await ctx.client.v2.getRun(queued.execution.runId)
3248
+ : queued.execution);
3249
+ // Prefer the server's own reported cost (#8179) over our preflight
3250
+ // best-effort `estimate` once we actually have it; absent on a server
3251
+ // that has not deployed #8179 yet, in which case only `estimate` (used
3252
+ // for the --max-cost gate above) is available.
3253
+ const serverCost = readServerCostBreakdown(queued);
3254
+ // The machine-readable summary this prints is always JSON, matching every
3255
+ // other command in this CLI; --json is accepted (it is a no-op) rather than
3256
+ // rejected, since there is no plain-text mode here to opt out of.
3257
+ print(await withOptionalDownloads(ctx.flags, sanitizeProductionOutput({
3258
+ batchId: queued.batchId,
3259
+ estimatedCostCredits: queued.estimatedCostCredits,
3260
+ ...(serverCost ?? {}),
3261
+ images: queued.images,
3262
+ estimate,
3263
+ batchStatus,
3264
+ compose: composeExecution,
3265
+ execution: finalExecution,
3266
+ })));
3267
+ process.exitCode = executionExitCode(finalExecution);
3268
+ };
3082
3269
  const commandProduction = async (subcommand, positionals, ctx) => {
3083
3270
  if (subcommand === 'agents') {
3084
3271
  print(sanitizeProductionOutput(await ctx.client.v1.getProductionAgents()));
@@ -3185,6 +3372,14 @@ const commandProduction = async (subcommand, positionals, ctx) => {
3185
3372
  return;
3186
3373
  }
3187
3374
  if (subcommand === 'run') {
3375
+ // `production run --image <file|assetId>` is a different command in
3376
+ // everything but name: the one-shot image -> finished-asset flow, not
3377
+ // confirmed-task mission execution. Intercept before `--order-id` is
3378
+ // required so the mission flow below is completely untouched when
3379
+ // --image is absent.
3380
+ if (getFlag(ctx.flags, 'image') != null) {
3381
+ return commandProductionRunOneShot(ctx);
3382
+ }
3188
3383
  const orderId = requireFlag(ctx.flags, 'order-id');
3189
3384
  const missionId = requireFlag(ctx.flags, 'mission-id');
3190
3385
  const runMode = parseRunModeFlag(ctx.flags);
@@ -3879,12 +4074,21 @@ const commandRuns = async (subcommand, positionals, ctx) => {
3879
4074
  print(await ctx.client.v2.listCanvasRuns(canvas.id, pageOptions(ctx.flags)));
3880
4075
  return;
3881
4076
  }
3882
- if (subcommand === 'get' || subcommand === 'watch') {
4077
+ if (subcommand === 'get' || subcommand === 'watch' || subcommand === 'wait') {
3883
4078
  const id = requirePositional(positionals, 2, 'run-id');
4079
+ // `wait` is `watch` under a name that matches how long-running waits are
4080
+ // asked for elsewhere in the CLI; both poll the same way (429s are
4081
+ // retried inside the client's own request layer, same as every other
4082
+ // poll loop in this file) and accept the same --interval-ms/--timeout-ms.
3884
4083
  const execution = subcommand === 'get'
3885
4084
  ? await ctx.client.v2.getRun(id)
3886
4085
  : await waitForExecution(ctx.client, id, watchOptions(ctx.flags));
3887
- print({ execution });
4086
+ if (subcommand === 'get' && hasFlag(ctx.flags, 'summary')) {
4087
+ stdout.write(`${formatExecutionSummaryLines(execution).join('\n')}\n`);
4088
+ }
4089
+ else {
4090
+ print({ execution });
4091
+ }
3888
4092
  process.exitCode = executionExitCode(execution);
3889
4093
  return;
3890
4094
  }
@@ -4003,6 +4207,20 @@ const parseNonNegativeIntegerFlag = (flags, name) => {
4003
4207
  }
4004
4208
  return parsed;
4005
4209
  };
4210
+ /** Base URL and workspace an MCP entry should target: explicit flags, then the selected profile, then defaults. */
4211
+ const resolveMcpTarget = async (flags) => {
4212
+ const config = await readAuthConfig(getConfigPath(flags));
4213
+ const explicitProfile = getFlag(flags, 'profile');
4214
+ const stored = config.profiles?.[explicitProfile ?? config.defaultProfile ?? defaultProfileName];
4215
+ if (explicitProfile && !stored)
4216
+ throw new Error('Selected profile does not exist');
4217
+ const selected = explicitProfile || stored?.workspaceId || isPersonalProfile(stored);
4218
+ const baseUrl = getFlag(flags, 'base-url') ??
4219
+ (selected ? stored?.baseUrl : env.ASSETHUB_API_BASE_URL ?? stored?.baseUrl) ?? defaultBaseUrl;
4220
+ const workspaceId = getFlag(flags, 'workspace') ??
4221
+ (stored && new URL(baseUrl).origin === new URL(stored.baseUrl).origin ? stored.workspaceId : undefined);
4222
+ return { baseUrl, workspaceId };
4223
+ };
4006
4224
  const run = async () => {
4007
4225
  const parsed = parseArgs(argv.slice(2));
4008
4226
  if (hasFlag(parsed.flags, 'version')) {
@@ -4014,6 +4232,20 @@ const run = async () => {
4014
4232
  return;
4015
4233
  }
4016
4234
  const [command, subcommand] = parsed.positionals;
4235
+ if (command !== 'init')
4236
+ await syncInstalledSkill();
4237
+ if (command === 'init') {
4238
+ if (subcommand)
4239
+ throw new Error(`Use init [--agent ${AGENT_IDS.join('|')}] [--project] [--dry-run]`);
4240
+ const target = await resolveMcpTarget(parsed.flags);
4241
+ print(await initAgents({
4242
+ ...target,
4243
+ agents: getFlagValues(parsed.flags, 'agent').map(value => assertFlagHasValue(value, '--agent <name>')),
4244
+ project: hasFlag(parsed.flags, 'project'),
4245
+ dryRun: hasFlag(parsed.flags, 'dry-run'),
4246
+ }));
4247
+ return;
4248
+ }
4017
4249
  if (command === 'mcp' && subcommand === 'tools') {
4018
4250
  stderr.write('Discovering AssetHub MCP tools…\n');
4019
4251
  const report = await diagnose({
@@ -4050,16 +4282,7 @@ const run = async () => {
4050
4282
  if (command === 'mcp') {
4051
4283
  if (subcommand !== 'config')
4052
4284
  throw new Error('Use mcp tools [tool-name] or mcp config --client cursor|codex');
4053
- const config = await readAuthConfig(getConfigPath(parsed.flags));
4054
- const explicitProfile = getFlag(parsed.flags, 'profile');
4055
- const stored = config.profiles?.[explicitProfile ?? config.defaultProfile ?? defaultProfileName];
4056
- if (explicitProfile && !stored)
4057
- throw new Error('Selected profile does not exist');
4058
- const selected = explicitProfile || stored?.workspaceId || isPersonalProfile(stored);
4059
- const baseUrl = getFlag(parsed.flags, 'base-url') ??
4060
- (selected ? stored?.baseUrl : env.ASSETHUB_API_BASE_URL ?? stored?.baseUrl) ?? defaultBaseUrl;
4061
- const workspaceId = getFlag(parsed.flags, 'workspace') ??
4062
- (stored && new URL(baseUrl).origin === new URL(stored.baseUrl).origin ? stored.workspaceId : undefined);
4285
+ const { baseUrl, workspaceId } = await resolveMcpTarget(parsed.flags);
4063
4286
  stdout.write(mcpConfig(requireFlag(parsed.flags, 'client'), baseUrl, hasFlag(parsed.flags, 'account'), workspaceId));
4064
4287
  return;
4065
4288
  }