@forgeax/engine-devkit 0.1.4 → 0.1.6

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 (51) hide show
  1. package/README.md +19 -4
  2. package/dist/.tsbuildinfo +1 -1
  3. package/dist/__tests__/cli-output.unit.test.d.ts +2 -0
  4. package/dist/__tests__/cli-output.unit.test.d.ts.map +1 -0
  5. package/dist/__tests__/gltf-source-key-diagnostics.integration.test.d.ts +2 -0
  6. package/dist/__tests__/gltf-source-key-diagnostics.integration.test.d.ts.map +1 -0
  7. package/dist/__tests__/preview-port.integration.test.d.ts +2 -0
  8. package/dist/__tests__/preview-port.integration.test.d.ts.map +1 -0
  9. package/dist/__tests__/rhi-debug-build-graph.integration.test.d.ts +2 -0
  10. package/dist/__tests__/rhi-debug-build-graph.integration.test.d.ts.map +1 -0
  11. package/dist/__tests__/sdk-update.unit.test.d.ts +2 -0
  12. package/dist/__tests__/sdk-update.unit.test.d.ts.map +1 -0
  13. package/dist/assets.d.ts.map +1 -1
  14. package/dist/bootstrap-commands.d.ts.map +1 -1
  15. package/dist/cli-output.d.ts +4 -0
  16. package/dist/cli-output.d.ts.map +1 -0
  17. package/dist/cli.mjs +380 -567
  18. package/dist/cli.mjs.map +1 -1
  19. package/dist/commands.d.ts.map +1 -1
  20. package/dist/host/__tests__/bootstrap-root-owner.test-d.d.ts +2 -0
  21. package/dist/host/__tests__/bootstrap-root-owner.test-d.d.ts.map +1 -0
  22. package/dist/host/project-bootstrap.d.ts +4 -2
  23. package/dist/host/project-bootstrap.d.ts.map +1 -1
  24. package/dist/host/resource-bootstrap.d.ts +5 -3
  25. package/dist/host/resource-bootstrap.d.ts.map +1 -1
  26. package/dist/host.d.ts +2 -1
  27. package/dist/host.d.ts.map +1 -1
  28. package/dist/index.d.ts +4 -0
  29. package/dist/index.d.ts.map +1 -1
  30. package/dist/index.mjs +303 -570
  31. package/dist/index.mjs.map +1 -1
  32. package/dist/project.d.ts +0 -1
  33. package/dist/project.d.ts.map +1 -1
  34. package/dist/rhi-debug/cli-context.d.ts.map +1 -1
  35. package/dist/sdk-bootstrap.d.ts +9 -0
  36. package/dist/sdk-bootstrap.d.ts.map +1 -1
  37. package/dist/sdk-cli.mjs +190 -24
  38. package/dist/sdk-cli.mjs.map +1 -1
  39. package/dist/sdk-install.d.ts.map +1 -1
  40. package/dist/sdk-update.d.ts +23 -0
  41. package/dist/sdk-update.d.ts.map +1 -0
  42. package/dist/tools/benchmark/__tests__/benchmark-vocabulary-owner.test-d.d.ts +2 -0
  43. package/dist/tools/benchmark/__tests__/benchmark-vocabulary-owner.test-d.d.ts.map +1 -0
  44. package/dist/tools/benchmark/harness.d.ts.map +1 -1
  45. package/dist/tools/browser-host.d.ts.map +1 -1
  46. package/dist/tools/native-preview.d.ts.map +1 -1
  47. package/dist/types.d.ts +7 -0
  48. package/dist/types.d.ts.map +1 -1
  49. package/package.json +29 -30
  50. package/dist/__tests__/tool-migration.test.d.ts +0 -2
  51. package/dist/__tests__/tool-migration.test.d.ts.map +0 -1
package/dist/project.d.ts CHANGED
@@ -1,5 +1,4 @@
1
1
  import type { CommandError, CommandResult, ProjectFacts } from './types.js';
2
2
  export declare function readProjectFacts(rootInput?: string): Promise<CommandResult<ProjectFacts>>;
3
- export declare function isCommandError(value: unknown): value is CommandError;
4
3
  export declare function commandError(cause: unknown, fallbackCode: string): CommandError;
5
4
  //# sourceMappingURL=project.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"project.d.ts","sourceRoot":"","sources":["../src/project.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,YAAY,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAyC5E,wBAAsB,gBAAgB,CACpC,SAAS,SAAgB,GACxB,OAAO,CAAC,aAAa,CAAC,YAAY,CAAC,CAAC,CAiItC;AAED,wBAAgB,cAAc,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,YAAY,CAWpE;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,GAAG,YAAY,CAQ/E"}
1
+ {"version":3,"file":"project.d.ts","sourceRoot":"","sources":["../src/project.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,YAAY,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAyC5E,wBAAsB,gBAAgB,CACpC,SAAS,SAAgB,GACxB,OAAO,CAAC,aAAa,CAAC,YAAY,CAAC,CAAC,CAiItC;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,GAAG,YAAY,CAiB/E"}
@@ -1 +1 @@
1
- {"version":3,"file":"cli-context.d.ts","sourceRoot":"","sources":["../../src/rhi-debug/cli-context.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAe,wBAAwB,EAAE,MAAM,iBAAiB,CAAC;AAE7E,wBAAgB,iCAAiC,IAAI,wBAAwB,CAkE5E"}
1
+ {"version":3,"file":"cli-context.d.ts","sourceRoot":"","sources":["../../src/rhi-debug/cli-context.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAe,wBAAwB,EAAE,MAAM,iBAAiB,CAAC;AAE7E,wBAAgB,iCAAiC,IAAI,wBAAwB,CAmE5E"}
@@ -13,7 +13,16 @@ export interface SdkInitState {
13
13
  export interface SdkInitReport extends SdkInitState {
14
14
  readonly root: string;
15
15
  readonly store: 'offline' | 'registry';
16
+ readonly onboarding: AgentOnboarding;
16
17
  }
18
+ export interface AgentOnboarding {
19
+ readonly read: readonly string[];
20
+ readonly next: {
21
+ readonly cwd: string;
22
+ readonly argv: readonly string[];
23
+ };
24
+ }
25
+ export declare function agentOnboarding(sdk: SdkContext, projectRoot?: string): AgentOnboarding;
17
26
  export declare function sdkProjectInstallArgs(store: string | undefined): string[];
18
27
  export declare function readSdkInitState(sdk: SdkContext): Promise<SdkInitState | undefined>;
19
28
  export declare function requireSdkInitialization(sdk: SdkContext): Promise<CommandResult<SdkInitState>>;
@@ -1 +1 @@
1
- {"version":3,"file":"sdk-bootstrap.d.ts","sourceRoot":"","sources":["../src/sdk-bootstrap.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAC3C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAIhD,QAAA,MAAM,uBAAuB,EAAG,OAAgB,CAAC;AAEjD,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,aAAa,EAAE,OAAO,uBAAuB,CAAC;IACvD,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC,QAAQ,CAAC;IACnC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,aAAc,SAAQ,YAAY;IACjD,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,KAAK,EAAE,SAAS,GAAG,UAAU,CAAC;CACxC;AAeD,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,EAAE,CAWzE;AAkDD,wBAAsB,gBAAgB,CAAC,GAAG,EAAE,UAAU,GAAG,OAAO,CAAC,YAAY,GAAG,SAAS,CAAC,CAOzF;AAED,wBAAsB,wBAAwB,CAC5C,GAAG,EAAE,UAAU,GACd,OAAO,CAAC,aAAa,CAAC,YAAY,CAAC,CAAC,CAkBtC;AAsBD,wBAAsB,cAAc,CAClC,GAAG,EAAE,UAAU,EACf,OAAO,GAAE;IAAE,QAAQ,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,CAAA;CAAO,GACtE,OAAO,CAAC,aAAa,CAAC,aAAa,CAAC,CAAC,CAiDvC"}
1
+ {"version":3,"file":"sdk-bootstrap.d.ts","sourceRoot":"","sources":["../src/sdk-bootstrap.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAC3C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAIhD,QAAA,MAAM,uBAAuB,EAAG,OAAgB,CAAC;AAEjD,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,aAAa,EAAE,OAAO,uBAAuB,CAAC;IACvD,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC,QAAQ,CAAC;IACnC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,aAAc,SAAQ,YAAY;IACjD,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,KAAK,EAAE,SAAS,GAAG,UAAU,CAAC;IACvC,QAAQ,CAAC,UAAU,EAAE,eAAe,CAAC;CACtC;AAED,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,CAAC;IACjC,QAAQ,CAAC,IAAI,EAAE;QACb,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;QACrB,QAAQ,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,CAAC;KAClC,CAAC;CACH;AAED,wBAAgB,eAAe,CAAC,GAAG,EAAE,UAAU,EAAE,WAAW,CAAC,EAAE,MAAM,GAAG,eAAe,CAgBtF;AAeD,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,EAAE,CAWzE;AAkDD,wBAAsB,gBAAgB,CAAC,GAAG,EAAE,UAAU,GAAG,OAAO,CAAC,YAAY,GAAG,SAAS,CAAC,CAOzF;AAED,wBAAsB,wBAAwB,CAC5C,GAAG,EAAE,UAAU,GACd,OAAO,CAAC,aAAa,CAAC,YAAY,CAAC,CAAC,CAkBtC;AAsBD,wBAAsB,cAAc,CAClC,GAAG,EAAE,UAAU,EACf,OAAO,GAAE;IAAE,QAAQ,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,CAAA;CAAO,GACtE,OAAO,CAAC,aAAa,CAAC,aAAa,CAAC,CAAC,CAkDvC"}
package/dist/sdk-cli.mjs CHANGED
@@ -1,9 +1,9 @@
1
1
  #!/usr/bin/env node
2
+ import { execFile, spawn } from 'child_process';
2
3
  import { resolve, dirname, basename, relative, sep, isAbsolute } from 'path';
3
- import { pathToFileURL, fileURLToPath } from 'url';
4
- import { execFile } from 'child_process';
5
4
  import { readdir, mkdir, mkdtemp, cp, rename, rm, copyFile, readFile, realpath, writeFile, symlink, access, lstat, readlink, rmdir } from 'fs/promises';
6
5
  import { promisify } from 'util';
6
+ import { fileURLToPath } from 'url';
7
7
  import { tmpdir } from 'os';
8
8
 
9
9
  var __defProp = Object.defineProperty;
@@ -4776,7 +4776,7 @@ async function readJson(path) {
4776
4776
  function firstUnsupportedStandaloneRealm(entries, inheritedRealm = "engine") {
4777
4777
  for (const entry of entries) {
4778
4778
  const realm = entry.realm ?? inheritedRealm ?? "engine";
4779
- if (realm === "host") return { id: entry.id, realm };
4779
+ if (realm !== "engine") return { id: entry.id, realm };
4780
4780
  if (entry.group === true) {
4781
4781
  const unsupported = firstUnsupportedStandaloneRealm(
4782
4782
  entry.config,
@@ -4894,13 +4894,10 @@ async function readProjectFacts(rootInput = process.cwd()) {
4894
4894
  }
4895
4895
  };
4896
4896
  }
4897
- function isCommandError(value) {
4898
- if (value === null || typeof value !== "object" || Array.isArray(value)) return false;
4899
- const candidate = value;
4900
- return typeof candidate.code === "string" && typeof candidate.expected === "string" && typeof candidate.hint === "string" && candidate.detail !== null && typeof candidate.detail === "object" && !Array.isArray(candidate.detail);
4901
- }
4902
4897
  function commandError(cause, fallbackCode) {
4903
- if (isCommandError(cause)) return cause;
4898
+ if (cause !== null && typeof cause === "object" && "code" in cause && "expected" in cause && "hint" in cause && "detail" in cause) {
4899
+ return cause;
4900
+ }
4904
4901
  return {
4905
4902
  code: fallbackCode,
4906
4903
  expected: "the ForgeaX command to complete",
@@ -4945,6 +4942,20 @@ async function findSdkContext() {
4945
4942
  var execFileAsync = promisify(execFile);
4946
4943
  var SDK_INIT_PATH = [".forgeax", "sdk-init.json"];
4947
4944
  var SDK_INIT_SCHEMA_VERSION = "1.0.0";
4945
+ function agentOnboarding(sdk, projectRoot) {
4946
+ const root2 = projectRoot ?? sdk.root;
4947
+ return {
4948
+ read: [
4949
+ resolve(root2, "AGENTS.md"),
4950
+ resolve(root2, "skills", "forgeax-engine-sdk", "SKILL.md"),
4951
+ resolve(root2, "skills", "forgeax-engine-sdk", "references", "feature-catalog.md")
4952
+ ],
4953
+ next: projectRoot === void 0 ? {
4954
+ cwd: root2,
4955
+ argv: ["node", "./bin/forgeax.mjs", "new", "../my-game"]
4956
+ } : { cwd: root2, argv: ["pnpm", "exec", "forgeax", "list", "--json"] }
4957
+ };
4958
+ }
4948
4959
  function sdkInitPath(sdk) {
4949
4960
  return resolve(sdk.root, ...SDK_INIT_PATH);
4950
4961
  }
@@ -4959,7 +4970,7 @@ function sdkProjectInstallArgs(store) {
4959
4970
  "--side-effects-cache=true",
4960
4971
  "--child-concurrency=1"
4961
4972
  ];
4962
- return store === void 0 ? common : [...common, "--offline", "--trust-lockfile", "--store-dir", store];
4973
+ return store === void 0 ? common : [...common, "--offline", "--config.trust-lockfile=true", "--store-dir", store];
4963
4974
  }
4964
4975
  function sdkBootstrapInstallArgs(store) {
4965
4976
  const common = [
@@ -4968,7 +4979,7 @@ function sdkBootstrapInstallArgs(store) {
4968
4979
  "--child-concurrency=1",
4969
4980
  "--side-effects-cache=true"
4970
4981
  ];
4971
- return store === void 0 ? common : [...common, "--offline", "--trust-lockfile", "--store-dir", store];
4982
+ return store === void 0 ? common : [...common, "--offline", "--config.trust-lockfile=true", "--store-dir", store];
4972
4983
  }
4973
4984
  function supportedPnpm(version) {
4974
4985
  const [major = 0, minor = 0] = version.split(".").map(Number);
@@ -5058,7 +5069,8 @@ async function sdkInitCommand(sdk, options = {}) {
5058
5069
  const report = {
5059
5070
  ...state,
5060
5071
  root: sdk.root,
5061
- store: sdk.store === void 0 ? "registry" : "offline"
5072
+ store: sdk.store === void 0 ? "registry" : "offline",
5073
+ onboarding: agentOnboarding(sdk)
5062
5074
  };
5063
5075
  if (options.dryRun === true || options.install === false) return { ok: true, value: report };
5064
5076
  let staging;
@@ -5085,6 +5097,102 @@ async function sdkInitCommand(sdk, options = {}) {
5085
5097
  if (staging !== void 0) await rm(staging, { recursive: true, force: true });
5086
5098
  }
5087
5099
  }
5100
+
5101
+ // src/sdk-update.ts
5102
+ var UPDATE_MIGRATION_RISK = "Install a newer SDK in a separate directory. Existing games remain pinned and are not migrated automatically; review release notes and migrate and test each game before changing its Engine version.";
5103
+ function parseVersion(version) {
5104
+ const match = /^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-([0-9A-Za-z.-]+))?(?:\+[0-9A-Za-z.-]+)?$/.exec(
5105
+ version
5106
+ );
5107
+ if (match === null) return void 0;
5108
+ const major = match[1];
5109
+ const minor = match[2];
5110
+ const patch = match[3];
5111
+ if (major === void 0 || minor === void 0 || patch === void 0) return void 0;
5112
+ const prerelease = match[4]?.split(".");
5113
+ if (prerelease?.some(
5114
+ (identifier) => identifier.length === 0 || /^\d+$/.test(identifier) && /^0\d+/.test(identifier)
5115
+ )) {
5116
+ return void 0;
5117
+ }
5118
+ return {
5119
+ core: [major, minor, patch],
5120
+ ...prerelease === void 0 ? {} : { prerelease }
5121
+ };
5122
+ }
5123
+ function compareNumericIdentifier(current, latest) {
5124
+ if (current.length !== latest.length) return latest.length > current.length ? 1 : -1;
5125
+ if (current === latest) return 0;
5126
+ return latest > current ? 1 : -1;
5127
+ }
5128
+ function comparePrerelease(current, latest) {
5129
+ const length = Math.max(current.length, latest.length);
5130
+ for (let index = 0; index < length; index += 1) {
5131
+ const currentIdentifier = current[index];
5132
+ const latestIdentifier = latest[index];
5133
+ if (currentIdentifier === void 0) return 1;
5134
+ if (latestIdentifier === void 0) return -1;
5135
+ if (currentIdentifier === latestIdentifier) continue;
5136
+ const currentNumeric = /^\d+$/.test(currentIdentifier);
5137
+ const latestNumeric = /^\d+$/.test(latestIdentifier);
5138
+ if (currentNumeric && latestNumeric) {
5139
+ return compareNumericIdentifier(currentIdentifier, latestIdentifier);
5140
+ }
5141
+ if (currentNumeric !== latestNumeric) return latestNumeric ? -1 : 1;
5142
+ return latestIdentifier > currentIdentifier ? 1 : -1;
5143
+ }
5144
+ return 0;
5145
+ }
5146
+ function newerSdkVersion(currentVersion, latestVersion) {
5147
+ const current = parseVersion(currentVersion);
5148
+ const latest = parseVersion(latestVersion);
5149
+ if (current === void 0 || latest === void 0) return false;
5150
+ for (let index = 0; index < current.core.length; index += 1) {
5151
+ const precedence = compareNumericIdentifier(
5152
+ current.core[index] ?? "0",
5153
+ latest.core[index] ?? "0"
5154
+ );
5155
+ if (precedence !== 0) return precedence > 0;
5156
+ }
5157
+ if (current.prerelease !== void 0 && latest.prerelease === void 0) return true;
5158
+ if (current.prerelease === void 0 || latest.prerelease === void 0) return false;
5159
+ return comparePrerelease(current.prerelease, latest.prerelease) > 0;
5160
+ }
5161
+ function offline() {
5162
+ return ["1", "true"].includes((process.env.npm_config_offline ?? "").toLowerCase());
5163
+ }
5164
+ async function checkSdkUpdate(currentVersion) {
5165
+ if (process.env.FORGEAX_DISABLE_UPDATE_CHECK === "1") {
5166
+ return { status: "skipped", currentVersion, reason: "disabled" };
5167
+ }
5168
+ if (offline()) return { status: "skipped", currentVersion, reason: "offline" };
5169
+ try {
5170
+ const registry = process.env.npm_config_registry ?? "https://registry.npmjs.org/";
5171
+ const response = await fetch(
5172
+ new URL("@forgeax%2Fengine-sdk", `${registry.replace(/\/$/, "")}/`),
5173
+ {
5174
+ headers: { accept: "application/vnd.npm.install-v1+json" },
5175
+ signal: AbortSignal.timeout(2e3)
5176
+ }
5177
+ );
5178
+ if (!response.ok) throw new Error(`registry-http-${response.status}`);
5179
+ const metadata = await response.json();
5180
+ const latestVersion = metadata["dist-tags"]?.latest;
5181
+ if (typeof latestVersion !== "string") throw new Error("registry-latest-version-missing");
5182
+ return newerSdkVersion(currentVersion, latestVersion) ? {
5183
+ status: "available",
5184
+ currentVersion,
5185
+ latestVersion,
5186
+ migrationRisk: UPDATE_MIGRATION_RISK
5187
+ } : { status: "current", currentVersion, latestVersion };
5188
+ } catch (cause) {
5189
+ return {
5190
+ status: "unavailable",
5191
+ currentVersion,
5192
+ reason: cause instanceof Error ? cause.message : String(cause)
5193
+ };
5194
+ }
5195
+ }
5088
5196
  var PROJECT_SKILL_MOUNT_ROOTS = Object.freeze([
5089
5197
  ".codebuddy/skills",
5090
5198
  ".cursor/skills",
@@ -5657,9 +5765,16 @@ async function newCommand(options = {}) {
5657
5765
  env: { ...process.env, CI: "true" },
5658
5766
  maxBuffer: 16 * 1024 * 1024
5659
5767
  });
5768
+ const sdkUpdate = await checkSdkUpdate(sdk.manifest.sdkVersion);
5660
5769
  return {
5661
5770
  ok: true,
5662
- value: { root: root2, template: templateId, sdkVersion: sdk.manifest.sdkVersion }
5771
+ value: {
5772
+ root: root2,
5773
+ template: templateId,
5774
+ sdkVersion: sdk.manifest.sdkVersion,
5775
+ onboarding: agentOnboarding(sdk, root2),
5776
+ sdkUpdate
5777
+ }
5663
5778
  };
5664
5779
  } catch (cause) {
5665
5780
  if (staging !== void 0) await rm(staging, { recursive: true, force: true });
@@ -5686,11 +5801,42 @@ async function newCommand(options = {}) {
5686
5801
  }
5687
5802
  }
5688
5803
 
5804
+ // src/cli-output.ts
5805
+ function agentOnboardingLines(value) {
5806
+ if (value === null || typeof value !== "object" || Array.isArray(value)) return [];
5807
+ const onboarding = value.onboarding;
5808
+ if (onboarding === null || typeof onboarding !== "object" || Array.isArray(onboarding)) return [];
5809
+ const candidate = onboarding;
5810
+ const lines = Array.isArray(candidate.read) ? candidate.read.filter((path) => typeof path === "string").map((path) => `[forgeax] read: ${path}`) : [];
5811
+ if (typeof candidate.next?.cwd === "string" && Array.isArray(candidate.next.argv) && candidate.next.argv.every((part) => typeof part === "string")) {
5812
+ lines.push(`[forgeax] next cwd: ${candidate.next.cwd}`);
5813
+ lines.push(`[forgeax] next: ${candidate.next.argv.join(" ")}`);
5814
+ }
5815
+ return lines;
5816
+ }
5817
+ function sdkUpdateLines(value) {
5818
+ if (value === null || typeof value !== "object" || Array.isArray(value)) return [];
5819
+ const update = value.sdkUpdate;
5820
+ if (update === null || typeof update !== "object" || Array.isArray(update)) return [];
5821
+ const candidate = update;
5822
+ if (candidate.status !== "available" || typeof candidate.currentVersion !== "string" || typeof candidate.latestVersion !== "string" || typeof candidate.migrationRisk !== "string") {
5823
+ return [];
5824
+ }
5825
+ return [
5826
+ `[forgeax] update available: @forgeax/engine-sdk ${candidate.currentVersion} -> ${candidate.latestVersion}`,
5827
+ `[forgeax] update note: ${candidate.migrationRisk}`
5828
+ ];
5829
+ }
5830
+ function renderForgeaxUsage() {
5831
+ return "Usage: forgeax new [directory] [--template empty|game-default]\n forgeax <init|doctor|test|dev|build|package|serve|preview> [directory]\n forgeax package [directory] [--output release/game-web.zip]\n forgeax run <rhi.capture|rhi.summary|rhi.inspect> [options]\n forgeax run <operation-id> --input <request.json>\n forgeax asset <add|verify|inspect|list> [subject]\n forgeax shader check [path]\n forgeax plugin <install|uninstall> <module-or-id> [options]\n forgeax skill <install|verify> [--root directory]\n forgeax sdk install <directory> [--version VERSION]\n";
5832
+ }
5833
+
5689
5834
  // src/sdk-cli.ts
5690
- var args = process.argv.slice(2);
5835
+ var rawArgs = process.argv.slice(2);
5836
+ var args = [...rawArgs];
5691
5837
  var commandArg = args.shift();
5692
5838
  var command = commandArg;
5693
- var help = commandArg === "--help" || commandArg === "-h";
5839
+ var help = rawArgs.includes("--help") || rawArgs.includes("-h");
5694
5840
  var json = args.includes("--json");
5695
5841
  var dryRun = args.includes("--dry-run");
5696
5842
  var noInstall = args.includes("--no-install");
@@ -5700,23 +5846,43 @@ var positional = args.find(
5700
5846
  (value, index) => !value.startsWith("--") && (templateIndex < 0 || index !== templateIndex + 1)
5701
5847
  );
5702
5848
  var root = command === "new" || command === "init" || command === "doctor" ? positional ?? process.cwd() : process.cwd();
5703
- if (command === "new" || command === "init" || command === "doctor") {
5849
+ if (help) {
5850
+ process.stdout.write(renderForgeaxUsage());
5851
+ } else if (command === "new" || command === "init" || command === "doctor") {
5704
5852
  const result = await (command === "new" ? newCommand({ root, dryRun, ...template === void 0 ? {} : { template } }) : command === "init" ? initCommand({ root, dryRun, install: !noInstall }) : doctorCommand({ root}));
5705
5853
  const envelope = result.ok ? { schemaVersion: "1.0.0", command, ok: true, value: result.value } : { schemaVersion: "1.0.0", command, ok: false, error: result.error };
5706
5854
  if (json) process.stdout.write(`${JSON.stringify(envelope)}
5707
5855
  `);
5708
- else if (result.ok) process.stdout.write(`[forgeax] ${command} ready
5856
+ else if (result.ok) {
5857
+ process.stdout.write(`[forgeax] ${command} ready
5709
5858
  `);
5710
- else process.stderr.write(`[forgeax] ${result.error.code}: ${result.error.hint}
5859
+ for (const line of agentOnboardingLines(result.value)) process.stdout.write(`${line}
5860
+ `);
5861
+ for (const line of sdkUpdateLines(result.value)) process.stdout.write(`${line}
5862
+ `);
5863
+ } else process.stderr.write(`[forgeax] ${result.error.code}: ${result.error.hint}
5711
5864
  `);
5712
5865
  if (!result.ok) process.exitCode = 1;
5713
- } else if (command !== void 0 && !help) {
5714
- const cli = resolve(root, "node_modules", "@forgeax", "engine-devkit", "dist", "cli.mjs");
5715
- await import(pathToFileURL(cli).href);
5866
+ } else if (command !== void 0) {
5867
+ const localForgeax = resolve(
5868
+ root,
5869
+ "node_modules",
5870
+ ".bin",
5871
+ process.platform === "win32" ? "forgeax.cmd" : "forgeax"
5872
+ );
5873
+ const child = spawn(localForgeax, [command, ...args], {
5874
+ cwd: root,
5875
+ shell: process.platform === "win32",
5876
+ stdio: "inherit"
5877
+ });
5878
+ const exitCode = await new Promise((resolveExit, reject) => {
5879
+ child.once("error", reject);
5880
+ child.once("exit", resolveExit);
5881
+ });
5882
+ if (exitCode !== 0) process.exitCode = exitCode ?? 1;
5716
5883
  } else {
5717
- const output = "Usage: forgeax new [directory] [--template empty|game-default]\n forgeax <init|doctor|test|dev|build|serve|preview> [directory]\n forgeax skill <install|verify> # from a game project\n";
5718
- (help ? process.stdout : process.stderr).write(output);
5719
- if (!help) process.exitCode = 2;
5884
+ process.stderr.write(renderForgeaxUsage());
5885
+ process.exitCode = 2;
5720
5886
  }
5721
5887
  /*! Bundled license information:
5722
5888