@assethub/cli 0.1.30 → 0.1.32

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.
Files changed (70) hide show
  1. package/README.md +282 -8
  2. package/dist/appEnv.d.ts +20 -0
  3. package/dist/appEnv.d.ts.map +1 -0
  4. package/dist/appEnv.js +62 -0
  5. package/dist/canvasGraphDownload.d.ts +11 -0
  6. package/dist/canvasGraphDownload.d.ts.map +1 -0
  7. package/dist/canvasGraphDownload.js +108 -0
  8. package/dist/execution.d.ts +5 -2
  9. package/dist/execution.d.ts.map +1 -1
  10. package/dist/execution.js +11 -12
  11. package/dist/hooks/command.d.ts +14 -0
  12. package/dist/hooks/command.d.ts.map +1 -0
  13. package/dist/hooks/command.js +181 -0
  14. package/dist/hooks/graph.d.ts +40 -0
  15. package/dist/hooks/graph.d.ts.map +1 -0
  16. package/dist/hooks/graph.js +269 -0
  17. package/dist/hooks/index.d.ts +7 -0
  18. package/dist/hooks/index.d.ts.map +1 -0
  19. package/dist/hooks/index.js +6 -0
  20. package/dist/hooks/install.d.ts +58 -0
  21. package/dist/hooks/install.d.ts.map +1 -0
  22. package/dist/hooks/install.js +286 -0
  23. package/dist/hooks/paths.d.ts +31 -0
  24. package/dist/hooks/paths.d.ts.map +1 -0
  25. package/dist/hooks/paths.js +101 -0
  26. package/dist/hooks/redact.d.ts +5 -0
  27. package/dist/hooks/redact.d.ts.map +1 -0
  28. package/dist/hooks/redact.js +67 -0
  29. package/dist/hooks/save.d.ts +62 -0
  30. package/dist/hooks/save.d.ts.map +1 -0
  31. package/dist/hooks/save.js +331 -0
  32. package/dist/hooks/transcript.d.ts +23 -0
  33. package/dist/hooks/transcript.d.ts.map +1 -0
  34. package/dist/hooks/transcript.js +78 -0
  35. package/dist/hooks/trim.d.ts +25 -0
  36. package/dist/hooks/trim.d.ts.map +1 -0
  37. package/dist/hooks/trim.js +220 -0
  38. package/dist/hooks/types.d.ts +56 -0
  39. package/dist/hooks/types.d.ts.map +1 -0
  40. package/dist/hooks/types.js +0 -0
  41. package/dist/hooks/upload.d.ts +52 -0
  42. package/dist/hooks/upload.d.ts.map +1 -0
  43. package/dist/hooks/upload.js +252 -0
  44. package/dist/index.d.ts +12 -2
  45. package/dist/index.d.ts.map +1 -1
  46. package/dist/index.js +1569 -165
  47. package/dist/nodeMeshBatch.d.ts.map +1 -1
  48. package/dist/nodeMeshBatch.js +5 -4
  49. package/dist/productionBatch.d.ts +77 -0
  50. package/dist/productionBatch.d.ts.map +1 -0
  51. package/dist/productionBatch.js +204 -0
  52. package/dist/runProgress.d.ts +4 -0
  53. package/dist/runProgress.d.ts.map +1 -0
  54. package/dist/runProgress.js +16 -0
  55. package/dist/runsUpload/controlEndpoints.d.ts +1 -1
  56. package/dist/runsUpload/controlEndpoints.d.ts.map +1 -1
  57. package/dist/runsUpload/controlEndpoints.js +4 -2
  58. package/dist/runsUpload/uploadRun.d.ts +7 -1
  59. package/dist/runsUpload/uploadRun.d.ts.map +1 -1
  60. package/dist/runsUpload/uploadRun.js +7 -4
  61. package/dist/setupCommand.d.ts +130 -0
  62. package/dist/setupCommand.d.ts.map +1 -0
  63. package/dist/setupCommand.js +569 -0
  64. package/dist/setupHooksBridge.d.ts +12 -0
  65. package/dist/setupHooksBridge.d.ts.map +1 -0
  66. package/dist/setupHooksBridge.js +4 -0
  67. package/dist/update.d.ts +74 -0
  68. package/dist/update.d.ts.map +1 -0
  69. package/dist/update.js +205 -0
  70. package/package.json +2 -2
package/README.md CHANGED
@@ -2,6 +2,35 @@
2
2
 
3
3
  Command line interface for AssetHub.
4
4
 
5
+ ## Quick setup
6
+
7
+ Connect Claude Code and Codex to AssetHub in one step:
8
+
9
+ ```sh
10
+ assethub setup # prompts for your API key and workspace
11
+ printf '%s' "$KEY" | assethub setup --api-key-stdin --workspace <id> --yes
12
+ assethub setup --dry-run # show every command and file change, change nothing
13
+ ```
14
+
15
+ Setup logs in (reusing a saved key), selects a workspace, registers the
16
+ `assethub` MCP server in Claude Code (`claude mcp add-json ... --scope user`, run
17
+ again safely), merges an `[mcp_servers.assethub]` section into
18
+ `$CODEX_HOME/config.toml` (default `~/.codex`, original saved as
19
+ `config.toml.bak-<timestamp>`), then runs `doctor --mcp` and prints a checklist
20
+ (`--json` for machine output). Use `--client claude|codex|both` to limit the
21
+ targets.
22
+
23
+ MCP does not need the CLI. Setup is only a shortcut: both clients call the hosted
24
+ `/api/mcp` server directly and read the key from the `ASSETHUB_API_KEY`
25
+ environment variable. The Claude Code entry is
26
+ `claude mcp add-json assethub '{"type":"http","url":"https://app.assethub.io/api/mcp","headers":{"Authorization":"Bearer ${ASSETHUB_API_KEY}","X-AssetHub-Workspace":"<id>"}}' --scope user`,
27
+ so the key is never written to Claude Code's config or passed on a command line,
28
+ and removing the CLI does not disconnect MCP. Codex uses `bearer_token_env_var`.
29
+ Setup never writes the key to a shell profile; run `assethub setup --print-env` to
30
+ print the `export ASSETHUB_API_KEY=...` line, and export it in the shell that
31
+ starts Claude Code or Codex. The key is redacted
32
+ (`ah_…last4`) everywhere else.
33
+
5
34
  ## API discovery and Workspace Skills
6
35
 
7
36
  Use `api search [query]` to discover the authenticated server catalog and
@@ -27,6 +56,56 @@ are required together; `--context` also selects the execution canvas and must
27
56
  match `--canvas` when supplied. Stale revisions and unsupported engines fail
28
57
  before generation. Guidance does not expand the model's supported part boundaries.
29
58
 
59
+ Body-aware graph runs accept `--base-body <mesh-asset-id>`. The server verifies
60
+ that the GLB belongs to the selected workspace, renders front/oblique/side/back
61
+ references from that exact mesh, and supplies them to preparation and splitting:
62
+
63
+ ```sh
64
+ assethub parts split --source-id "$IMAGE_ASSET_ID" --canvas "$CANVAS_ID" \
65
+ --part-extractor 'V3.0.7 Artist Skills' --base-body mesh_42 \
66
+ --skill-mode auto --auto-repair true \
67
+ --skill-planner-model openai/gpt-5.6-luna --wait
68
+ ```
69
+
70
+ `--skill-planner-model` changes only workspace Skill selection for that run.
71
+ Allowed models are `openai/gpt-5.6-sol`, `openai/gpt-5.6-luna`, and
72
+ `anthropic/claude-opus-5.5`; omitting it keeps the current SOL default.
73
+
74
+ Character assembly Alpha is an explicit option on the existing graph entry:
75
+
76
+ ```sh
77
+ assethub production analyze --source-id <owned-image> --canvas <id> \
78
+ --part-extractor 'V3.0.9 Garment Boundaries' --pipeline-depth composition \
79
+ --assembly-policy concept-to-character-v1 \
80
+ --mesh-generation-json '{"modelId":"meshGen.tripo_p2_preview","faceLimit":10000,"params":{"quad":true,"texture":true,"pbr":true,"textureQuality":"standard"}}' \
81
+ --operation-id <uuid>
82
+ ```
83
+
84
+ It selects the existing Quick assembly (V3) composer, which returns measured part
85
+ pivots for the native review handoff. Explicit incompatible composer selections
86
+ are rejected before dispatch; omitted policy preserves existing defaults.
87
+ It requires existing Internal graph access and Composer body-first/background
88
+ capabilities; a Max plan alone does not grant graph access. The selected policy
89
+ is stored with the graph. Existing production and mesh charges apply. Outputs
90
+ are reviewable candidates, not approved characters; detailed finishing remains
91
+ an explicit follow-up. This option does not add a finishing fee or authorize
92
+ paid regeneration. Omit it to preserve the existing production flow. Reuse the
93
+ same operation ID after an uncertain response rather than starting another run.
94
+
95
+ `--mesh-generation-json` supplies one explicit graph mesh provider and its options.
96
+ The server applies the existing strict `mesh.generate` model contract before any
97
+ graph credit hold; graph-unsupported options are rejected, never silently substituted.
98
+ P2 Quad has a maximum faceLimit of 25000. Graph settings do not support
99
+ `isLowPoly`, `generateParts`, `ultraMode`, `outputQuality`, or `poseMode`.
100
+ The selected settings are frozen for first generation and retries. Omit the
101
+ option to preserve the legacy provider defaults. P2 Quad retains original FBX;
102
+ the composed GLB is a triangulated preview, not proof of Quad topology.
103
+
104
+ There is no aggregate credit cap on this graph operation. The production fee,
105
+ each part's mesh generation and composition use their existing billing. Choose
106
+ `--pipeline-depth parts` without `--assembly-policy` to inspect parts before
107
+ authorizing mesh generation. The new settings do not bypass that stopping point.
108
+
30
109
  ## Personal API keys
31
110
 
32
111
  Log in once with a personal key, then select its workspace:
@@ -111,6 +190,28 @@ explicit overrides. `auth logout` removes the selected saved profile (or the
111
190
  saved default); environment credentials remain under your shell’s control.
112
191
  Diagnostics omit API keys and raw server error bodies.
113
192
 
193
+ ## Updating the CLI
194
+
195
+ ```sh
196
+ assethub update --check # report the latest published version; installs nothing
197
+ assethub update --dry-run # print the install command it would run
198
+ assethub update # install the latest version (asks first in a terminal)
199
+ assethub update --yes # install without asking
200
+ ```
201
+
202
+ `update` reads the latest `@assethub/cli` version with `npm view` (so your
203
+ `.npmrc` registry, auth token and proxy apply; it reads the registry directly
204
+ only when npm is unavailable), finds which package manager installed the
205
+ running CLI globally (npm, pnpm, yarn, bun or Volta), and runs that manager's
206
+ global install pinned to the exact version. Your saved login in
207
+ `~/.assethub/config.json` lives outside the package and is never touched, so you
208
+ do not log in again. Afterwards it runs the updated `assethub doctor` with the
209
+ same `--profile`/`--config` and reports `auth` as `pass`, `fail`, or
210
+ `not_configured`; it fails if the `assethub` on your PATH still reports the old
211
+ version. It never downgrades. A CLI run through `npx`, installed as a project
212
+ dependency, or built from a source checkout is not updated in place; the error
213
+ says what to do instead.
214
+
114
215
  ## Historical meshes and artifact graphs
115
216
 
116
217
  Lists are scoped to the selected workspace, including assets created in the UI. Mesh search
@@ -248,23 +349,104 @@ Existing parts commands use the same canvas and durable operation storage:
248
349
  assethub parts split --source-id "$IMAGE_ASSET_ID" --canvas "$CANVAS_ID" --part-extractor V1.5 --wait
249
350
  # Select only the parts to execute; --all-ready selects all ready tasks.
250
351
  assethub parts split --source-id "$IMAGE_ASSET_ID" --canvas "$CANVAS_ID" --part-extractor V1.5 --all-ready --wait
251
- # Internal graph versions run the complete split through one analyze receipt.
352
+ # Graph versions run the complete split through one analyze receipt.
252
353
  assethub production agents
253
354
  assethub parts split --source-id "$IMAGE_ASSET_ID" --canvas "$CANVAS_ID" --part-extractor V3.6.1 --all-ready --wait
254
- # CLI 0.1.20+: existing Internal V3.6.5 and Pluffy models; check server availability first.
355
+ # CLI 0.1.20+: V3.6.5 and Pluffy models; check server availability first.
255
356
  assethub parts split --source-id "$IMAGE_ASSET_ID" --canvas "$CANVAS_ID" --part-extractor V3.6.5 --all-ready --wait
256
357
  assethub production analyze --source-id "$IMAGE_ASSET_ID" --canvas "$CANVAS_ID" --part-extractor pluffy --wait
257
358
  assethub production automation --canvas "$CANVAS_ID" --input-json @batch.json --wait
258
359
  ```
259
360
 
361
+ ### V4 Character Assembly: image to assembled 3D character
362
+
363
+ One command runs the whole pipeline (parts, meshes, Blender assembly and review) and
364
+ saves the assembled character GLB:
365
+
366
+ ```sh
367
+ assethub production analyze --file ./concept.png --part-extractor v4 \
368
+ --name "My character" --canvas "$CANVAS_ID" --wait --download --out-dir ./character
369
+ ```
370
+
371
+ A run takes about an hour, so `--wait` defaults to a 2 hour limit for V4
372
+ (override with `--timeout-ms`). The run finishes `completed` when the assembly
373
+ passes review, and `needs_review` (exit code 3) when it stops with the best
374
+ assembly it made; both return that assembly as a mesh output. `failed` means no
375
+ assembly was made. Follow a run started without `--wait` with
376
+ `runs watch <run-id> --timeout-ms 7200000`.
377
+
378
+ While a V4 run works, `--wait`, `runs watch` and `runs get` show where it is.
379
+ The receipt's `progress` field has the phase, a one-line summary, each part's
380
+ state and the Blender assembly rounds, in the words of the canvas Part Composer
381
+ card. `--wait` and `runs watch` print a stderr line only when it changes:
382
+
383
+ ```text
384
+ [run] 557d2a58-… running · Step 3 of 4 · Making the parts · 3 of 9 meshes ready · 4 redoing, 2 checking
385
+ ```
386
+
387
+ ```sh
388
+ assethub runs watch <run-id> --timeout-ms 7200000 --download --out-dir ./character
389
+ assethub runs get <run-id> # JSON receipt, progress included
390
+ assethub runs get <run-id> --download --out-dir ./character # save the assembled GLB
391
+ ```
392
+
393
+ A finished run keeps its `progress`. A failed one also carries
394
+ `error.code: CHARACTER_ASSEMBLY_NOT_ACCEPTED` with the reason it stopped.
395
+
396
+ Pick a stopped run back up (no new charge) with its run ID; `--wait`
397
+ follows the same run until the resumed attempt finishes:
398
+
399
+ ```sh
400
+ assethub production resume <run-id> --wait --download --out-dir ./character
401
+ ```
402
+
403
+ `runs get <run-id>` then reads it as `running` again, and its result is replaced
404
+ by the resumed run's own when it finishes. An order ID still works without
405
+ `--wait`. The API
406
+ contract is in `docs/api-character-assembly-progress.md`.
407
+
408
+ ### Batch runs: many images, or one image many times
409
+
410
+ `production batch` starts one `production analyze` per image, and per `--repeat`,
411
+ with the same agent and options on one canvas. Use it to run V4 over several
412
+ concepts, or to repeat one concept and compare how consistent the results are:
413
+
414
+ ```sh
415
+ assethub production batch --file ./harpy.png --file ./satyr.png --repeat 2 \
416
+ --part-extractor v4 --yes --wait --concurrency 2 --download --out-dir ./batch
417
+ assethub production batch --files-dir ./concepts --part-extractor v4 --yes
418
+ ```
419
+
420
+ - Images: `--file` (repeatable), `--files-dir` (its .png/.jpg/.jpeg/.webp files by
421
+ name), `--source-id` and `--source-url` (repeatable). At most 20 runs per batch.
422
+ - More than one run needs `--yes`: each one is a paid run (V4 takes about an hour).
423
+ - Without `--canvas`, the batch gets one new canvas. Orders are named
424
+ `<--name> <image> #<repeat>`.
425
+ - Every other `production analyze` option applies to each run.
426
+ - The command prints the batch `--operation-id` first. Rerun the same command
427
+ with it to resume: started runs are read back, not started or charged again,
428
+ and different inputs under that ID are refused.
429
+ - When the workspace is at its active agent-run limit, an image is `deferred`,
430
+ not failed. With `--wait`, it is started once one of the batch's runs finishes.
431
+ Without `--wait`, rerun the command later to start it.
432
+ - `--wait` keeps at most `--concurrency` (default 2) of the batch's runs going.
433
+ It prints a stderr line per change and saves each run's outputs under
434
+ `<out-dir>/<image>/run-<repeat>/`.
435
+
436
+ The JSON output lists every item with its `status` (`dispatched`, `deferred`,
437
+ `failed`, `pending`, or the finished run's status), `runId` and receipt. Exit
438
+ code 0 means every run started (or, with `--wait`, completed). 3 means some
439
+ are deferred, pending or `needs_review`. 1 means one failed. MCP clients get the
440
+ same behaviour from the `production_analyze_batch` tool.
441
+
260
442
  `parts split` keeps separate analysis and selected-part execution phases. Each phase
261
443
  has its own saved operation ID, with the execution linked to the analysis run.
262
- For Internal `V3.6.1` (`V3.6.1 Primary Images First`), `V3.6.3`
444
+ For `V3.6.1` (`V3.6.1 Primary Images First`), `V3.6.3`
263
445
  (`V3.6.3 Fast Analysis`, CLI 0.1.16+), `V3.6.4`
264
446
  (`V3.6.4 Fast Analysis`, CLI 0.1.17+), `V3.6.5 Primary Images` and
265
447
  `Chibi Character (Pluffy) v3.1` (both CLI 0.1.20+), `V3.7 Artist Skills`,
266
448
  `V3.7.1 Building Modules` (both CLI 0.1.23+/0.1.24+), `V3.0.9 Garment
267
- Boundaries`, and `Humanoid Assembly (internal)` (both CLI 0.1.26+), analysis
449
+ Boundaries`, and `Humanoid Assembly` (both CLI 0.1.26+), analysis
268
450
  runs the complete Artifact Graph split. `--all-ready` waits for that one receipt and does not start a
269
451
  second production execution. Resume an interrupted graph split with
270
452
  `runs resume <operation-id>`; `--task-id`, `--mission-id`,
@@ -354,6 +536,79 @@ truncated exports require `--allow-truncated`. Other commands, including product
354
536
  retain their existing API behavior and do not yet create these receipts.
355
537
  `autopilot --demo` is an experimental demo requiring the AssetHub monorepo and its unpublished development dependency `@assethub/autopilot-core`. Standalone project workflow commands do not require or install it. Autonomous budgeted improvement is a later stage.
356
538
 
539
+ ## Trajectory memory
540
+
541
+ Internal-only. `memorize` captures a canvas as a reusable recipe; `replay`
542
+ re-runs a memory's recipe onto a new image.
543
+
544
+ ```sh
545
+ # Whole canvas, or just the shapes you name (max 256 tldraw shape ids).
546
+ assethub memory memorize --canvas "$CANVAS_ID" --wait
547
+ assethub memory memorize --canvas "$CANVAS_ID" --nodes shape:a,shape:b --wait
548
+
549
+ # Replay one memory onto a registered asset.
550
+ assethub memory replay "<graphId>:<nodeId>" --source ast_x --wait
551
+ ```
552
+
553
+ `--source` must be an asset your workspace owns — an `outputs[].assetId` from an
554
+ earlier job, or a generation `resourceId`. A `url` is refused with 400
555
+ `UNSUPPORTED_SOURCE`, because a replay needs a registered image rather than a
556
+ link; bring a remote one in with `files import` first.
557
+
558
+ `memorize` reserves credit for up to 100 trajectory summaries and settles the
559
+ number actually indexed. If a selection has more than 100 candidates, none are
560
+ automatically indexed; use `--nodes` to select a smaller history. Check
561
+ `job.indexKnown` and `job.trajectoriesIndexed` after completion: saving a graph
562
+ alone does not make its recipes searchable. `--canvas` takes a positive integer.
563
+ Personal-key commands use the selected profile workspace or `--workspace`.
564
+ The replay walk itself meters per step through each model's own consume plan as
565
+ it runs, so a replay costs the sum of its executable steps and there is no
566
+ route-level hold.
567
+
568
+ Three behaviours worth knowing before scripting against it:
569
+
570
+ - **A replay that fails is a finished run.** `status` is the walk's verdict, not
571
+ the state of the machinery — a walk whose every step failed reports `failed`
572
+ having completed normally. Read `steps[]` for what actually happened;
573
+ `skipped` and `blocked` are steps the recipe could not run.
574
+ - **A match with no prepared memory is a result, not an error.** It means the
575
+ organization has curated nothing. Exit 0, empty result.
576
+ - **A canvas you do not own answers 404, not 403** — the same answer a canvas
577
+ that does not exist gets. That is deliberate: canvas ids are sequential enough
578
+ that a distinguishable 403 would let a caller learn which ones exist. Both
579
+ exit 2 with the server's message, and the CLI does not tell them apart.
580
+
581
+ Exit codes follow the usual convention: `0` completed, `1` terminal failure,
582
+ `2` input/auth/capability, `3` timeout or still pending when `--wait` gave up.
583
+
584
+ ## Canvas export (artifact-graph zips)
585
+
586
+ Internal-only. Export an organization's workflow canvases as `ag.graph-folder.v1`
587
+ zips — the same exporter the dev dashboard's canvas-export panel drives, without
588
+ a browser. A non-internal key gets 404 from every call here, printed as-is with
589
+ exit 2.
590
+
591
+ ```sh
592
+ # Find the org by name or by a member's email, then list its workflow canvases.
593
+ assethub org search acme
594
+ assethub org canvases --org "$ORG_ID"
595
+
596
+ # Queue exports (chunked into POSTs of 50), wait for every job, download the zips.
597
+ assethub graph export-canvas --org "$ORG_ID" --canvas 30917,30918 --wait --out-dir ./exports
598
+ ```
599
+
600
+ Without `--wait` the command prints the queued `jobs` and returns. With it, every
601
+ job is polled every 5 seconds until `ready` or `failed` (default `--timeout`
602
+ 1800 s), each ready zip is streamed to `<out-dir>/<projectId>-rev<rev>.zip` with
603
+ its `sha256` and `bytes` recorded, and the output is
604
+ `{jobs, omitted, downloaded, failed}` (the signed archive URLs are never printed
605
+ — the zip is on disk). A canvas that already has an export in flight is answered
606
+ with that job rather than a second one.
607
+ Exit codes: 0 success, 1 a job failed, a download failed, or a requested id was
608
+ `omitted` (not a workflow canvas owned by `--org` — the API drops it and the
609
+ command names it rather than reporting a partial batch as success), 2 caller
610
+ error, 3 `--wait` timed out (the partial job list is still printed).
611
+
357
612
  ## Storyboard project workflow
358
613
 
359
614
  These API-key commands work from the standalone CLI. Canvas/context commands use
@@ -606,7 +861,7 @@ Image generation uses the `v2` endpoint with mandatory canvas history.
606
861
  `--api-version v1` is rejected; run `assethub capabilities` to check availability.
607
862
 
608
863
  Part extraction uses the same names shown in the AssetHub product: `V1.5`,
609
- `V2.0 alpha`, `V2.1 alpha`, and the Internal-only aliases `V3.6.1`
864
+ `V2.0 alpha`, `V2.1 alpha`, and the graph aliases `V3.6.1`
610
865
  (`V3.6.1 Primary Images First`), `V3.6.3` (`V3.6.3 Fast Analysis`),
611
866
  `V3.6.4` (`V3.6.4 Fast Analysis`), `V3.6.5` (`V3.6.5 Primary Images`),
612
867
  and `pluffy` (`Chibi Character (Pluffy) v3.1`). CLI 0.1.20 adds the latter two;
@@ -614,9 +869,9 @@ and `pluffy` (`Chibi Character (Pluffy) v3.1`). CLI 0.1.20 adds the latter two;
614
869
  `V3.7 Artist Skills` (`v3.7`; also known as `V3.0.7 Artist Skills`) and
615
870
  `V3.7.1 Building Modules` (`v3.7.1`; also known as `V3.0.8 Building Modules`)
616
871
  support `--skill-mode`. `V3.0.9 Garment Boundaries` (`v3.0.9`) and
617
- `Humanoid Assembly (internal)` (`humanoid assembly`, `humanoid-assembly`,
618
- `humanoid_assembly_auto`; CLI 0.1.26+) are additional Internal-only graph
619
- extractors; use the exact quoted public name or one of its aliases with
872
+ `Humanoid Assembly` (`humanoid-assembly`, `humanoid_assembly_auto`; CLI 0.1.26+)
873
+ are additional graph extractors; which extractors your account can run is
874
+ decided by the server; use the exact quoted public name or one of its aliases with
620
875
  `--part-extractor`.
621
876
  Run `production agents` to check availability and `supportedOnGraphEndpoint`
622
877
  before selecting a graph version. These aliases do not change the V1.5 default
@@ -660,6 +915,25 @@ expired proof by logging in again. Explicit `--profile` uses its saved proof and
660
915
  ignores environment credentials; an explicit `--api-key` can supply the workspace
661
916
  key. Generation uses normal workspace credits.
662
917
 
918
+ `composer run --model V6` selects Auto assemble (`part_composer_v6_auto_assemble`).
919
+ `composer run --model V5.1` runs Skill assembly: the CLI sends it as a codex
920
+ `mesh.refine` with `skillAssembly: "assemble-character"` because the server runs
921
+ the bundled Character Assembly skill in the Blender sandbox, not as a compose
922
+ model. It uses identity starting transforms unless you pass `--transforms-json`,
923
+ accepts only Agents API `--agent-model` values and an optional
924
+ `--reasoning low|medium|high`. `composer refine --from-run <run-id> --skill-assembly`
925
+ does the same from a finished compose run's placement. Both models follow their
926
+ release gates. Without `--timeout-ms`, `--wait` allows 95 minutes for V6 and 125
927
+ minutes for V5.1.
928
+
929
+ `composer run --optimize off|light|medium|heavy` is the Part Composer node's
930
+ Optimize output preset. Assembly always works on its own shrunk parts; the final
931
+ bake uses the original full-resolution meshes and then keeps ~75% (`light`),
932
+ ~50% (`medium`) or ~25% (`heavy`) of the geometry with WebP textures, or all of
933
+ it (`off`, also clearing a ratio saved on a `--from-run` or `--input-json`
934
+ input). It is refused with a base body and with `--node`, where the node's own
935
+ Optimize output setting applies.
936
+
663
937
  `composer refine --from-run` accepts a `mesh.compose` or prior `mesh.refine` run
664
938
  and uses that receipt's final `composition.transforms` and any replacement
665
939
  `composition.parts` on the same canvas, preserving `parentRunId` lineage. If the
@@ -0,0 +1,20 @@
1
+ export declare const LAUNCH_AGENT_LABEL = "io.assethub.env";
2
+ export declare const API_KEY_ENV = "ASSETHUB_API_KEY";
3
+ type Run = (file: string, args: string[]) => Promise<{
4
+ code: number;
5
+ output: string;
6
+ }>;
7
+ export declare const launchAgentPath: (home: string) => string;
8
+ /** ProgramArguments for the login agent: `assethub <args>` via this node and CLI, or the login shell's. */
9
+ export declare const launchAgentProgram: (node: string, cli: string, args: string[]) => string[];
10
+ export declare const launchAgentPlist: (program: string[]) => string;
11
+ /** The ASSETHUB_API_KEY that apps started now would receive, if any. */
12
+ export declare const readLaunchdKey: (run: Run) => Promise<string | undefined>;
13
+ export declare const loadKeyIntoLaunchd: (key: string, run: Run) => Promise<{
14
+ ok: true;
15
+ } | {
16
+ ok: false;
17
+ detail: string;
18
+ }>;
19
+ export {};
20
+ //# sourceMappingURL=appEnv.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"appEnv.d.ts","sourceRoot":"","sources":["../src/appEnv.ts"],"names":[],"mappings":"AAUA,eAAO,MAAM,kBAAkB,oBAAoB,CAAA;AACnD,eAAO,MAAM,WAAW,qBAAqB,CAAA;AAG7C,KAAK,GAAG,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,OAAO,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAC,CAAC,CAAA;AAEpF,eAAO,MAAM,eAAe,GAAI,MAAM,MAAM,KAAG,MACuB,CAAA;AActE,2GAA2G;AAC3G,eAAO,MAAM,kBAAkB,GAAI,MAAM,MAAM,EAAE,KAAK,MAAM,EAAE,MAAM,MAAM,EAAE,KAAG,MAAM,EAQpF,CAAA;AAED,eAAO,MAAM,gBAAgB,GAAI,SAAS,MAAM,EAAE,KAAG,MAiBvC,CAAA;AAEd,wEAAwE;AACxE,eAAO,MAAM,cAAc,GAAU,KAAK,GAAG,KAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAIzE,CAAA;AAID,eAAO,MAAM,kBAAkB,GAC7B,KAAK,MAAM,EACX,KAAK,GAAG,KACP,OAAO,CAAC;IAAC,EAAE,EAAE,IAAI,CAAA;CAAC,GAAG;IAAC,EAAE,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAC,CAKlD,CAAA"}
package/dist/appEnv.js ADDED
@@ -0,0 +1,62 @@
1
+ import { join } from 'node:path';
2
+ // macOS apps started from the Dock or Finder (Claude, Codex) do not read shell
3
+ // profiles, so an exported ASSETHUB_API_KEY never reaches them and the MCP
4
+ // header `Bearer ${ASSETHUB_API_KEY}` goes out empty (HTTP 401). launchd's user
5
+ // environment does reach them: `launchctl setenv` covers apps started from now
6
+ // on, and a LaunchAgent repeats it at every login by running `assethub env load`,
7
+ // which reads the key from the CLI's own config. The key is never written to the
8
+ // plist or to any other new file.
9
+ export const LAUNCH_AGENT_LABEL = 'io.assethub.env';
10
+ export const API_KEY_ENV = 'ASSETHUB_API_KEY';
11
+ const LAUNCHCTL = '/bin/launchctl';
12
+ export const launchAgentPath = (home) => join(home, 'Library', 'LaunchAgents', `${LAUNCH_AGENT_LABEL}.plist`);
13
+ const xml = (value) => value.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
14
+ // launchd's PATH has neither nvm's node nor a global `assethub`, so the agent
15
+ // runs the node and CLI that ran setup. Once that node version is removed or
16
+ // the CLI moves, it asks the user's login shell for `assethub` instead.
17
+ const LAUNCH_AGENT_SCRIPT = [
18
+ 'node="$1"; cli="$2"; shift 2',
19
+ 'if [ -x "$node" ] && [ -f "$cli" ]; then exec "$node" "$cli" "$@"; fi',
20
+ 'exec "${SHELL:-/bin/zsh}" -lic \'exec assethub "$@"\' assethub "$@"',
21
+ ].join('\n');
22
+ /** ProgramArguments for the login agent: `assethub <args>` via this node and CLI, or the login shell's. */
23
+ export const launchAgentProgram = (node, cli, args) => [
24
+ '/bin/sh',
25
+ '-c',
26
+ LAUNCH_AGENT_SCRIPT,
27
+ 'assethub-env',
28
+ node,
29
+ cli,
30
+ ...args,
31
+ ];
32
+ export const launchAgentPlist = (program) => [
33
+ '<?xml version="1.0" encoding="UTF-8"?>',
34
+ '<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">',
35
+ '<plist version="1.0">',
36
+ '<dict>',
37
+ ' <key>Label</key>',
38
+ ` <string>${LAUNCH_AGENT_LABEL}</string>`,
39
+ ' <key>ProgramArguments</key>',
40
+ ' <array>',
41
+ ...program.map(arg => ` <string>${xml(arg)}</string>`),
42
+ ' </array>',
43
+ ' <key>RunAtLoad</key>',
44
+ ' <true/>',
45
+ '</dict>',
46
+ '</plist>',
47
+ '',
48
+ ].join('\n');
49
+ /** The ASSETHUB_API_KEY that apps started now would receive, if any. */
50
+ export const readLaunchdKey = async (run) => {
51
+ const result = await run(LAUNCHCTL, ['getenv', API_KEY_ENV]);
52
+ const value = result.code === 0 ? result.output.trim() : '';
53
+ return value || undefined;
54
+ };
55
+ // `launchctl setenv` only takes the value as an argument, so the key is briefly
56
+ // visible to local `ps` while it runs; the result never echoes it.
57
+ export const loadKeyIntoLaunchd = async (key, run) => {
58
+ const result = await run(LAUNCHCTL, ['setenv', API_KEY_ENV, key]);
59
+ return result.code === 0
60
+ ? { ok: true }
61
+ : { ok: false, detail: `launchctl setenv exited ${result.code}: ${result.output.split(key).join('[key]').trim().slice(0, 200)}` };
62
+ };
@@ -0,0 +1,11 @@
1
+ export type DownloadedCanvasGraphZip = {
2
+ path: string;
3
+ bytes: number;
4
+ sha256: string;
5
+ };
6
+ export declare const downloadCanvasGraphZip: ({ url, destinationPath, timeoutMs, }: {
7
+ url: string;
8
+ destinationPath: string;
9
+ timeoutMs?: number;
10
+ }) => Promise<DownloadedCanvasGraphZip>;
11
+ //# sourceMappingURL=canvasGraphDownload.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"canvasGraphDownload.d.ts","sourceRoot":"","sources":["../src/canvasGraphDownload.ts"],"names":[],"mappings":"AAqBA,MAAM,MAAM,wBAAwB,GAAG;IACrC,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,EAAE,MAAM,CAAA;IACb,MAAM,EAAE,MAAM,CAAA;CACf,CAAA;AAiDD,eAAO,MAAM,sBAAsB,GAAU,sCAI1C;IACD,GAAG,EAAE,MAAM,CAAA;IACX,eAAe,EAAE,MAAM,CAAA;IACvB,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB,KAAG,OAAO,CAAC,wBAAwB,CAuCnC,CAAA"}
@@ -0,0 +1,108 @@
1
+ import { createHash, randomUUID } from 'node:crypto';
2
+ import { createWriteStream } from 'node:fs';
3
+ import { mkdir, rename, unlink } from 'node:fs/promises';
4
+ import { dirname, join, resolve } from 'node:path';
5
+ import { Readable, Transform } from 'node:stream';
6
+ import { pipeline } from 'node:stream/promises';
7
+ /** Refuse anything past this — an artifact-graph zip is capped server-side at
8
+ * 400 MiB of retained blobs, so a larger body is not the file we asked for. */
9
+ const MAX_ZIP_BYTES = 1024 * 1024 * 1024;
10
+ /** The only error messages that leave this module verbatim. A network error
11
+ * can carry the signed URL, so anything else collapses to a fixed string. */
12
+ const SAFE_MESSAGES = new Set([
13
+ 'Invalid download URL',
14
+ 'Empty file response',
15
+ 'File exceeds 1 GiB',
16
+ 'Too many redirects',
17
+ ]);
18
+ /**
19
+ * Stream one signed artifact-graph zip to disk.
20
+ *
21
+ * The signed URL is used WITHOUT API credentials — it authenticates itself —
22
+ * and follows up to five redirects, because the storage signer may answer with
23
+ * one; each hop is checked (no HTTPS-to-HTTP, no public-to-private host). Bytes
24
+ * go through a sha256/byte meter into a temp file beside the destination and
25
+ * are renamed into place only once the body ended cleanly, so a half-written
26
+ * zip never sits under the final name. Errors are bounded to a fixed set of
27
+ * messages so a signed URL never lands in the CLI's JSON output.
28
+ */
29
+ const MAX_REDIRECTS = 5;
30
+ const isPrivateHost = (hostname) => {
31
+ const host = hostname.replace(/^\[|\]$/g, '').toLowerCase();
32
+ if (host === 'localhost' || host.endsWith('.localhost') || host === '::1' || host === '0.0.0.0')
33
+ return true;
34
+ if (/^(fc|fd|fe8|fe9|fea|feb)/.test(host) && host.includes(':'))
35
+ return true;
36
+ const octets = host.split('.').map(Number);
37
+ if (octets.length !== 4 || octets.some(n => !Number.isInteger(n)))
38
+ return false;
39
+ const [a, b] = octets;
40
+ return a === 10 || a === 127 || (a === 169 && b === 254) || (a === 172 && b >= 16 && b <= 31) || (a === 192 && b === 168);
41
+ };
42
+ const checkedUrl = (value, from) => {
43
+ const parsed = new URL(value);
44
+ if (!['http:', 'https:'].includes(parsed.protocol) || parsed.username || parsed.password)
45
+ throw new Error('Invalid download URL');
46
+ // A redirect may not downgrade to plain HTTP or move from a public host into
47
+ // a private network or this machine.
48
+ if (from?.protocol === 'https:' && parsed.protocol !== 'https:')
49
+ throw new Error('Invalid download URL');
50
+ if (from && !isPrivateHost(from.hostname) && isPrivateHost(parsed.hostname))
51
+ throw new Error('Invalid download URL');
52
+ return parsed;
53
+ };
54
+ /** The storage signer may answer with a redirect; every hop is checked before it is followed. */
55
+ const fetchFollowingSafeRedirects = async (url, signal) => {
56
+ let current = checkedUrl(url);
57
+ for (let hop = 0;; hop++) {
58
+ const response = await fetch(current.toString(), { signal, redirect: 'manual' });
59
+ const location = response.headers.get('location');
60
+ if (response.status < 300 || response.status >= 400 || !location)
61
+ return response;
62
+ if (hop >= MAX_REDIRECTS)
63
+ throw new Error('Too many redirects');
64
+ await response.body?.cancel();
65
+ current = checkedUrl(new URL(location, current).toString(), current);
66
+ }
67
+ };
68
+ export const downloadCanvasGraphZip = async ({ url, destinationPath, timeoutMs = 120_000, }) => {
69
+ const destination = resolve(destinationPath);
70
+ const directory = dirname(destination);
71
+ await mkdir(directory, { recursive: true, mode: 0o700 });
72
+ const temporary = join(directory, `.${randomUUID()}.tmp`);
73
+ try {
74
+ const response = await fetchFollowingSafeRedirects(url, AbortSignal.timeout(timeoutMs));
75
+ if (!response.ok)
76
+ throw new Error(`HTTP ${response.status}`);
77
+ if (!response.body)
78
+ throw new Error('Empty file response');
79
+ const hash = createHash('sha256');
80
+ let bytes = 0;
81
+ const meter = new Transform({
82
+ transform(chunk, _encoding, callback) {
83
+ bytes += chunk.length;
84
+ if (bytes > MAX_ZIP_BYTES)
85
+ return callback(new Error('File exceeds 1 GiB'));
86
+ hash.update(chunk);
87
+ callback(null, chunk);
88
+ },
89
+ });
90
+ await pipeline(Readable.fromWeb(response.body), meter, createWriteStream(temporary, { flags: 'wx', mode: 0o600 }));
91
+ if (bytes === 0)
92
+ throw new Error('Empty file response');
93
+ await rename(temporary, destination);
94
+ return { path: destination, bytes, sha256: hash.digest('hex') };
95
+ }
96
+ catch (error) {
97
+ const message = error instanceof Error ? error.message : '';
98
+ throw new Error(SAFE_MESSAGES.has(message) || /^HTTP \d{3}$/.test(message)
99
+ ? message
100
+ : 'File download failed');
101
+ }
102
+ finally {
103
+ await unlink(temporary).catch(error => {
104
+ if (error.code !== 'ENOENT')
105
+ throw error;
106
+ });
107
+ }
108
+ };
@@ -38,7 +38,9 @@ export declare class CliExecutionError extends Error {
38
38
  readonly operationId?: string | undefined;
39
39
  readonly execution?: CanvasExecution | undefined;
40
40
  readonly runId: string | undefined;
41
- constructor(message: string, exitCode?: number, operationId?: string | undefined, execution?: CanvasExecution | undefined, runId?: string | undefined);
41
+ constructor(message: string, exitCode?: number, operationId?: string | undefined, execution?: CanvasExecution | undefined, runId?: string | undefined, options?: {
42
+ cause?: unknown;
43
+ });
42
44
  }
43
45
  /** Kept only for SIGINT reporting; interrupting the client never cancels server work. */
44
46
  export declare const activeExecution: {
@@ -47,9 +49,9 @@ export declare const activeExecution: {
47
49
  runId?: string;
48
50
  execution?: CanvasExecution;
49
51
  };
50
- export declare const childOperationId: (parent: string, step: string) => string;
51
52
  export declare const executeRecorded: (session: Session, operation: Operation, body: RequestBody, options?: SubmitOptions) => Promise<{
52
53
  execution: CanvasExecution;
54
+ workspaceSkillAdmission?: import("@assethub/api-client").WorkspaceSkillAdmissionDecision;
53
55
  jobId: string;
54
56
  imageGenId: string;
55
57
  status: "queued";
@@ -118,6 +120,7 @@ export declare const resumeRecorded: (options: Omit<SessionOptions, "canvasId" |
118
120
  expectedBodySubset?: Record<string, unknown>;
119
121
  }) => Promise<{
120
122
  execution: CanvasExecution;
123
+ workspaceSkillAdmission?: import("@assethub/api-client").WorkspaceSkillAdmissionDecision;
121
124
  jobId: string;
122
125
  imageGenId: string;
123
126
  status: "queued";
@@ -1 +1 @@
1
- {"version":3,"file":"execution.d.ts","sourceRoot":"","sources":["../src/execution.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"execution.d.ts","sourceRoot":"","sources":["../src/execution.ts"],"names":[],"mappings":"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"}