@helix3/helix-cli 0.1.19-helix3.377 → 0.1.20-helix3.379
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 +26 -4
- package/dist/index.js +126 -3
- package/dist/index.js.map +1 -1
- package/dist/lib.d.ts +2 -2
- package/dist/lib.js +3 -1
- package/dist/lib.js.map +1 -1
- package/dist/publications.d.ts +11 -0
- package/dist/publications.js +33 -0
- package/dist/publications.js.map +1 -1
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/dist/vehicle/simulate.d.ts +174 -0
- package/dist/vehicle/simulate.js +472 -0
- package/dist/vehicle/simulate.js.map +1 -0
- package/dist/vehicle/simulateRuntime.d.ts +76 -0
- package/dist/vehicle/simulateRuntime.js +252 -0
- package/dist/vehicle/simulateRuntime.js.map +1 -0
- package/dist/vehicle/validate.d.ts +70 -4
- package/dist/vehicle/validate.js +229 -9
- package/dist/vehicle/validate.js.map +1 -1
- package/docs/vehicle-simulate.md +121 -0
- package/package.json +2 -1
- package/plugins/beamng-vehicle/bin/__pycache__/beamng_abs.cpython-312.pyc +0 -0
- package/plugins/beamng-vehicle/bin/__pycache__/beamng_audio.cpython-312.pyc +0 -0
- package/plugins/beamng-vehicle/bin/__pycache__/beamng_engine.cpython-312.pyc +0 -0
- package/plugins/beamng-vehicle/bin/__pycache__/beamng_expression.cpython-312.pyc +0 -0
- package/plugins/beamng-vehicle/bin/__pycache__/beamng_jbeam.cpython-312.pyc +0 -0
- package/plugins/beamng-vehicle/bin/__pycache__/beamng_materials.cpython-312.pyc +0 -0
- package/plugins/beamng-vehicle/bin/__pycache__/test_beamng_engine.cpython-312.pyc +0 -0
package/README.md
CHANGED
|
@@ -45,10 +45,12 @@ The token is stored in `~/.helix/credentials.json` (mode `600`). It's sent as
|
|
|
45
45
|
| `helix validate [dir]` | Validate a bundle locally — the exact rules the server enforces. |
|
|
46
46
|
| `helix publish [dir] [--thumbnail <file>] [--upload-source] [--source-dir <path>]` | Validate → resolve/create the world → upload files → finalize → set the cover image → print the play URL. `--upload-source` additionally sends the project's source through a separate private channel so the world can be edited on the website later — **off by default**. |
|
|
47
47
|
| `helix list` | List your worlds. |
|
|
48
|
-
| `helix vehicle
|
|
48
|
+
| `helix vehicle simulate <dir\|vehicle-package.json> [--item <id>] [--spec <file>] [--offline] [--json]` | Drive the package offline with the platform's **own** engine instrument (the runtime `^0.3` serves today, cached by sha; offline = last cached, labelled) and judge 0-100 km/h, 0-60 mph, quarter mile, top speed, 100-0 km/h / 60-0 mph braking, skidpad g, turbo lag and the rest pose against the package `targets` and `--spec`. Exit `0` pass, `1` a figure out of tolerance, `2` could not simulate. See [docs/vehicle-simulate.md](docs/vehicle-simulate.md). |
|
|
49
|
+
| `helix vehicle validate <vehicle-package.json> [--glb <model.glb>] [--no-simulate] [--json]` | One-second local gate for a hand-authored Universal Vehicle, run before Package publication. Checks the package against the engine's own validator (vendored, pinned to an engine commit), the engine publish gate, the backend pin requirements, `groundToBodyOrigin` vs `wheelRadius + staticRideHeight`, and the `componentBuild` digest; with `--glb` also resolves the four wheel nodes, checks each wheel node's origin is at its hub (`WHEEL_PIVOT_NOT_AT_HUB`), the +X-left / +Z-forward frame, the vehicle publish budgets the articulation nodes and the add-on host manifest (`asset.extras.HELIX_vehicle`); drives packages that declare `targets` (`helix vehicle simulate`). Exit `0` no errors, `1` errors, `2` unreadable input. See [Vehicle validate](#vehicle-validate). |
|
|
49
50
|
| `helix vehicle preview [<dir-or-package.json>] [--glb <model.glb>] [--addon <dir>]… [--item <id>] [--tolerance-cm <cm>] [--out <dir>] [--proxy-item <id>] [--json]` | Render a vehicle that is **not published yet** headless in the real runtime (hosted test grounds, Try Now through a published proxy vehicle whose car is swapped for your package + GLB, served from disk; nothing uploaded or recorded) and measure it: body-origin height against the declared `groundToBodyOrigin` (the number that locks at first mint), wheels on their hubs, arch clearance, rolling radius vs `wheelRadius`, steering, doors, seats. Prints a numeric summary with PASS/FAIL per check and writes frames, a contact sheet, `bundle.json` and `preview.json`. Boards with the candidate's own seat ids. With `--addon <dir>` (repeatable) it previews unpublished vehicle **add-ons** instead: fits each to the candidate car or a published car and measures the drawn geometry in world space against its anchor (wheels within 1 cm of each hub, socket/host-framed parts at their mount, not at the car's origin; tune-only ops read back from the live tuning). Exit `0` pass, `1` fail, `2` could not measure. See [docs/vehicle-preview.md](docs/vehicle-preview.md). |
|
|
50
51
|
| `helix continuum publish-glb <mesh.glb> --title <t> [--package-type asset\|character] [--offer marketplace\|world --price-lix <n> --content-rating <rating>]` | Seal a Package first; optional offer makes it ownable. See [Package-first GLB publication](#package-first-glb-publication). |
|
|
51
52
|
| `helix continuum make-item --package-id <id> --package-version <v> --manifest-cid <cid> --content-rating <rating> [--offer marketplace\|world --price-lix <n>]` | Project one exact sealed Package Version into an Item, with an optional first offer. |
|
|
53
|
+
| `helix continuum publish-owned-item <item-id> --package-id <id> --package-version <v> --manifest-cid <cid> --content-rating <rating> --accept-rating-attestation` | Publish an existing personal Item from its unchanged public sealed Package pin. Offers are separate. |
|
|
52
54
|
| `helix vehicle audio-check <dir\|package.json\|item-id> [--json]` | Proves every sound the runtime will select resolves, is PCM WAV and is audible (pre-publish on local files, or read-back on a published item). |
|
|
53
55
|
| `helix vehicle addon check <dir> [--json]` | Add-on fit gate for local source and host compatibility. |
|
|
54
56
|
| `helix item list-slots [--json]` | Print the Character-Creator vocabulary a wearable declares: the cosmetic slot tags, and the genders. |
|
|
@@ -84,7 +86,7 @@ The token is stored in `~/.helix/credentials.json` (mode `600`). It's sent as
|
|
|
84
86
|
| `helix world performance-report [bundle] [--scene <scene-v2.json>] [--package <package-version.json>] [--snapshot <inspect.json>] [--perf <receipt.json>]` | Analyze exact declared scene resources and existing reference-profile budgets, while keeping authored geometry/material/delivery estimates separate from supplied runtime claims. Prints actionable instancing, Palette, lighting, transfer, and visual-QA guidance; it never predicts FPS from static counts. |
|
|
85
87
|
| `helix world scene-source inventory\|compile <helsinki\|bistro> <archive>` | Verify and safely inventory a known CC BY source archive, then compile deterministic local proxy/detail GLBs and an existing-schema Scene v2 package. |
|
|
86
88
|
| `helix world scene-source publish <world-id> <package-dir> [--publish]` | Validate the Scene v2 package and print its multipart build receipt. Execution remains dry-run-only until backend private-pin entitlement lands; `--publish` currently fails closed, and access control never changes CC BY rights. |
|
|
87
|
-
| `helix continuum publish-source-map\|publish-scratch\|publish-package\|publish-glb\|make-item` | Resume exact-CID object adoption/ingestion, Package lease/seal, optional explicitly authorized Listing, and WorldRelease publication through one creator-owned pipeline. |
|
|
89
|
+
| `helix continuum publish-source-map\|publish-scratch\|publish-package\|publish-glb\|make-item\|publish-owned-item` | Resume exact-CID object adoption/ingestion, Package lease/seal, optional explicitly authorized Listing, and WorldRelease publication through one creator-owned pipeline. |
|
|
88
90
|
| `helix continuum receipt <job-id>` | Read the sanitized durable receipt for a completed Continuum publication. |
|
|
89
91
|
| `helix unreal init\|validate\|doctor\|package [project]` | Create and gate a shared-runtime or native-game publish manifest, check optional editor MCP, and assemble a local upload-shaped package. |
|
|
90
92
|
| `helix unreal publish <candidate> --world <slug>` | Upload a **cooked** Unreal world to HELIX: verify the candidate, presign, upload every artifact, finalize, and promote it as the world's active build. |
|
|
@@ -569,8 +571,11 @@ How each field is resolved, and what a null means:
|
|
|
569
571
|
|
|
570
572
|
## Vehicle validate
|
|
571
573
|
|
|
572
|
-
`helix vehicle validate <vehicle-package.json> [--glb <model.glb>] [--json]` needs no login
|
|
573
|
-
This local gate checks the vehicle Package and optional GLB before any publication.
|
|
574
|
+
`helix vehicle validate <vehicle-package.json> [--glb <model.glb>] [--no-simulate] [--offline] [--json]` needs no login.
|
|
575
|
+
This local gate checks the vehicle Package and optional GLB before any publication. When the package declares
|
|
576
|
+
`targets` it also drives the car with the platform's engine instrument (`helix vehicle simulate`; the runtime is
|
|
577
|
+
fetched once and cached, `--offline` uses the cache, `--no-simulate` skips the drive) and reports every figure
|
|
578
|
+
outside its tolerance as `SIMULATED_PERFORMANCE_OUT_OF_TOLERANCE`.
|
|
574
579
|
|
|
575
580
|
Every finding prints as `CODE path — message` plus a `fix:` line; `--json` returns
|
|
576
581
|
`{ ok, errors, warnings, issues: [{ code, level, path, message, fix }], engineCommit }`.
|
|
@@ -580,6 +585,8 @@ Every finding prints as `CODE path — message` plus a `fix:` line; `--json` re
|
|
|
580
585
|
| Engine validator (all its errors and warnings) | `ENGINE_VALIDATOR`, `ENGINE_VALIDATOR_CRASH` |
|
|
581
586
|
| Publish gate + backend pin | `PACKAGE_NOT_OBJECT`, `PACKAGE_VERSION_UNSUPPORTED`, `SCHEMA_VERSION_MISMATCH`, `REQUIRED_FIELD_MISSING`, `REQUIRED_BLOCK_MISSING`, `MESH_CLASS_ID_MISSING`, `MESH_PARTS_MISSING`, `WHEEL_VISUALS_MISSING`, `WHEEL_VISUALS_INVALID`, `NOT_DISTRIBUTABLE`, `MESH_SOURCE_FIXTURE`, `PUBLISH_GATE` |
|
|
582
587
|
| Cross-field | `GROUND_TO_BODY_ORIGIN_MISMATCH` (> 5 mm; fix the ride height, the field is locked after first publish), `COMPONENT_BUILD_DIGEST_MISMATCH` (prints the computed digest), `COMPONENT_ACTIONS_MISMATCH` (prints the compiled protocol), `COMPONENT_BUILD_INVALID`, `PANEL_SIGNAL_NO_ACTION` (warn), `SEAT_SOCKET_UNKNOWN` (warn) |
|
|
588
|
+
| Drive (package `targets`) | `SIMULATED_PERFORMANCE_OUT_OF_TOLERANCE` (figure, simulated, target, error, tolerance, engine version), `SIMULATED_REST_POSE_INVALID`, `SIMULATION_UNAVAILABLE` (warn: no runtime reachable or cached) |
|
|
589
|
+
| `--glb` host manifest | `HOST_MANIFEST_MISSING`, `HOST_MANIFEST_MISPLACED` (found in scene/document/node extras; the backend reads only `asset.extras.HELIX_vehicle`), `HOST_MANIFEST_EMPTY`, `HOST_MANIFEST_DIVERGENT`, `HOST_MANIFEST_SOCKET_INVALID`, `HOST_MANIFEST_SOCKET_NAME_INVALID`, `HOST_MANIFEST_SOCKET_NODE_MISSING`. `helix continuum publish-package` refuses a `vehicle` Package descriptor whose model GLB has any of these errors before sealing. See [docs/vehicle-simulate.md](docs/vehicle-simulate.md#host-manifest) |
|
|
583
590
|
| `--glb` | `WHEEL_NODES_MISSING`, `WHEEL_PIVOT_NOT_AT_HUB` (origin > 2 cm from the centre of its geometry — the wheel add-on anchor lands there), `WHEEL_ORIGINS_NOT_DISTINCT`, `WHEEL_FRAME_MIRRORED_X`, `WHEEL_FRAME_FRONT_NOT_PLUS_Z`, `WHEEL_NODE_EMPTY` (warn), `LENGTH_NOT_ALONG_Z` (warn), `PANEL_NODE_MISSING`, `VEHICLE_BUDGET_TRIANGLES` / `_MATERIALS` / `_TEXTURE_EDGE` / `_DRAW_CALLS` / `_FILE_SIZE` |
|
|
584
591
|
|
|
585
592
|
The model frame is glTF: +X is the vehicle's left, +Y up, +Z forward, metres. Wheel nodes are found by name with
|
|
@@ -632,6 +639,21 @@ Creating an Item without an active offer grants no creator copy. The same intent
|
|
|
632
639
|
interrupted call. The backend derives specialized Item metadata from the sealed Package root;
|
|
633
640
|
client supplied host, fit, operation and rider metadata is never trusted.
|
|
634
641
|
|
|
642
|
+
An Item created with `make-item --personal` keeps its identity when published later. First make
|
|
643
|
+
its Package public and confirm the current sealed pin, then attest its rating and publish that
|
|
644
|
+
existing Item. Publishing opens no acquisition route or creator copy; create a Marketplace or
|
|
645
|
+
World Distribution afterward when it should become available:
|
|
646
|
+
|
|
647
|
+
```bash
|
|
648
|
+
helix continuum publish-owned-item <item-uuid> --package-id <uuid> \
|
|
649
|
+
--package-version 1.0.0 --manifest-cid cid:sha256:<64-hex> \
|
|
650
|
+
--content-rating everyone --accept-rating-attestation --json
|
|
651
|
+
```
|
|
652
|
+
|
|
653
|
+
Use `--intent-id <uuidv4>` to retry an interrupted promotion safely. The server requires the
|
|
654
|
+
Package to be public, sealed, current, owned by the creator, and pinned to that Item. A private
|
|
655
|
+
Package cannot be promoted through this Item command.
|
|
656
|
+
|
|
635
657
|
Existing Item reads, distributions, visual QA and Package Version moves remain available. The
|
|
636
658
|
former Item-first authoring commands are retired from CLI discovery.
|
|
637
659
|
Vehicle, add-on, locomotion and interactive definition authors must seal the appropriate Package
|
package/dist/index.js
CHANGED
|
@@ -574,7 +574,10 @@ vehicleCommand
|
|
|
574
574
|
.description('Validate a vehicle package (and optionally its GLB) against the engine contract, the backend pin rules and the publish budgets. '
|
|
575
575
|
+ 'Exit 0 = no errors, 1 = errors, 2 = unreadable input')
|
|
576
576
|
.argument('<vehicle-package.json>', 'the vehicle package JSON that will be sealed in the Vehicle Package')
|
|
577
|
-
.option('--glb <model.glb>', 'also check the model: wheel nodes and pivots, frame orientation, budgets, articulation nodes')
|
|
577
|
+
.option('--glb <model.glb>', 'also check the model: wheel nodes and pivots, frame orientation, budgets, articulation nodes, and the add-on host manifest (asset.extras.HELIX_vehicle)')
|
|
578
|
+
.option('--no-simulate', 'skip the offline drive (by default a package with `targets` is driven by the platform\'s own engine instrument and every figure outside its tolerance is an ERROR)')
|
|
579
|
+
.option('--offline', 'drive with the last cached engine runtime; never fetch')
|
|
580
|
+
.option('--api-url <url>', 'API whose engine runtime drives the car (default: this CLI\'s environment)')
|
|
578
581
|
.option('--json', 'print the machine-readable report')
|
|
579
582
|
.action(async (packageFile, opts) => {
|
|
580
583
|
let pkg;
|
|
@@ -605,7 +608,7 @@ vehicleCommand
|
|
|
605
608
|
const { provisionalAudio } = await Promise.resolve().then(() => __importStar(require('./vehicle/audio')));
|
|
606
609
|
const prepared = provisionalAudio(pkg, (0, node_path_1.resolve)(packageFile, '..'));
|
|
607
610
|
provisional = prepared.filled;
|
|
608
|
-
result = await (0, validate_1.validateVehicle)(prepared.pkg, glb);
|
|
611
|
+
result = await (0, validate_1.validateVehicle)(prepared.pkg, glb, opts.simulate === false ? {} : { simulate: { apiUrl: opts.apiUrl ?? config_1.DEFAULT_API_URL, offline: opts.offline } });
|
|
609
612
|
}
|
|
610
613
|
catch (error) {
|
|
611
614
|
process.stderr.write(`✖ cannot validate ${opts.glb ?? packageFile}: ${error instanceof Error ? error.message : String(error)}\n`);
|
|
@@ -618,10 +621,15 @@ vehicleCommand
|
|
|
618
621
|
else {
|
|
619
622
|
if (result.issues.length > 0)
|
|
620
623
|
console.log((0, validate_1.formatVehicleIssues)(result.issues));
|
|
624
|
+
if (result.simulation) {
|
|
625
|
+
const { formatSimulationReport } = await Promise.resolve().then(() => __importStar(require('./vehicle/simulate')));
|
|
626
|
+
console.log(formatSimulationReport(result.simulation).split('\n').map((line) => ` ${line}`).join('\n'));
|
|
627
|
+
}
|
|
621
628
|
if (provisional > 0)
|
|
622
629
|
console.log(` ${provisional} audio row${provisional === 1 ? '' : 's'} backed by a local WAV: seal the WAV in the Vehicle Package before making its Item; \`helix vehicle audio-check\` proves ${provisional === 1 ? 'it plays' : 'they play'}`);
|
|
623
630
|
console.log(`${result.ok ? '✔' : '✖'} ${result.ok ? 'Valid' : 'Invalid'} vehicle package: ${result.errors} error${result.errors === 1 ? '' : 's'}, ${result.warnings} warning${result.warnings === 1 ? '' : 's'}`
|
|
624
|
-
+ `${glb ? ' (package + GLB)' : ' (package only — add --glb <model.glb> to check wheels, pivots and
|
|
631
|
+
+ `${glb ? ' (package + GLB)' : ' (package only — add --glb <model.glb> to check wheels, pivots, budgets and the host manifest)'}`
|
|
632
|
+
+ `${result.simulation ? ` + drive (engine runtime ${result.simulation.runtime.version})` : opts.simulate === false ? ' (drive skipped: --no-simulate)' : ''} [validator ${result.engineCommit.slice(0, 8)}]`);
|
|
625
633
|
}
|
|
626
634
|
if (!result.ok)
|
|
627
635
|
process.exitCode = 1;
|
|
@@ -707,6 +715,77 @@ function printVehicleJsonOr(json, value, human) {
|
|
|
707
715
|
else
|
|
708
716
|
human();
|
|
709
717
|
}
|
|
718
|
+
vehicleCommand
|
|
719
|
+
.command('simulate')
|
|
720
|
+
.description('Drive a vehicle package offline with the platform\'s OWN engine instrument (the runtime `^0.3` serves today: Rapier, land solver v2, the code players run) '
|
|
721
|
+
+ 'and judge it: 0-100 km/h, 0-60 mph, quarter mile, top speed (converged or not), 100-0 km/h and 60-0 mph braking, skidpad lateral g, turbo lag, '
|
|
722
|
+
+ 'gears used and the rest pose. Every figure is compared with the package\'s own `targets` (and --spec): error = (simulated - target) / target, '
|
|
723
|
+
+ 'PASS iff |error| <= tolerance. The runtime is fetched once per version and cached by sha under ~/.helix/cache/engine-runtime; offline, the last '
|
|
724
|
+
+ 'cached runtime is used and labelled. TURBO LAG: with boostTorqueCoef 0 the solver adds no boost torque, so a turbo car whose curve is the full-boost '
|
|
725
|
+
+ 'dyno curve pulls with no lag; author lag by derating the torque curve below spool, then check `turbo lag` here (docs/vehicle-simulate.md). '
|
|
726
|
+
+ 'Exit 0 = every compared figure passes, 1 = a figure is out of tolerance or the rest pose is wrong, 2 = could not simulate')
|
|
727
|
+
.argument('[dir-or-package.json]', 'a vehicle package directory (vehicle-package.json), the package JSON, or a saved item read')
|
|
728
|
+
.option('--item <id>', 'simulate a PUBLISHED vehicle item\'s stored package (public read) instead of a local file')
|
|
729
|
+
.option('--spec <file>', 'extra targets: a package / {targets}, or a reference spec (perf.0_100_kmh_s, perf.braking_100_0_m, perf.braking_70mph_0_m, perf.skidpad_g, perf.turbo_lag_s … as {value, tol_pct})')
|
|
730
|
+
.option('--offline', 'use the last cached engine runtime; never fetch')
|
|
731
|
+
.option('--runtime <file-or-url>', 'drive with this runtime bundle instead of the served one (a candidate engine build)')
|
|
732
|
+
.option('--range <range>', 'engine range to resolve (default ^0.3)')
|
|
733
|
+
.option('--api-url <url>', 'API to resolve the runtime (and --item) from (default: this CLI\'s environment)')
|
|
734
|
+
.option('--json', 'print the machine-readable report')
|
|
735
|
+
.action(async (input, opts) => {
|
|
736
|
+
const { readVehiclePackageArg, simulateVehicle, targetsFromSpec, formatSimulationReport } = await Promise.resolve().then(() => __importStar(require('./vehicle/simulate')));
|
|
737
|
+
const { loadEngineRuntime } = await Promise.resolve().then(() => __importStar(require('./vehicle/simulateRuntime')));
|
|
738
|
+
const { provisionalAudio } = await Promise.resolve().then(() => __importStar(require('./vehicle/audio')));
|
|
739
|
+
const apiUrl = (opts.apiUrl ?? config_1.DEFAULT_API_URL).replace(/\/$/, '');
|
|
740
|
+
let pkg;
|
|
741
|
+
let source;
|
|
742
|
+
let specTargets;
|
|
743
|
+
try {
|
|
744
|
+
if (opts.item) {
|
|
745
|
+
// A public read; retried on a 5xx so one flaky gateway answer does not read as "no such car".
|
|
746
|
+
let res = await fetch(`${apiUrl}/api/v1/universal-items/${encodeURIComponent(opts.item)}`, { headers: { accept: 'application/json' } });
|
|
747
|
+
for (let attempt = 1; res.status >= 500 && attempt < 4; attempt += 1) {
|
|
748
|
+
await new Promise((done) => setTimeout(done, 1000 * attempt));
|
|
749
|
+
res = await fetch(`${apiUrl}/api/v1/universal-items/${encodeURIComponent(opts.item)}`, { headers: { accept: 'application/json' } });
|
|
750
|
+
}
|
|
751
|
+
if (!res.ok)
|
|
752
|
+
throw new Error(`GET /api/v1/universal-items/${opts.item} answered HTTP ${res.status}`);
|
|
753
|
+
const body = await res.json();
|
|
754
|
+
pkg = (body.item ?? body).properties?.vehiclePackage;
|
|
755
|
+
if (!pkg)
|
|
756
|
+
throw new Error(`item ${opts.item} carries no properties.vehiclePackage`);
|
|
757
|
+
source = `item ${opts.item}`;
|
|
758
|
+
}
|
|
759
|
+
else {
|
|
760
|
+
if (!input)
|
|
761
|
+
throw new Error('pass a vehicle package directory or JSON file, or --item <id>');
|
|
762
|
+
const read = readVehiclePackageArg(input);
|
|
763
|
+
pkg = provisionalAudio(read.pkg, read.dir).pkg;
|
|
764
|
+
source = read.file;
|
|
765
|
+
}
|
|
766
|
+
if (opts.spec)
|
|
767
|
+
specTargets = targetsFromSpec(JSON.parse((0, node_fs_1.readFileSync)((0, node_path_1.resolve)(opts.spec), 'utf8')), opts.spec);
|
|
768
|
+
}
|
|
769
|
+
catch (error) {
|
|
770
|
+
process.stderr.write(`✖ ${error instanceof Error ? error.message : String(error)}\n`);
|
|
771
|
+
process.exitCode = 2;
|
|
772
|
+
return;
|
|
773
|
+
}
|
|
774
|
+
try {
|
|
775
|
+
const runtime = await loadEngineRuntime({ apiUrl, offline: opts.offline, runtime: opts.runtime, range: opts.range });
|
|
776
|
+
const report = await simulateVehicle(pkg, runtime, { specTargets });
|
|
777
|
+
if (opts.json)
|
|
778
|
+
console.log(JSON.stringify({ source, spec: opts.spec ? (0, node_path_1.resolve)(opts.spec) : null, ...report }, null, 2));
|
|
779
|
+
else
|
|
780
|
+
console.log(formatSimulationReport(report));
|
|
781
|
+
if (!report.ok)
|
|
782
|
+
process.exitCode = 1;
|
|
783
|
+
}
|
|
784
|
+
catch (error) {
|
|
785
|
+
process.stderr.write(`✖ cannot simulate ${source}: ${error instanceof Error ? error.message : String(error)}\n`);
|
|
786
|
+
process.exitCode = 2;
|
|
787
|
+
}
|
|
788
|
+
});
|
|
710
789
|
vehicleCommand
|
|
711
790
|
.command('audio-check')
|
|
712
791
|
.description('Prove every sound a vehicle declares will actually play: each engine-ladder rung and slot sample the runtime selects must resolve (a local WAV '
|
|
@@ -4660,6 +4739,47 @@ continuum
|
|
|
4660
4739
|
fail(error instanceof lib_1.ApiError ? error.render() : `✖ ${error instanceof Error ? error.message : String(error)}`);
|
|
4661
4740
|
}
|
|
4662
4741
|
});
|
|
4742
|
+
continuum
|
|
4743
|
+
.command('publish-owned-item')
|
|
4744
|
+
.description('Publish an existing personal Item from its exact sealed public Package pin; open offers separately')
|
|
4745
|
+
.argument('<item-id>', 'existing Item UUID; identity is preserved')
|
|
4746
|
+
.requiredOption('--package-id <uuid>', 'owned sealed Package UUID')
|
|
4747
|
+
.requiredOption('--package-version <semver>', 'exact current sealed Package Version')
|
|
4748
|
+
.requiredOption('--manifest-cid <cid>', 'exact immutable manifest CID')
|
|
4749
|
+
.requiredOption('--content-rating <rating>', 'creator-attested rating: everyone, teen, mature or adult')
|
|
4750
|
+
.option('--accept-rating-attestation', 'attest that the stated content rating is accurate')
|
|
4751
|
+
.option('--intent-id <uuidv4>', 'stable UUIDv4 for safe retry after an interrupted request')
|
|
4752
|
+
.option('--json', 'emit the unchanged Item and publication receipt')
|
|
4753
|
+
.action(async (itemId, opts) => {
|
|
4754
|
+
try {
|
|
4755
|
+
if (opts.acceptRatingAttestation !== true)
|
|
4756
|
+
throw new Error('--accept-rating-attestation is required to publish an Item');
|
|
4757
|
+
if (!['everyone', 'teen', 'mature', 'adult'].includes(opts.contentRating))
|
|
4758
|
+
throw new Error('--content-rating must be everyone, teen, mature or adult');
|
|
4759
|
+
const creds = requireAuth();
|
|
4760
|
+
const mismatch = (0, config_1.credsEnvMismatchWarning)(creds.apiUrl);
|
|
4761
|
+
if (mismatch)
|
|
4762
|
+
throw new Error(`Refusing to publish an Item:\n${mismatch}`);
|
|
4763
|
+
const { publishOwnedItemFromPackage } = await Promise.resolve().then(() => __importStar(require('./publications')));
|
|
4764
|
+
const receipt = await publishOwnedItemFromPackage({
|
|
4765
|
+
itemId,
|
|
4766
|
+
intentId: opts.intentId,
|
|
4767
|
+
packagePin: { packageId: opts.packageId, version: opts.packageVersion, manifestCid: opts.manifestCid },
|
|
4768
|
+
contentRating: opts.contentRating,
|
|
4769
|
+
acceptRatingAttestation: true,
|
|
4770
|
+
}, creds);
|
|
4771
|
+
if (opts.json)
|
|
4772
|
+
console.log(JSON.stringify(receipt, null, 2));
|
|
4773
|
+
else {
|
|
4774
|
+
console.log(`✔ Published existing Package-backed Item ${receipt.item.id}`);
|
|
4775
|
+
console.log(` package: ${receipt.item.packagePin.packageId}@${receipt.item.packagePin.version}`);
|
|
4776
|
+
console.log(' offers: none opened; use helix item distribution create when ready');
|
|
4777
|
+
}
|
|
4778
|
+
}
|
|
4779
|
+
catch (error) {
|
|
4780
|
+
fail(error instanceof lib_1.ApiError ? error.render() : `✖ ${error instanceof Error ? error.message : String(error)}`);
|
|
4781
|
+
}
|
|
4782
|
+
});
|
|
4663
4783
|
continuum
|
|
4664
4784
|
.command('publish-glb')
|
|
4665
4785
|
.description('Seal a GLB as a Continuum Prop or Character Package; optionally open a Marketplace or World offer')
|
|
@@ -4745,6 +4865,9 @@ continuum
|
|
|
4745
4865
|
const { readContinuumPublicationFile } = await Promise.resolve().then(() => __importStar(require('./continuum/cli')));
|
|
4746
4866
|
const loaded = await readContinuumPublicationFile(path);
|
|
4747
4867
|
const descriptor = loaded.input;
|
|
4868
|
+
// A vehicle model the backend cannot read as an add-on host would seal a silent non-host (docs/vehicle-simulate.md).
|
|
4869
|
+
const { assertVehiclePackageDescriptorHost } = await Promise.resolve().then(() => __importStar(require('./vehicle/validate')));
|
|
4870
|
+
assertVehiclePackageDescriptorHost(descriptor, loaded.objectPublications);
|
|
4748
4871
|
const publication = explicitPublicListings({
|
|
4749
4872
|
...descriptor, sourceDigest: loaded.sourceDigest, objects: loaded.objectPublications,
|
|
4750
4873
|
...(opts.stage === true ? { stage: true } : {}),
|