@helix3/helix-cli 0.1.18-helix3.255 → 0.1.18-helix3.256

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -47,6 +47,8 @@ const scenePerformance_1 = require("./scenePerformance");
47
47
  const lib_1 = require("./lib");
48
48
  const itemQuote_1 = require("./itemQuote");
49
49
  const itemSearch_1 = require("./itemSearch");
50
+ const vault_1 = require("./vault");
51
+ const looks_1 = require("./looks");
50
52
  const tables_1 = require("./itemDef/tables");
51
53
  const emoteRules_1 = require("./itemDef/emoteRules");
52
54
  const scaffold_1 = require("./itemDef/scaffold");
@@ -1210,14 +1212,14 @@ item
1210
1212
  // list it is always read with. `--gender`'s own help carries the same values.
1211
1213
  item
1212
1214
  .command('search')
1213
- .description('Search the published MARKETPLACE catalogue — including builds, the presets someone already assembled')
1215
+ .description("Search the published MARKETPLACE catalogue — including Looks (user-facing name for a `build`: a free, never-owned preset), the dressed presets someone already assembled. A Look is never owned itself; its parts are acquired individually from their own listings")
1214
1216
  .argument('[query]', 'free text over title, slug and tags')
1215
1217
  .option('--kind <kind>', 'universal item kind (avatar, wearable, vehicle, weapon, add_on, home_item, emote, prop)')
1216
1218
  .option('--category <category>', 'marketplace category')
1217
1219
  .option('--sub-category <subCategory>', 'form factor beneath the category, e.g. car / rifle / art')
1218
1220
  .option('--tag <tag>', 'exact tag')
1219
1221
  .option('--host-kind <hostKind>', 'host class, e.g. vehicle / character / weapon')
1220
- .option('--builds <mode>', `builds in the results: ${itemSearch_1.BUILD_FILTER_MODES.join(' | ')} (default include — a build is filed under its base's own category, so it comes back alongside bases unless you narrow)`)
1222
+ .option('--builds <mode>', `Looks (API identifier: builds) in the results: ${itemSearch_1.BUILD_FILTER_MODES.join(' | ')} (default include — a Look is filed under its base's own category, so it comes back alongside bases unless you narrow)`)
1221
1223
  .option('--limit <n>', 'rows to return (1-100, default 20)')
1222
1224
  .option('--json', 'machine-readable output')
1223
1225
  .action(async (query, opts) => {
@@ -1243,11 +1245,12 @@ item
1243
1245
  return;
1244
1246
  }
1245
1247
  for (const row of result.items) {
1246
- // The BUILD mark leads the line. A build is filed under its base's
1248
+ // The Look mark leads the line (`buildKind` is the field's API name;
1249
+ // "Look" is what a human reads). A Look is filed under its base's
1247
1250
  // own kind, so without it these rows are indistinguishable from the
1248
- // bases they were assembled from — which is the whole reason builds
1251
+ // bases they were assembled from — which is the whole reason Looks
1249
1252
  // do not get a category of their own.
1250
- const mark = row.buildKind ? `[build:${row.buildKind}] ` : '';
1253
+ const mark = row.buildKind ? `[look:${row.buildKind}] ` : '';
1251
1254
  const price = row.priceLix === null ? 'unlisted' : `Ⱡ${row.priceLix}`;
1252
1255
  console.log(`${mark}${row.title} (${row.kind}, ${price})`);
1253
1256
  console.log(` ${row.id}${row.creator ? ` by ${row.creator}` : ''}`);
@@ -1262,7 +1265,7 @@ item
1262
1265
  });
1263
1266
  item
1264
1267
  .command('build')
1265
- .description("What is in a published build: its base, its parts, what you own, and what the parts cost together")
1268
+ .description("What is in a published Look (API identifier: build): its base, its add-on parts, what you own, and what the parts cost together. A Look is never owned itself — only its parts are, each bought or held from its own listing")
1266
1269
  .argument('<itemId>', 'universal item id of the build')
1267
1270
  .option('--json', 'machine-readable output')
1268
1271
  .action(async (itemId, opts) => {
@@ -2161,6 +2164,113 @@ product
2161
2164
  fail(err instanceof lib_1.ApiError ? err.render() : `✖ ${err instanceof Error ? err.message : String(err)}`);
2162
2165
  }
2163
2166
  });
2167
+ // --- helix vault -------------------------------------------------------------
2168
+ // The Continuum Vault catalog (`GET /api/v1/vault/catalog`) — the table that
2169
+ // backs the website's Vault page and actually lists Looks (build Packages),
2170
+ // characters, vehicles, weapons, devices, and every other sealed Continuum
2171
+ // Package. Distinct from `helix assets search`, which hits the LEGACY
2172
+ // `/api/v1/vault/assets` table and has no Looks and never will.
2173
+ const vault = program
2174
+ .command('vault')
2175
+ .description('Discover sealed Continuum Packages — including Looks — through the public Vault catalog');
2176
+ vault
2177
+ .command('search')
2178
+ .description('Search the Continuum Vault catalog. Finds Looks (pass --package-type look) and every other sealed, listed Continuum Package. Public — no login required')
2179
+ .argument('[query]', 'free-text search over title and tags')
2180
+ .option('--package-type <type>', `filter by Continuum Package type. "look" is accepted as an alias for "build" (${vault_1.VAULT_CATALOG_PACKAGE_TYPE_INPUTS.join(', ')})`)
2181
+ .option('--sort <mode>', 'recent or name')
2182
+ .option('--cursor <token>', 'pagination cursor from a previous nextCursor')
2183
+ .option('--limit <n>', 'page size (1-100)')
2184
+ .action(async (query, opts) => {
2185
+ const creds = (0, config_1.loadCredentials)();
2186
+ const apiUrl = creds?.apiUrl ?? config_1.DEFAULT_API_URL;
2187
+ if (opts.sort && !['recent', 'name'].includes(opts.sort)) {
2188
+ fail('✖ --sort must be recent or name');
2189
+ }
2190
+ try {
2191
+ printJson(await (0, vault_1.searchVaultCatalog)(apiUrl, {
2192
+ q: query,
2193
+ packageType: opts.packageType,
2194
+ sort: opts.sort,
2195
+ cursor: opts.cursor,
2196
+ limit: optionalNumber(opts.limit, '--limit'),
2197
+ }, creds ?? undefined));
2198
+ }
2199
+ catch (err) {
2200
+ fail(err instanceof lib_1.ApiError ? err.render() : `✖ ${err instanceof Error ? err.message : String(err)}`);
2201
+ }
2202
+ });
2203
+ // --- helix look --------------------------------------------------------------
2204
+ // A Look is a Universal Item pinned to a Continuum Package of type `build`: a
2205
+ // free, never-owned preset — a base plus the exact add-ons installed on it.
2206
+ // Its parts are still owned and acquired individually from their own listings;
2207
+ // applying a Look never grants, buys, or moves anything the caller does not
2208
+ // already own. Contract: run/open-alpha-qa/looks/phase2-contract.txt (items 4
2209
+ // and 6) in the workspace root.
2210
+ const look = program
2211
+ .command('look')
2212
+ .description('Read and save Looks — dressed-character presets (API identifier: build)');
2213
+ look
2214
+ .command('get')
2215
+ .description('The dressed character behind one Look in a single public call: base model plus every add-on, with pinned Packages, model URLs/CIDs, and fit data — enough to render it')
2216
+ .argument('<ref>', 'Look item id, or packageId@version (an @ splits packageId from an explicit version; without one, the value is read as an item id)')
2217
+ .option('--json', 'machine-readable output')
2218
+ .action(async (ref, opts) => {
2219
+ const creds = (0, config_1.loadCredentials)();
2220
+ const apiUrl = creds?.apiUrl ?? config_1.DEFAULT_API_URL;
2221
+ const api = creds ? lib_1.HelixApi.forCredentials(creds) : new lib_1.HelixApi(apiUrl);
2222
+ try {
2223
+ const result = await (0, looks_1.resolveLook)(api, (0, looks_1.parseLookRef)(ref));
2224
+ if (opts.json)
2225
+ return printJson(result);
2226
+ console.log(`${result.look.title ?? result.look.packageId} (${result.look.kind})`);
2227
+ console.log(` base: ${result.base.item?.title ?? result.base.package.packageId}`);
2228
+ if (result.base.model)
2229
+ console.log(` ${result.base.model.url}`);
2230
+ for (const addOn of result.addOns) {
2231
+ console.log(` + [${addOn.slot}] ${addOn.item?.title ?? addOn.package.packageId}`);
2232
+ if (addOn.model)
2233
+ console.log(` ${addOn.model.url}`);
2234
+ }
2235
+ console.log(result.merged
2236
+ ? `\nmerged Runtime Artifact: ${result.merged.url}`
2237
+ : '\nno merged Runtime Artifact yet — assemble base + add-ons at runtime');
2238
+ }
2239
+ catch (err) {
2240
+ fail(err instanceof lib_1.ApiError ? err.render() : `✖ ${err instanceof Error ? err.message : String(err)}`);
2241
+ }
2242
+ });
2243
+ look
2244
+ .command('save')
2245
+ .description("Freeze an inventory instance's current composition into a Look. Never charges a publish fee, never grants a copy of any part, never creates a distribution — it publishes the recipe, not the parts")
2246
+ .argument('<inventory-item-id>', 'inventory instance to freeze')
2247
+ .requiredOption('--title <title>', 'Look title (1-80 chars)')
2248
+ .option('--description <text>', 'Look description (<=500 chars)')
2249
+ .option('--public', 'publish publicly (sealed public Package + Vault + Marketplace listings); default is private')
2250
+ .option('--look <lookItemId>', 'an existing Look you created — advances it to a new version instead of creating a new one')
2251
+ .option('--json', 'machine-readable output')
2252
+ .action(async (inventoryItemId, opts) => {
2253
+ const creds = requireAuth();
2254
+ try {
2255
+ const result = await (0, looks_1.saveLook)(lib_1.HelixApi.forCredentials(creds), inventoryItemId, {
2256
+ title: opts.title,
2257
+ description: opts.description,
2258
+ visibility: opts.public ? 'public' : 'private',
2259
+ lookItemId: opts.look,
2260
+ });
2261
+ if (opts.json)
2262
+ return printJson(result);
2263
+ console.log(`✔ ${result.created ? 'Saved' : 'Updated'} Look ${result.lookItemId} (${result.visibility})`);
2264
+ console.log(` package: ${result.package.packageId}@${result.package.version}`);
2265
+ if (result.vaultListingId)
2266
+ console.log(` vault listing: ${result.vaultListingId}`);
2267
+ if (result.marketplaceListingId)
2268
+ console.log(` marketplace listing: ${result.marketplaceListingId}`);
2269
+ }
2270
+ catch (err) {
2271
+ fail(err instanceof lib_1.ApiError ? err.render() : `✖ ${err instanceof Error ? err.message : String(err)}`);
2272
+ }
2273
+ });
2164
2274
  // --- helix assets ----------------------------------------------------------
2165
2275
  // Operational asset work lives here. MCP surfaces may point agents at these
2166
2276
  // commands, but they must not reimplement Vault, Dreamer, download, or receipt