@assethub/cli 0.1.16 → 0.1.18

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/README.md CHANGED
@@ -141,7 +141,7 @@ Existing parts commands use the same canvas and durable operation storage:
141
141
  assethub parts split --source-id "$IMAGE_ASSET_ID" --canvas "$CANVAS_ID" --part-extractor V1.5 --wait
142
142
  # Select only the parts to execute; --all-ready selects all ready tasks.
143
143
  assethub parts split --source-id "$IMAGE_ASSET_ID" --canvas "$CANVAS_ID" --part-extractor V1.5 --all-ready --wait
144
- # Internal V3.6.1 and V3.6.3 run the complete graph split through one analyze receipt.
144
+ # Internal V3.6.1, V3.6.3 and V3.6.4 run the complete graph split through one analyze receipt.
145
145
  assethub production agents
146
146
  assethub parts split --source-id "$IMAGE_ASSET_ID" --canvas "$CANVAS_ID" --part-extractor V3.6.1 --all-ready --wait
147
147
  assethub production automation --canvas "$CANVAS_ID" --input-json @batch.json --wait
@@ -150,7 +150,8 @@ assethub production automation --canvas "$CANVAS_ID" --input-json @batch.json --
150
150
  `parts split` keeps separate analysis and selected-part execution phases. Each phase
151
151
  has its own saved operation ID, with the execution linked to the analysis run.
152
152
  For Internal `V3.6.1` (`V3.6.1 Primary Images First`) and `V3.6.3`
153
- (`V3.6.3 Fast Analysis`, CLI 0.1.16+), analysis runs the complete
153
+ (`V3.6.3 Fast Analysis`, CLI 0.1.16+), and `V3.6.4`
154
+ (`V3.6.4 Fast Analysis`, CLI 0.1.17+), analysis runs the complete
154
155
  Artifact Graph split. `--all-ready` waits for that one receipt and does not start a
155
156
  second production execution. Resume an interrupted graph split with
156
157
  `runs resume <operation-id>`; `--task-id`, `--mission-id`,
@@ -421,7 +422,8 @@ Image generation uses the `v2` endpoint with mandatory canvas history.
421
422
 
422
423
  Part extraction uses the same names shown in the AssetHub product: `V1.5`,
423
424
  `V2.0 alpha`, `V2.1 alpha`, and the Internal-only aliases `V3.6.1`
424
- (`V3.6.1 Primary Images First`) and `V3.6.3` (`V3.6.3 Fast Analysis`).
425
+ (`V3.6.1 Primary Images First`), `V3.6.3` (`V3.6.3 Fast Analysis`),
426
+ and `V3.6.4` (`V3.6.4 Fast Analysis`).
425
427
  Run `production agents` to check availability and `supportedOnGraphEndpoint`
426
428
  before selecting a graph version. These aliases do not change the default.
427
429
  Retired names are no longer accepted by the CLI.
@@ -540,3 +542,30 @@ variables to your MCP client and reconnect. This server uses
540
542
  `https://app.assethub.io/api/workspaces/mcp` and exposes `workspace_list`,
541
543
  `workspace_members_list`, `workspace_member_invite`, `workspace_member_set_role`,
542
544
  and `workspace_member_remove`. Keep the existing API-key MCP server for generation.
545
+
546
+ ## Download a canvas handoff
547
+
548
+ ```sh
549
+ assethub canvas download --canvas 42 --out-dir ./client-handoff
550
+ assethub canvas download --canvas 42 --mesh mesh_123 --out-dir ./mesh-handoff
551
+ ```
552
+
553
+ This staged feature uses the selected workspace API key. A canvas invitation does
554
+ not grant API-key or workspace access. Use an empty output directory. The bundle
555
+ contains image files, final mesh files, `manifest.json`, `index.html`, and
556
+ `history.md`. Open `index.html` locally to review images and recorded steps.
557
+
558
+ The export follows the actual recorded mesh inputs and image-edit ancestors,
559
+ including intermediate assets removed from the canvas. Current canvas connections
560
+ are not generation evidence. UI `mesh_generation` / `projected_image_gen`, API
561
+ execution receipts, and associated Production / Artifact Graph records are read
562
+ without dispatching new work. Prompts and models appear when recorded. Missing
563
+ or ambiguous history is reported explicitly; this is the available recorded
564
+ history, not a reconstruction of unrecorded editing gestures.
565
+
566
+ Downloads stream to temporary files and are renamed only after completion. The
567
+ manifest records local paths, byte counts and SHA-256 hashes; signed URL tokens
568
+ and API credentials are not saved. Download failures retain the successful files
569
+ and manifest and exit 1. Truncated exports exit 3. Individual files are limited to
570
+ 1 GiB, and bounded server traversal reports any omitted history. History warnings
571
+ can remain even when all available files download successfully.
@@ -0,0 +1,28 @@
1
+ import type { CanvasExport } from '@assethub/api-client';
2
+ /** Signed file URLs are used without API credentials and never written into the bundle. */
3
+ export declare const downloadCanvas: (input: {
4
+ client: {
5
+ v2: {
6
+ exportCanvas: (id: number, options?: {
7
+ mesh?: string;
8
+ }) => Promise<CanvasExport>;
9
+ };
10
+ };
11
+ canvasId: number;
12
+ mesh?: string;
13
+ outDir: string;
14
+ progress?: (message: string) => void;
15
+ }) => Promise<{
16
+ outDir: string;
17
+ manifestPath: string;
18
+ htmlPath: string;
19
+ historyPath: string;
20
+ downloaded: number;
21
+ failed: number;
22
+ steps: number;
23
+ warnings: string[];
24
+ missingEvidence: string[];
25
+ truncated: boolean;
26
+ exitCode: number;
27
+ }>;
28
+ //# sourceMappingURL=canvasDownload.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"canvasDownload.d.ts","sourceRoot":"","sources":["../src/canvasDownload.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAC,YAAY,EAAoB,MAAM,sBAAsB,CAAA;AAmBzE,2FAA2F;AAC3F,eAAO,MAAM,cAAc,GAAU,OAAO;IAC1C,MAAM,EAAE;QACN,EAAE,EAAE;YACF,YAAY,EAAE,CACZ,EAAE,EAAE,MAAM,EACV,OAAO,CAAC,EAAE;gBAAC,IAAI,CAAC,EAAE,MAAM,CAAA;aAAC,KACtB,OAAO,CAAC,YAAY,CAAC,CAAA;SAC3B,CAAA;KACF,CAAA;IACD,QAAQ,EAAE,MAAM,CAAA;IAChB,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,MAAM,EAAE,MAAM,CAAA;IACd,QAAQ,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAA;CACrC;;;;;;;;;;;;EA8LA,CAAA"}
@@ -0,0 +1,184 @@
1
+ import { createHash, randomUUID } from 'node:crypto';
2
+ import { createWriteStream } from 'node:fs';
3
+ import { mkdir, readdir, rename, unlink, writeFile } from 'node:fs/promises';
4
+ import { join, resolve } from 'node:path';
5
+ import { Readable, Transform } from 'node:stream';
6
+ import { pipeline } from 'node:stream/promises';
7
+ const html = (value) => value.replace(/[&<>"']/g, character => ({ '&': '&amp;', '<': '&lt;', '>': '&gt;', '"': '&quot;', "'": '&#39;' })[character]);
8
+ const markdown = (value) => value.replace(/[\\`*_{}\[\]()#+.!|<>-]/g, '\\$&').replace(/\r?\n/g, ' ');
9
+ /** Signed file URLs are used without API credentials and never written into the bundle. */
10
+ export const downloadCanvas = async (input) => {
11
+ const outDir = resolve(input.outDir);
12
+ await mkdir(outDir, { recursive: true, mode: 0o700 });
13
+ if ((await readdir(outDir)).length)
14
+ throw new Error('Canvas download requires an empty output directory');
15
+ const exported = await input.client.v2.exportCanvas(input.canvasId, {
16
+ mesh: input.mesh,
17
+ });
18
+ if (exported.schemaVersion !== 'assethub.canvas-export.v1' ||
19
+ exported.canvas.id !== input.canvasId)
20
+ throw new Error('Invalid canvas export response');
21
+ await mkdir(join(outDir, 'files'), { mode: 0o700 });
22
+ const files = [];
23
+ for (const [index, asset] of exported.assets.entries()) {
24
+ const { url, ...safeAsset } = asset;
25
+ const file = { ...safeAsset };
26
+ files.push(file);
27
+ input.progress?.(`Downloading ${index + 1}/${exported.assets.length}`);
28
+ const temporary = join(outDir, 'files', `.${randomUUID()}.tmp`);
29
+ try {
30
+ if (!url)
31
+ throw new Error('No downloadable file URL is available');
32
+ const parsed = new URL(url);
33
+ if (!['http:', 'https:'].includes(parsed.protocol) ||
34
+ parsed.username ||
35
+ parsed.password)
36
+ throw new Error('Invalid download URL');
37
+ const response = await fetch(url, {
38
+ signal: AbortSignal.timeout(120_000),
39
+ redirect: 'error',
40
+ });
41
+ if (!response.ok)
42
+ throw new Error(`HTTP ${response.status}`);
43
+ if (!response.body)
44
+ throw new Error('Empty file response');
45
+ const contentType = response.headers
46
+ .get('content-type')
47
+ ?.split(';')[0]
48
+ ?.trim();
49
+ const imageTypes = {
50
+ 'image/png': 'png',
51
+ 'image/jpeg': 'jpg',
52
+ 'image/webp': 'webp',
53
+ 'image/gif': 'gif',
54
+ 'image/avif': 'avif',
55
+ };
56
+ let extension;
57
+ if (asset.mediaType === 'image') {
58
+ const ext = contentType && imageTypes[contentType];
59
+ if (!ext)
60
+ throw new Error('Expected a raster image file');
61
+ extension = ext;
62
+ }
63
+ else {
64
+ if (contentType === 'text/html' || contentType === 'image/svg+xml')
65
+ throw new Error('Expected a mesh file');
66
+ extension = ['glb', 'gltf', 'fbx', 'obj', 'stl', 'ply', 'zip'].includes(asset.format ?? '')
67
+ ? asset.format
68
+ : 'glb';
69
+ }
70
+ const stem = asset.name
71
+ .replace(/[^a-zA-Z0-9_-]+/g, '-')
72
+ .replace(/^-+|-+$/g, '')
73
+ .slice(0, 50) || asset.mediaType;
74
+ const name = `${String(index + 1).padStart(3, '0')}-${stem}-${createHash('sha256').update(asset.id).digest('hex').slice(0, 10)}.${extension}`;
75
+ const hash = createHash('sha256');
76
+ let bytes = 0;
77
+ const meter = new Transform({
78
+ transform(chunk, _encoding, callback) {
79
+ bytes += chunk.length;
80
+ if (bytes > 1024 * 1024 * 1024)
81
+ return callback(new Error('File exceeds 1 GiB'));
82
+ hash.update(chunk);
83
+ callback(null, chunk);
84
+ },
85
+ });
86
+ await pipeline(Readable.fromWeb(response.body), meter, createWriteStream(temporary, { flags: 'wx', mode: 0o600 }));
87
+ if (bytes === 0)
88
+ throw new Error('Empty file response');
89
+ await rename(temporary, join(outDir, 'files', name));
90
+ Object.assign(file, {
91
+ path: `files/${name}`,
92
+ bytes,
93
+ sha256: hash.digest('hex'),
94
+ });
95
+ }
96
+ catch (error) {
97
+ // Network errors may contain signed URLs. Only our bounded known messages
98
+ // are retained, never provider error bodies or raw fetch exceptions.
99
+ const message = error instanceof Error ? error.message : '';
100
+ file.error =
101
+ /^(HTTP \d{3}|No downloadable file URL is available|Invalid download URL|Empty file response|Expected a raster image file|Expected a mesh file|File exceeds 1 GiB)$/.test(message)
102
+ ? message
103
+ : 'File download failed';
104
+ }
105
+ finally {
106
+ await unlink(temporary).catch(error => {
107
+ if (error.code !== 'ENOENT')
108
+ throw error;
109
+ });
110
+ }
111
+ }
112
+ const byId = new Map(files.map(file => [file.id, file]));
113
+ const showAsset = (id) => {
114
+ const file = byId.get(id);
115
+ return file?.path
116
+ ? `<a href="${html(file.path)}">${html(file.name)}</a>`
117
+ : html(file?.name ?? id);
118
+ };
119
+ const warnings = [
120
+ ...exported.warnings,
121
+ ...(exported.truncated
122
+ ? ['The export was truncated; some assets or history are missing.']
123
+ : []),
124
+ ];
125
+ const manifest = { ...exported, assets: files, warnings };
126
+ const sections = exported.steps
127
+ .map(step => `<section><h2>${html(step.operation)}</h2><p>${html([step.createdAt, step.model, step.source].filter(Boolean).join(' · '))}</p>${step.prompt ? `<pre>${html(step.prompt)}</pre>` : ''}<p>Inputs: ${step.inputs.map(ref => `${showAsset(ref.id)} (${html(ref.role)}; ${html(ref.evidence)})`).join(', ') || 'No recorded inputs'}</p><p>Outputs: ${step.outputs.map(showAsset).join(', ') || 'History step'}</p>${step.warnings.map(warning => `<p>${html(warning)}</p>`).join('')}</section>`)
128
+ .join('');
129
+ const document = `<!doctype html><html lang="en"><meta charset="utf-8"><meta name="viewport" content="width=device-width"><meta http-equiv="Content-Security-Policy" content="default-src 'none'; img-src 'self'; style-src 'unsafe-inline'; base-uri 'none'; form-action 'none'"><title>${html(exported.canvas.name)}</title><style>body{font:16px system-ui;max-width:1000px;margin:32px auto;padding:0 20px;color:#202126}a{color:#2455ac}pre{white-space:pre-wrap;overflow-wrap:anywhere}section{border-top:1px solid #ccc;padding:16px 0}.images{display:grid;grid-template-columns:repeat(auto-fit,minmax(220px,1fr));gap:20px}img{width:100%;height:220px;object-fit:contain}figure{margin:0}figcaption{overflow-wrap:anywhere}</style><h1>${html(exported.canvas.name)}</h1><p>Canvas ${exported.canvas.id}. Actual generation inputs and available recorded history. Canvas connections are not evidence of generation inputs.</p>${warnings.map(warning => `<p>${html(warning)}</p>`).join('')}<h2>Files</h2><div class="images">${files.map(file => `<figure>${file.mediaType === 'image' && file.path ? `<img loading="lazy" src="${html(file.path)}" alt="${html(file.name)}">` : ''}<figcaption>${showAsset(file.id)} · ${html(file.role)}${file.error ? ` · ${html(file.error)}` : ''}</figcaption></figure>`).join('')}</div><h2>History</h2>${sections}</html>`;
130
+ const mdAsset = (id) => {
131
+ const file = byId.get(id);
132
+ return file?.path
133
+ ? `[${markdown(file.name)}](${file.path})`
134
+ : markdown(file?.name ?? id);
135
+ };
136
+ const history = [
137
+ `# ${markdown(exported.canvas.name)}`,
138
+ '',
139
+ `Canvas ${exported.canvas.id}. Actual generation inputs and available history; canvas connections are not generation evidence.`,
140
+ '',
141
+ ...warnings.map(warning => `- ${markdown(warning)}`),
142
+ '',
143
+ '## Files',
144
+ '',
145
+ ...files.map(file => `- ${mdAsset(file.id)} (${file.role})${file.error ? `: ${markdown(file.error)}` : ''}`),
146
+ '',
147
+ ...exported.steps.flatMap(step => [
148
+ `## ${markdown(step.operation)}`,
149
+ '',
150
+ markdown([step.createdAt, step.model, step.source].filter(Boolean).join(' · ')),
151
+ '',
152
+ ...(step.prompt ? [`Prompt: ${markdown(step.prompt)}`, ''] : []),
153
+ `Inputs: ${step.inputs.map(ref => `${mdAsset(ref.id)} (${markdown(ref.role)}; ${markdown(ref.evidence)})`).join(', ') || 'No recorded inputs'}`,
154
+ '',
155
+ `Outputs: ${step.outputs.map(mdAsset).join(', ') || 'History step'}`,
156
+ '',
157
+ ...step.warnings.map(warning => `- ${markdown(warning)}`),
158
+ '',
159
+ ]),
160
+ ].join('\n');
161
+ await writeFile(join(outDir, 'manifest.json'), JSON.stringify(manifest, null, 2) + '\n', { mode: 0o600, flag: 'wx' });
162
+ await writeFile(join(outDir, 'index.html'), document, {
163
+ mode: 0o600,
164
+ flag: 'wx',
165
+ });
166
+ await writeFile(join(outDir, 'history.md'), history, {
167
+ mode: 0o600,
168
+ flag: 'wx',
169
+ });
170
+ const failed = files.filter(file => file.error).length;
171
+ return {
172
+ outDir,
173
+ manifestPath: join(outDir, 'manifest.json'),
174
+ htmlPath: join(outDir, 'index.html'),
175
+ historyPath: join(outDir, 'history.md'),
176
+ downloaded: files.length - failed,
177
+ failed,
178
+ steps: exported.steps.length,
179
+ warnings,
180
+ missingEvidence: exported.steps.flatMap(step => step.warnings),
181
+ truncated: exported.truncated,
182
+ exitCode: failed ? 1 : exported.truncated ? 3 : 0,
183
+ };
184
+ };
package/dist/index.d.ts CHANGED
@@ -2,7 +2,7 @@
2
2
  import { type AnimationRetargetRequest, type Intervention, type RigRequest } from '@assethub/api-client';
3
3
  import { buildRunUploadPlan } from './runsUpload/buildRunUpload.js';
4
4
  type Flags = Record<string, string | boolean | string[]>;
5
- 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|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 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 composer models\n assethub composer refine --list-modes\n assethub composer refine --from-run <run-id> --instruction <text> [--mode standard|thorough|placement|workshop|blender] [--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 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 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>] [--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>] [--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 --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";
5
+ 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|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 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 composer models\n assethub composer refine --list-modes\n assethub composer refine --from-run <run-id> --instruction <text> [--mode standard|thorough|placement|workshop|blender] [--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 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 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>] [--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>] [--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 --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";
6
6
  /**
7
7
  * The `animate retarget` request, built from flags alone.
8
8
  *
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAsBA,OAAO,EAIL,KAAK,wBAAwB,EAO7B,KAAK,YAAY,EAEjB,KAAK,UAAU,EAgBhB,MAAM,sBAAsB,CAAA;AAa7B,OAAO,EAAC,kBAAkB,EAAc,MAAM,gCAAgC,CAAA;AAI9E,KAAK,KAAK,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,GAAG,MAAM,EAAE,CAAC,CAAA;AAoIxD,eAAO,MAAM,KAAK,4zZA4HjB,CAAA;AAq1ED;;;;;;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;AAmqCD,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":";AAuBA,OAAO,EAIL,KAAK,wBAAwB,EAO7B,KAAK,YAAY,EAEjB,KAAK,UAAU,EAgBhB,MAAM,sBAAsB,CAAA;AAa7B,OAAO,EAAC,kBAAkB,EAAc,MAAM,gCAAgC,CAAA;AAI9E,KAAK,KAAK,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,GAAG,MAAM,EAAE,CAAC,CAAA;AA4IxD,eAAO,MAAM,KAAK,q5ZA6HjB,CAAA;AAq1ED;;;;;;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;AAyrCD,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
@@ -2,6 +2,7 @@
2
2
  import { setTimeout as delay } from 'node:timers/promises';
3
3
  import { cliVersion, diagnose, mcpConfig } from './setup.js';
4
4
  import { ingestProjectSources } from './projectSources.js';
5
+ import { downloadCanvas } from './canvasDownload.js';
5
6
  import { writeCanvasComparison } from './canvasComparison.js';
6
7
  import { importCanvasAssetWithState } from './canvasAssetImport.js';
7
8
  import { execFile, spawn } from 'node:child_process';
@@ -28,7 +29,11 @@ const defaultImageModelId = 'imageGen.nanoBanana2.openrouter';
28
29
  const defaultMeshModelId = 'meshGen.hunyuan31';
29
30
  const defaultProfileName = 'default';
30
31
  const defaultPartExtractorName = 'V1.5';
31
- const isArtifactGraphPartExtractor = (value) => value === 'ah_agent_graph_v3_6_1' || value === 'ah_agent_graph_v3_6_3';
32
+ const artifactGraphPartExtractorApiValues = new Set([
33
+ 'ah_agent_graph_v3_6_1',
34
+ 'ah_agent_graph_v3_6_3',
35
+ 'ah_agent_graph_v3_6_4',
36
+ ]);
32
37
  const partExtractorOptions = [
33
38
  {
34
39
  publicName: 'V1.5',
@@ -51,9 +56,14 @@ const partExtractorOptions = [
51
56
  aliases: ['v3.6.1', '3.6.1', 'v3.6.1 primary images first'],
52
57
  },
53
58
  {
54
- publicName: 'V3.6.3',
59
+ publicName: 'V3.6.3 Fast Analysis',
55
60
  apiValue: 'ah_agent_graph_v3_6_3',
56
- aliases: ['v3.6.3', '3.6.3', 'v3.6.3 fast analysis'],
61
+ aliases: ['v3.6.3', '3.6.3'],
62
+ },
63
+ {
64
+ publicName: 'V3.6.4 Fast Analysis',
65
+ apiValue: 'ah_agent_graph_v3_6_4',
66
+ aliases: ['v3.6.4', '3.6.4'],
57
67
  },
58
68
  ];
59
69
  const partExtractorPublicNames = partExtractorOptions
@@ -94,6 +104,7 @@ Usage:
94
104
  assethub workspace context get --internal --org <uuid> --actor <uuid> --canvas <id> [--out <json>] [--order <uuid>]
95
105
  assethub project ingest <source-dir> --out-dir <directory> [--exclude-dir <relative-path>...]
96
106
  assethub language text|vision --input-json @<json> --operation-id <uuid> [--out <json>]
107
+ assethub canvas download --canvas <id> --out-dir <directory> [--mesh <mesh_asset_id>]
97
108
  assethub canvas import --canvas <id> --file <image> [--name <name>]
98
109
  assethub canvas context get --canvas <id> [--out <json>]
99
110
  assethub canvas context put --canvas <id> --file <json> [--if-version <n>]
@@ -2751,7 +2762,7 @@ const isArtifactGraphPartSplit = (value, execution) => (value != null &&
2751
2762
  typeof value === 'object' &&
2752
2763
  'engine' in value &&
2753
2764
  value.engine === 'artifact-graph') ||
2754
- isArtifactGraphPartExtractor(execution.resolvedInput?.agentVersion);
2765
+ artifactGraphPartExtractorApiValues.has(String(execution.resolvedInput?.agentVersion));
2755
2766
  const commandParts = async (subcommand, ctx) => {
2756
2767
  const runPartSplit = async (source, operationId = getFlag(ctx.flags, 'operation-id') ?? randomUUID()) => {
2757
2768
  let orderId = source == null ? getFlag(ctx.flags, 'order-id') : undefined;
@@ -2762,14 +2773,15 @@ const commandParts = async (subcommand, ctx) => {
2762
2773
  const requestedAgentVersion = orderId == null || partExtractorFlag != null
2763
2774
  ? resolvePartExtractorApiValue(partExtractorFlag ?? defaultPartExtractorName)
2764
2775
  : undefined;
2765
- if (isArtifactGraphPartExtractor(requestedAgentVersion)) {
2766
- const name = partExtractorPublicNameByApiValue.get(requestedAgentVersion);
2776
+ if (requestedAgentVersion != null &&
2777
+ artifactGraphPartExtractorApiValues.has(requestedAgentVersion)) {
2778
+ const publicName = publicPartExtractorName(requestedAgentVersion);
2767
2779
  for (const flag of ['task-id', 'mission-id', 'part-extraction-mode']) {
2768
2780
  if (hasFlag(ctx.flags, flag))
2769
- throw new Error(`--${flag} is not supported with ${name}`);
2781
+ throw new Error(`--${flag} is not supported with ${publicName}`);
2770
2782
  }
2771
2783
  if (orderId != null)
2772
- throw new Error(`--order-id is not supported with ${name}; use runs resume <operation-id> to resume a graph split`);
2784
+ throw new Error(`--order-id is not supported with ${publicName}; use runs resume <operation-id> to resume a graph split`);
2773
2785
  }
2774
2786
  const session = await productionSession(ctx, orderId == null ? 'production.analyze' : 'production.execute');
2775
2787
  let execution;
@@ -3013,6 +3025,23 @@ const canvasForRead = (ctx) => openExecutionSession({
3013
3025
  create: false,
3014
3026
  });
3015
3027
  const commandCanvas = async (subcommand, positionals, ctx) => {
3028
+ if (subcommand === 'download') {
3029
+ const outDir = requireFlag(ctx.flags, 'out-dir');
3030
+ const { canvas } = await canvasForRead(ctx);
3031
+ const mesh = getFlag(ctx.flags, 'mesh');
3032
+ if (mesh && !/^mesh_[1-9]\d*$/.test(mesh))
3033
+ throw new Error('--mesh must be a mesh_<id> asset ID');
3034
+ const result = await downloadCanvas({
3035
+ client: ctx.client,
3036
+ canvasId: canvas.id,
3037
+ mesh,
3038
+ outDir,
3039
+ progress: message => process.stderr.write(`${message}\n`),
3040
+ });
3041
+ print(result);
3042
+ process.exitCode = result.exitCode;
3043
+ return;
3044
+ }
3016
3045
  if (subcommand === 'context' ||
3017
3046
  subcommand === 'import' ||
3018
3047
  subcommand === 'compare' ||
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@assethub/cli",
3
- "version": "0.1.16",
3
+ "version": "0.1.18",
4
4
  "description": "Command line interface for AssetHub.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -30,7 +30,7 @@
30
30
  "access": "public"
31
31
  },
32
32
  "dependencies": {
33
- "@assethub/api-client": "^0.1.8",
33
+ "@assethub/api-client": "^0.1.9",
34
34
  "@modelcontextprotocol/sdk": "^1.30.0"
35
35
  },
36
36
  "repository": {