@helix3/helix-cli 0.1.18-helix3.339 → 0.1.18-helix3.340
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 +2 -1
- package/dist/index.js +39 -3
- package/dist/index.js.map +1 -1
- package/dist/itemSetVersion.d.ts +39 -0
- package/dist/itemSetVersion.js +88 -0
- package/dist/itemSetVersion.js.map +1 -0
- package/dist/lib.d.ts +11 -0
- package/dist/lib.js +16 -0
- package/dist/lib.js.map +1 -1
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/dist/visualQa/command.d.ts +4 -0
- package/dist/visualQa/command.js +12 -2
- package/dist/visualQa/command.js.map +1 -1
- package/dist/visualQa/hosted.d.ts +4 -0
- package/dist/visualQa/hosted.js +1 -1
- package/dist/visualQa/hosted.js.map +1 -1
- package/dist/visualQa/moveUx.d.ts +44 -0
- package/dist/visualQa/moveUx.js +100 -0
- package/dist/visualQa/moveUx.js.map +1 -0
- package/dist/visualQa/resolve.d.ts +4 -0
- package/dist/visualQa/resolve.js +20 -3
- package/dist/visualQa/resolve.js.map +1 -1
- package/package.json +2 -2
- package/plugins/beamng-vehicle/bin/__pycache__/beamng_abs.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/README.md
CHANGED
|
@@ -49,7 +49,8 @@ The token is stored in `~/.helix/credentials.json` (mode `600`). It's sent as
|
|
|
49
49
|
| `helix item publish <mesh.glb> --title <t> [--collectible-supply <n>] [initial distribution flags] [--dry-run\|--quote]` | Publish a Standard item by default, or one fixed-supply Collectible. The item definition is separate from acquisition routes. |
|
|
50
50
|
| `helix item distribution create\|list\|update\|disable …` | Manage Marketplace/World Claim or Buy routes without republishing the item or paying another publish fee. |
|
|
51
51
|
| `helix item visual-qa <item-id> [--submit] [--local-critic] [--storage-state <file>] [--host <id…>]` | Render the item's current package version headless in the real runtime (test-grounds world for vehicles and whole avatars, the customiser for add-ons and wearables on every declared host/base, the item viewer for props), measure it, and with `--submit` record the backend's verdict (numeric asserts + vision critic) against that exact version. **Marketplace/Vault listing, distributions and version moves on a public item require a pass.** See [docs/visual-qa.md](docs/visual-qa.md). |
|
|
52
|
-
| `helix item visual-qa <item-id> --package-version <v> [--vehicle-package <file>]` | Render a version the item is **not pinned to yet**, so a refused version move can pass the gate before the pointer moves. Vehicles and avatars go through Try Now (vehicles also need the move's vehicle package), add-ons and wearables through the customiser; the bundle names the candidate, and the vehicle checksum is the one the server minted for that trial. Never falls back to the current version. See [docs/visual-qa-candidate-versions.md](docs/visual-qa-candidate-versions.md). |
|
|
52
|
+
| `helix item visual-qa <item-id> --package-version <v> [--vehicle-package <file>]` | Render a version the item is **not pinned to yet**, so a refused version move can pass the gate before the pointer moves. Vehicles and avatars go through Try Now (vehicles also need the move's vehicle package), add-ons and wearables through the customiser; the bundle names the candidate, and the vehicle checksum is the one the server minted for that trial. Never falls back to the current version. See [docs/visual-qa-candidate-versions.md](docs/visual-qa-candidate-versions.md). With `--submit`, a PASS prints the next command (`helix item set-version …`); a 403 for a non-creator says so on the first line; `--status` also lists the item's pending (sealed, not current) versions. |
|
|
53
|
+
| `helix item set-version <item-id> --package-version <v> --reason <text> [--vehicle-package <file>] [--expected-current-version-id <uuid>] [--json]` | Move an item to a sealed Package Version of its own package (pin resolved from the public Package API; `POST /api/v1/universal-items/<id>/versions`). The flow for a **listed** item: `item publish-version` seals vN and the move is refused → `item visual-qa <id> --package-version vN --submit` → `item set-version`. A refusal prints the server's message first (it names the next command), then the remedy and any hosted render it queued. An unknown version lists the sealed ones. |
|
|
53
54
|
| `helix device create <dir> --id <slug> --title <t> --model <mesh.glb> --template standing-desk\|clock\|television` | Scaffold a GLB-backed `helix.device/1` definition, including the interactive TV/media-player template. There is intentionally no website Device editor. |
|
|
54
55
|
| `helix device validate [dir] [--json]` | Validate the definition, GLB bytes and named-node bindings, typed state/controls, capabilities, and Home+World compatibility, including [declarative character hand reach](docs/device-hand-reach.md). |
|
|
55
56
|
| `helix device test [dir] [--mode single\|multiplayer\|both] [--json]` | Exercise every interaction, persistence remount, and deterministic one-/two-client authority convergence. |
|
package/dist/index.js
CHANGED
|
@@ -36,6 +36,8 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
36
36
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
37
37
|
const baseColorGuard_1 = require("./character/baseColorGuard");
|
|
38
38
|
const normalMapGuard_1 = require("./character/normalMapGuard");
|
|
39
|
+
const itemSetVersion_1 = require("./itemSetVersion");
|
|
40
|
+
const moveUx_1 = require("./visualQa/moveUx");
|
|
39
41
|
const commander_1 = require("commander");
|
|
40
42
|
const commands_1 = require("./sceneHlod/commands");
|
|
41
43
|
const placementRequest_1 = require("./placementRequest");
|
|
@@ -1266,6 +1268,7 @@ item
|
|
|
1266
1268
|
.option('--ear-clearance', "with --fit-body: also clear the base body's ears (automatic for headwear/mask/hair/eyewear slot types)")
|
|
1267
1269
|
.option('--no-ear-clearance', 'with --fit-body: skip the ear-clearance stage')
|
|
1268
1270
|
.option('--json', 'machine-readable output')
|
|
1271
|
+
.addHelpText('after', moveUx_1.VERSION_MOVE_FLOW_HELP)
|
|
1269
1272
|
.action(async (itemId, file, opts) => {
|
|
1270
1273
|
const creds = requireAuth();
|
|
1271
1274
|
let meshPath = (0, node_path_1.resolve)(file);
|
|
@@ -1325,6 +1328,34 @@ item
|
|
|
1325
1328
|
fail(error instanceof lib_1.ApiError ? error.render() : `✖ ${error instanceof Error ? error.message : String(error)}`);
|
|
1326
1329
|
}
|
|
1327
1330
|
});
|
|
1331
|
+
// Move a (listed) item to an already-sealed Package Version of its own package. The visual-QA gate refuses the move
|
|
1332
|
+
// until that version has a passing run; a refusal prints the server's message first because it names the next command.
|
|
1333
|
+
item
|
|
1334
|
+
.command('set-version')
|
|
1335
|
+
.description('Move an item to a sealed Package Version of its own package (the version-move step after `item visual-qa --package-version <v> --submit` passed)')
|
|
1336
|
+
.argument('<item-id>', 'universal item UUID')
|
|
1337
|
+
.requiredOption('--package-version <version>', 'the sealed version to move to, e.g. 1.0.12')
|
|
1338
|
+
.requiredOption('--reason <text>', 'required, lands in the audit ledger')
|
|
1339
|
+
.option('--vehicle-package <file>', 'vehicles: the version move\'s vehicle package JSON (the same file given to `item visual-qa`)')
|
|
1340
|
+
.option('--expected-current-version-id <uuid>', 'refuse if the item has moved off this Package Version since you last read it')
|
|
1341
|
+
.option('--json', 'machine-readable output')
|
|
1342
|
+
.addHelpText('after', moveUx_1.VERSION_MOVE_FLOW_HELP)
|
|
1343
|
+
.action(async (itemId, opts) => {
|
|
1344
|
+
const creds = requireAuth();
|
|
1345
|
+
try {
|
|
1346
|
+
const { parseVehiclePackage } = await Promise.resolve().then(() => __importStar(require('./visualQa/candidate')));
|
|
1347
|
+
const vehiclePackage = opts.vehiclePackage ? parseVehiclePackage((0, node_fs_1.readFileSync)(opts.vehiclePackage, 'utf8'), opts.vehiclePackage) : null;
|
|
1348
|
+
const result = await (0, itemSetVersion_1.setItemVersion)(itemId, { packageVersion: opts.packageVersion, reason: opts.reason, vehiclePackage, expectedCurrentVersionId: opts.expectedCurrentVersionId }, creds);
|
|
1349
|
+
if (opts.json)
|
|
1350
|
+
console.log(JSON.stringify(result, null, 2));
|
|
1351
|
+
else
|
|
1352
|
+
for (const line of (0, itemSetVersion_1.renderSetVersionSuccess)(result))
|
|
1353
|
+
console.log(line);
|
|
1354
|
+
}
|
|
1355
|
+
catch (error) {
|
|
1356
|
+
fail(error instanceof lib_1.ApiError ? (0, itemSetVersion_1.renderSetVersionError)(error) : `✖ ${error instanceof Error ? error.message : String(error)}`);
|
|
1357
|
+
}
|
|
1358
|
+
});
|
|
1328
1359
|
// One command prints the whole Character-Creator vocabulary a wearable must
|
|
1329
1360
|
// declare — the 34 slot tags AND the two genders. There is no `list-genders`:
|
|
1330
1361
|
// a dedicated command for a closed two-value list is a command to discover, to
|
|
@@ -1730,6 +1761,7 @@ item
|
|
|
1730
1761
|
.option('--api-url <url>', 'platform API base URL')
|
|
1731
1762
|
.option('--web-url <url>', 'website base URL (default: the site that serves --api-url)')
|
|
1732
1763
|
.option('--json', 'print the outcome as JSON')
|
|
1764
|
+
.addHelpText('after', moveUx_1.VERSION_MOVE_FLOW_HELP)
|
|
1733
1765
|
.action(async (id, opts) => {
|
|
1734
1766
|
try {
|
|
1735
1767
|
const { validateCandidateFlags, parseVehiclePackage } = await Promise.resolve().then(() => __importStar(require('./visualQa/candidate')));
|
|
@@ -1787,6 +1819,8 @@ item
|
|
|
1787
1819
|
if (job?.error)
|
|
1788
1820
|
console.log(` error: ${job.error}`);
|
|
1789
1821
|
console.log(`current version: ${st.currentVersion ? (st.currentVersion.passed ? 'PASSED' : 'no passing run') : 'not pinned to a package version'}`);
|
|
1822
|
+
for (const line of (0, moveUx_1.describePendingVersions)(id, st.pendingVersions))
|
|
1823
|
+
console.log(line);
|
|
1790
1824
|
}
|
|
1791
1825
|
process.exitCode = job && hosted.isTerminal(job.status) ? hosted.exitCodeForJob(job) : 0;
|
|
1792
1826
|
return;
|
|
@@ -1849,7 +1883,7 @@ item
|
|
|
1849
1883
|
quiet: opts.json,
|
|
1850
1884
|
});
|
|
1851
1885
|
if (opts.json) {
|
|
1852
|
-
console.log(JSON.stringify({ verdict: outcome.verdict, reasons: outcome.reasons, bundleDir: outcome.bundleDir, contactSheet: outcome.contactSheet, server: outcome.server, critic: outcome.critic, timings: outcome.timings }, null, 2));
|
|
1886
|
+
console.log(JSON.stringify({ verdict: outcome.verdict, reasons: outcome.reasons, nextStep: (0, moveUx_1.nextStepAfterPass)({ itemId: id, packageVersion: outcome.bundle.item.packageVersion, candidate: !!outcome.candidate, submitted: !!outcome.server, verdict: outcome.verdict, vehiclePackageFile: opts.vehiclePackage })[0]?.replace(/^\s*next:\s*/, '') ?? null, bundleDir: outcome.bundleDir, contactSheet: outcome.contactSheet, server: outcome.server, critic: outcome.critic, timings: outcome.timings }, null, 2));
|
|
1853
1887
|
}
|
|
1854
1888
|
else {
|
|
1855
1889
|
const mark = outcome.verdict === 'pass' ? '✔' : '✖';
|
|
@@ -1862,6 +1896,8 @@ item
|
|
|
1862
1896
|
console.log(` recorded: ${outcome.server.contactSheetUrl}`);
|
|
1863
1897
|
if (!opts.submit)
|
|
1864
1898
|
console.log(' (local run only — add --submit to record the verdict the listing gate checks)');
|
|
1899
|
+
for (const line of (0, moveUx_1.nextStepAfterPass)({ itemId: id, packageVersion: outcome.bundle.item.packageVersion, candidate: !!outcome.candidate, submitted: !!outcome.server, verdict: outcome.verdict, vehiclePackageFile: opts.vehiclePackage }))
|
|
1900
|
+
console.log(line);
|
|
1865
1901
|
console.log(` ${(outcome.timings.totalMs / 1000).toFixed(1)} s (render ${(outcome.timings.renderMs / 1000).toFixed(1)} s)`);
|
|
1866
1902
|
}
|
|
1867
1903
|
process.exitCode = outcome.verdict === 'pass' ? 0 : outcome.verdict === 'fail' ? 1 : 2;
|
|
@@ -1899,7 +1935,7 @@ const itemDistribution = item
|
|
|
1899
1935
|
.description('Create and manage primary Claim/Buy routes for one published item definition');
|
|
1900
1936
|
const renderDistribution = (d) => [
|
|
1901
1937
|
`${d.id} · ${d.channel}${d.worldSlug ? `:${d.worldSlug}/${d.key}` : ''}`,
|
|
1902
|
-
`${d
|
|
1938
|
+
`${(0, lib_1.isClaimRoute)(d) ? 'Claim' : `Buy ${d.priceLix} LIX`}${d.active ? '' : ' · DISABLED'}`,
|
|
1903
1939
|
`max/player ${d.maxPerPlayer ?? 'unlimited'} · max claims ${d.maxClaims ?? 'unlimited'}`,
|
|
1904
1940
|
].join(' · ');
|
|
1905
1941
|
itemDistribution
|
|
@@ -1944,7 +1980,7 @@ itemDistribution
|
|
|
1944
1980
|
if (opts.json)
|
|
1945
1981
|
console.log(JSON.stringify(created, null, 2));
|
|
1946
1982
|
else
|
|
1947
|
-
console.log(
|
|
1983
|
+
console.log(`${(0, lib_1.distributionCreatedHeadline)(created, input.priceLix)}\n ${renderDistribution(created)}`);
|
|
1948
1984
|
}
|
|
1949
1985
|
catch (err) {
|
|
1950
1986
|
fail(err instanceof lib_1.ApiError ? err.render() : `✖ ${err instanceof Error ? err.message : String(err)}`);
|