@vgai/cli 0.4.1-canary.20260715.0 → 0.4.1

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 (3) hide show
  1. package/README.md +1 -1
  2. package/dist/index.js +63 -53
  3. package/package.json +8 -8
package/README.md CHANGED
@@ -42,7 +42,7 @@ vgai select <id> | --all | deselect selection
42
42
  vgai focus [id] | view <top|front|right|perspective>
43
43
  vgai show <viewport scene|game / inspector / console / build>
44
44
  vgai open-asset <path> <kind>
45
- vgai grid|helpers|stats <on|off> | shading <solid|wireframe|unlit>
45
+ vgai grid|helpers|stats <on|off> | shading <solid|unlit|wireframe|normals|overdraw>
46
46
  vgai status print full editor state as JSON
47
47
 
48
48
  vgai apply-diff <scene> <patch> [--report] apply a SceneDiff patch to a scene
package/dist/index.js CHANGED
@@ -261411,26 +261411,26 @@ var EditorClient = class {
261411
261411
  const data = await res.json();
261412
261412
  return data.projects;
261413
261413
  }
261414
- // --- Project operations ---
261415
- /** List live project-local operation definitions below `src/operations/`.
261416
- * The editor server loads metadata in Node; operation modules never enter the
261414
+ // --- Registered project tools ---
261415
+ /** List tools explicitly registered in `package.json#vgai.tools`.
261416
+ * The editor server loads callable metadata in Node; modules never enter the
261417
261417
  * editor browser merely because they were listed. */
261418
- async listProjectOperations() {
261419
- const res = await fetch(`${this.baseUrl}/__editor/project-operations`);
261420
- if (!res.ok) throw new Error(`Failed to list project operations: ${res.status}`);
261418
+ async listProjectTools() {
261419
+ const res = await fetch(`${this.baseUrl}/__editor/project-tools`);
261420
+ if (!res.ok) throw new Error(`Failed to list project tools: ${res.status}`);
261421
261421
  return await res.json();
261422
261422
  }
261423
- /** Execute one Node-hosted project operation through the existing validated
261424
- * operation registry. Write/destructive operations require `confirm:true`. */
261425
- async runProjectOperation(name, input = {}, options = {}) {
261426
- const res = await fetch(`${this.baseUrl}/__editor/project-operations/run`, {
261423
+ /** Execute one Node-hosted project tool through the shared validated
261424
+ * dispatcher. Write/destructive tools require `confirm:true`. */
261425
+ async runProjectTool(name, input = {}, options = {}) {
261426
+ const res = await fetch(`${this.baseUrl}/__editor/project-tools/run`, {
261427
261427
  method: "POST",
261428
261428
  headers: { "Content-Type": "application/json" },
261429
261429
  body: JSON.stringify({ name, input, confirm: options.confirm === true })
261430
261430
  });
261431
261431
  const body = await res.json();
261432
261432
  if (!body || typeof body !== "object" || typeof body.ok !== "boolean") {
261433
- throw new Error(`Project operation returned an invalid response (${res.status}).`);
261433
+ throw new Error(`Project tool returned an invalid response (${res.status}).`);
261434
261434
  }
261435
261435
  return body;
261436
261436
  }
@@ -275248,7 +275248,9 @@ var CORE_ERROR_CODES = {
275248
275248
  /** The impl threw something that isn't a declared, structured error. */
275249
275249
  INTERNAL_ERROR: "INTERNAL_ERROR"
275250
275250
  };
275251
+ var OPERATION_ERROR_BRAND = Symbol.for("@vgai/sdk.OperationError");
275251
275252
  var OperationError = class extends Error {
275253
+ [OPERATION_ERROR_BRAND] = true;
275252
275254
  code;
275253
275255
  data;
275254
275256
  constructor(code, message, data) {
@@ -275258,6 +275260,12 @@ var OperationError = class extends Error {
275258
275260
  this.data = data;
275259
275261
  }
275260
275262
  };
275263
+ function isOperationError(value) {
275264
+ if (value instanceof OperationError) return true;
275265
+ if (value === null || typeof value !== "object") return false;
275266
+ const candidate = value;
275267
+ return candidate[OPERATION_ERROR_BRAND] === true && typeof candidate["code"] === "string" && typeof candidate["message"] === "string";
275268
+ }
275261
275269
  function toStructuredIssues(issues) {
275262
275270
  return issues.map((issue2) => ({
275263
275271
  path: [...issue2.path],
@@ -275299,7 +275307,7 @@ function defineOperation(def) {
275299
275307
  return def;
275300
275308
  }
275301
275309
  function normalizeThrown(def, err2) {
275302
- if (err2 instanceof OperationError) {
275310
+ if (isOperationError(err2)) {
275303
275311
  const declared = def.errors.find((e) => e.code === err2.code);
275304
275312
  if (!declared) {
275305
275313
  return {
@@ -283632,7 +283640,7 @@ function writeScaffoldBaseline(targetDir, engineVersion, engineDir) {
283632
283640
  }
283633
283641
 
283634
283642
  // ../create-vgai-project/src/engine-version.ts
283635
- var SEMVER_RE2 = /^(\d+)\.(\d+)\.(\d+)(?:-[0-9A-Za-z-.]+)?(?:\+[0-9A-Za-z-.]+)?$/;
283643
+ var SEMVER_RE2 = /^(\d+)\.(\d+)\.(\d+)(?:-([0-9A-Za-z-.]+))?(?:\+([0-9A-Za-z-.]+))?$/;
283636
283644
  function parseSemver(version2) {
283637
283645
  const match = SEMVER_RE2.exec(version2);
283638
283646
  if (!match) return null;
@@ -283645,15 +283653,39 @@ function compareTuples(a, b) {
283645
283653
  }
283646
283654
  return 0;
283647
283655
  }
283656
+ function comparePrerelease(a, b) {
283657
+ if (a === b) return 0;
283658
+ if (a === void 0) return 1;
283659
+ if (b === void 0) return -1;
283660
+ const aParts = a.split(".");
283661
+ const bParts = b.split(".");
283662
+ for (let index = 0; index < Math.max(aParts.length, bParts.length); index++) {
283663
+ const aPart = aParts[index];
283664
+ const bPart = bParts[index];
283665
+ if (aPart === void 0) return -1;
283666
+ if (bPart === void 0) return 1;
283667
+ if (aPart === bPart) continue;
283668
+ const aNumeric = /^\d+$/.test(aPart);
283669
+ const bNumeric = /^\d+$/.test(bPart);
283670
+ if (aNumeric && bNumeric) return Number(aPart) < Number(bPart) ? -1 : 1;
283671
+ if (aNumeric !== bNumeric) return aNumeric ? -1 : 1;
283672
+ return aPart < bPart ? -1 : 1;
283673
+ }
283674
+ return 0;
283675
+ }
283648
283676
  function compareEnginePin(pin, current) {
283677
+ const pinMatch = SEMVER_RE2.exec(pin);
283678
+ const currentMatch = SEMVER_RE2.exec(current);
283649
283679
  const pinTuple = parseSemver(pin);
283650
283680
  const currentTuple = parseSemver(current);
283651
283681
  if (!pinTuple || !currentTuple) {
283652
283682
  const reason = !pinTuple && !currentTuple ? `neither pin "${pin}" nor current "${current}" is a valid exact semver string` : !pinTuple ? `pin "${pin}" is not a valid exact semver string` : `current "${current}" is not a valid exact semver string`;
283653
283683
  return { status: "invalid", pin, current, reason };
283654
283684
  }
283655
- const cmp = compareTuples(pinTuple, currentTuple);
283656
- const status = cmp === 0 ? "match" : cmp < 0 ? "pin-behind" : "pin-ahead";
283685
+ if (pin === current) return { status: "match", pin, current };
283686
+ const tupleCmp = compareTuples(pinTuple, currentTuple);
283687
+ const cmp = tupleCmp !== 0 ? tupleCmp : comparePrerelease(pinMatch?.[4], currentMatch?.[4]) || -1;
283688
+ const status = cmp < 0 ? "pin-behind" : "pin-ahead";
283657
283689
  return { status, pin, current };
283658
283690
  }
283659
283691
  function satisfiesRange(version2, range) {
@@ -284072,26 +284104,6 @@ test('React-only root mounts and receives honest DOM keyboard input', async ({ g
284072
284104
  await game.screenshot('react-root-after-keyboard-input');
284073
284105
  });
284074
284106
  `;
284075
- var REACT_ONLY_PLAYTEST_SOURCE = `import { editor, game } from '@vgai/live';
284076
-
284077
- await editor.play();
284078
- await game.waitFor(
284079
- (state) =>
284080
- (state('react-starter') as { lastInput?: string } | undefined)?.lastInput === 'Ready',
284081
- { simSeconds: 10 },
284082
- );
284083
- await game.page(async (page) => {
284084
- await page.keyboard.press('ArrowRight');
284085
- });
284086
- await game.waitFor(
284087
- (state) =>
284088
- (state('react-starter') as { lastInput?: string } | undefined)?.lastInput === 'ArrowRight',
284089
- { simSeconds: 10 },
284090
- );
284091
- const shot = await game.screenshot('react-playtest-after-keyboard-input');
284092
- console.log('React-only DOM input reached the game.');
284093
- console.log('screenshot: ' + shot);
284094
- `;
284095
284107
  var REACT_ONLY_MAIN_SOURCE = `import { manifestEntryModules } from 'virtual:vgai-manifest-entries';
284096
284108
  import { registerReactAdapter } from '@engine/react/root-adapter';
284097
284109
  import { mountGameFromManifest, type ManifestHost } from '@engine/runtime/mount-game';
@@ -284126,7 +284138,6 @@ function rewriteTemplateVariantFiles(targetDir, template) {
284126
284138
  if (template !== "react") return;
284127
284139
  rmSync(join15(targetDir, "src", "runtime"), { recursive: true, force: true });
284128
284140
  rmSync(join15(targetDir, "src", "scripts"), { recursive: true, force: true });
284129
- rmSync(join15(targetDir, "src", "tools"), { recursive: true, force: true });
284130
284141
  rmSync(join15(targetDir, "tests", "logic", "example.test.ts"), { force: true });
284131
284142
  rmSync(join15(targetDir, "public"), { recursive: true, force: true });
284132
284143
  mkdirSync4(join15(targetDir, "public"), { recursive: true });
@@ -284138,7 +284149,6 @@ function rewriteTemplateVariantFiles(targetDir, template) {
284138
284149
  REACT_ONLY_ACCEPTANCE_SOURCE,
284139
284150
  "utf-8"
284140
284151
  );
284141
- writeFileSync3(join15(targetDir, "scripts", "playtest.ts"), REACT_ONLY_PLAYTEST_SOURCE, "utf-8");
284142
284152
  }
284143
284153
  function rewriteTsconfig(targetDir, engineRelPath, editorRelPath) {
284144
284154
  const tsconfigPath = join15(targetDir, "tsconfig.json");
@@ -296655,8 +296665,8 @@ function defaultCreateDependencyMode() {
296655
296665
  return existsSync21(join25(ENGINE_ROOT, "packages", "engine")) ? "link" : "registry";
296656
296666
  }
296657
296667
  function cliVersion() {
296658
- if ("0.4.1-canary.20260715.0") {
296659
- return "0.4.1-canary.20260715.0";
296668
+ if ("0.4.1") {
296669
+ return "0.4.1";
296660
296670
  }
296661
296671
  try {
296662
296672
  const pkg = JSON.parse(readFileSync20(join25(__dirname4, "..", "package.json"), "utf8"));
@@ -296675,7 +296685,7 @@ function bakedTargetVersions() {
296675
296685
  if (false)
296676
296686
  return void 0;
296677
296687
  try {
296678
- return JSON.parse('{"@vgai/engine":"0.4.1-canary.20260715.0","@vgai/editor":"0.4.1-canary.20260715.0","@vgai/p2p-colyseus":"0.4.1-canary.20260715.0","@vgai/probe":"0.4.1-canary.20260715.0","@vgai/live":"0.4.1-canary.20260715.0","@vgai/sdk":"0.4.1-canary.20260715.0","@vgai/editor-sdk":"0.4.1-canary.20260715.0","@vgai/cli":"0.4.1-canary.20260715.0"}');
296688
+ return JSON.parse('{"@vgai/engine":"0.4.1","@vgai/editor":"0.4.1","@vgai/p2p-colyseus":"0.4.1","@vgai/probe":"0.4.1","@vgai/live":"0.4.1","@vgai/sdk":"0.4.1","@vgai/editor-sdk":"0.4.1","@vgai/cli":"0.4.1"}');
296679
296689
  } catch {
296680
296690
  return void 0;
296681
296691
  }
@@ -296765,7 +296775,7 @@ Project:
296765
296775
  run <name> Run a Node-hosted project capability with validated JSON input
296766
296776
  --describe Print the selected capability's schemas and metadata without running
296767
296777
  --input <file|-> Read input JSON from a file or stdin (default: {})
296768
- --yes Confirm write/destructive operation execution
296778
+ --yes Confirm write/destructive tool execution
296769
296779
  --json Print the full machine-readable catalog/outcome
296770
296780
  upgrade [folder] Report + re-sync + re-pin against this engine checkout (default: cwd)
296771
296781
  --report Report only \u2014 never write to disk
@@ -296938,7 +296948,7 @@ Display:
296938
296948
  grid <on|off> Set grid visibility
296939
296949
  helpers <on|off> Set helpers visibility
296940
296950
  stats <on|off> Set stats overlay
296941
- shading <mode> Set shading: solid, wireframe, unlit
296951
+ shading <mode> Set active viewport shading: solid, unlit, wireframe, normals, overdraw
296942
296952
 
296943
296953
  State:
296944
296954
  status Print full editor state
@@ -298603,12 +298613,12 @@ async function run() {
298603
298613
  console.error(usage);
298604
298614
  process.exit(EXIT_CODES.VALIDATION_ERROR);
298605
298615
  }
298606
- const catalog = await getClient().listProjectOperations();
298616
+ const catalog = await getClient().listProjectTools();
298607
298617
  if (runArgs.includes("--json")) {
298608
298618
  console.log(JSON.stringify(catalog, null, 2));
298609
298619
  break;
298610
298620
  }
298611
- for (const operation of catalog.operations) {
298621
+ for (const operation of catalog.tools) {
298612
298622
  console.log(
298613
298623
  `${operation.name} ${operation.host} ${operation.permission.risk} ${operation.summary}`
298614
298624
  );
@@ -298616,8 +298626,8 @@ async function run() {
298616
298626
  for (const error48 of catalog.loadErrors) {
298617
298627
  console.error(`\u2717 ${error48.sourcePath}: ${error48.message}`);
298618
298628
  }
298619
- if (catalog.operations.length === 0 && catalog.loadErrors.length === 0) {
298620
- console.log("No project operations found.");
298629
+ if (catalog.tools.length === 0 && catalog.loadErrors.length === 0) {
298630
+ console.log("No project tools found.");
298621
298631
  }
298622
298632
  break;
298623
298633
  }
@@ -298630,8 +298640,8 @@ async function run() {
298630
298640
  console.error(usage);
298631
298641
  process.exit(EXIT_CODES.VALIDATION_ERROR);
298632
298642
  }
298633
- const catalog = await getClient().listProjectOperations();
298634
- const operation = catalog.operations.find((entry) => entry.name === name);
298643
+ const catalog = await getClient().listProjectTools();
298644
+ const operation = catalog.tools.find((entry) => entry.name === name);
298635
298645
  if (!operation) {
298636
298646
  console.error(`No project capability is named ${JSON.stringify(name)}.`);
298637
298647
  process.exit(EXIT_CODES.VALIDATION_ERROR);
@@ -298666,12 +298676,12 @@ ${JSON.stringify(operation.resultSchema, null, 2)}`);
298666
298676
  );
298667
298677
  } catch (error48) {
298668
298678
  console.error(
298669
- `Invalid operation input JSON: ${error48 instanceof Error ? error48.message : error48}`
298679
+ `Invalid tool input JSON: ${error48 instanceof Error ? error48.message : error48}`
298670
298680
  );
298671
298681
  process.exit(EXIT_CODES.VALIDATION_ERROR);
298672
298682
  }
298673
298683
  }
298674
- const outcome = await getClient().runProjectOperation(name, input, {
298684
+ const outcome = await getClient().runProjectTool(name, input, {
298675
298685
  confirm: runArgs.includes("--yes")
298676
298686
  });
298677
298687
  console.log(JSON.stringify(outcome, null, 2));
@@ -299423,11 +299433,11 @@ Choose exactly one target: project, --port, or --all.`);
299423
299433
  break;
299424
299434
  case "shading":
299425
299435
  if (hasHelpFlag(args)) {
299426
- console.log("Usage: vgai shading <solid|wireframe|unlit>");
299436
+ console.log("Usage: vgai shading <solid|unlit|wireframe|normals|overdraw>");
299427
299437
  break;
299428
299438
  }
299429
- if (!args[1]) {
299430
- console.error("Usage: vgai shading <solid|wireframe|unlit>");
299439
+ if (!["solid", "unlit", "wireframe", "normals", "overdraw"].includes(args[1] ?? "")) {
299440
+ console.error("Usage: vgai shading <solid|unlit|wireframe|normals|overdraw>");
299431
299441
  process.exit(1);
299432
299442
  }
299433
299443
  await getClient().setShadingMode(args[1]);
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@vgai/cli",
3
3
  "author": "Volter AI, Inc.",
4
4
  "license": "Apache-2.0",
5
- "version": "0.4.1-canary.20260715.0",
5
+ "version": "0.4.1",
6
6
  "type": "module",
7
7
  "repository": {
8
8
  "type": "git",
@@ -28,13 +28,13 @@
28
28
  },
29
29
  "dependencies": {
30
30
  "@oclif/core": "^4.11.14",
31
- "@vgai/editor": "0.4.1-canary.20260715.0",
32
- "@vgai/editor-sdk": "0.4.1-canary.20260715.0",
33
- "@vgai/engine": "0.4.1-canary.20260715.0",
34
- "@vgai/live": "0.4.1-canary.20260715.0",
35
- "@vgai/p2p-colyseus": "0.4.1-canary.20260715.0",
36
- "@vgai/probe": "0.4.1-canary.20260715.0",
37
- "@vgai/sdk": "0.4.1-canary.20260715.0",
31
+ "@vgai/editor": "0.4.1",
32
+ "@vgai/editor-sdk": "0.4.1",
33
+ "@vgai/engine": "0.4.1",
34
+ "@vgai/live": "0.4.1",
35
+ "@vgai/p2p-colyseus": "0.4.1",
36
+ "@vgai/probe": "0.4.1",
37
+ "@vgai/sdk": "0.4.1",
38
38
  "ink": "^7.1.0",
39
39
  "playwright": "^1.58.2",
40
40
  "react": "^19.2.4",