@genex-ai/cli-demo 1.28.0-dev.632 → 1.29.1-dev.634

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.
@@ -7,7 +7,7 @@ import {
7
7
  isRenderMode,
8
8
  sceneSummary,
9
9
  sheetOf
10
- } from "./chunk-42MHGAXI.js";
10
+ } from "./chunk-2COG4P3T.js";
11
11
  import {
12
12
  getCliVersion
13
13
  } from "./chunk-HYCSNWYX.js";
@@ -176,11 +176,11 @@ async function handle(msg) {
176
176
  const args = msg.params?.arguments ?? {};
177
177
  const tool = TOOLS.find((t) => t.name === name);
178
178
  if (!tool) return fail(id, -32602, `Unknown tool: ${name}`);
179
- const base = await mcpEndpoint();
180
- if (!base) {
181
- return reply(id, { content: [{ type: "text", text: blenderSetupHint() }], isError: true });
182
- }
183
179
  try {
180
+ const base = await mcpEndpoint();
181
+ if (!base) {
182
+ return reply(id, { content: [{ type: "text", text: blenderSetupHint() }], isError: true });
183
+ }
184
184
  return reply(id, await tool.run(args, base));
185
185
  } catch (err) {
186
186
  return reply(id, {
@@ -201,7 +201,10 @@ var stderrLog = {
201
201
  };
202
202
  async function mcpEndpoint() {
203
203
  const seat = await acquireSeat({ log: stderrLog });
204
- if (seat.kind === "granted") return seat.grant.url;
204
+ if (seat.kind === "granted") {
205
+ await blenderCall(seat.grant.url, "/health");
206
+ return seat.grant.url;
207
+ }
205
208
  if (seat.kind === "refused") stderrLog.error(`no Blender seat: ${seat.reason}`);
206
209
  if (seat.kind === "warming") stderrLog.warn("the Blender seat is still warming \u2014 the next call will try again");
207
210
  return blenderEndpoint();
@@ -17,6 +17,22 @@ import fs from "fs/promises";
17
17
  import path from "path";
18
18
  import os from "os";
19
19
 
20
+ // src/lib/source-exclude.ts
21
+ var SOURCE_EXCLUDE = [
22
+ "node_modules/",
23
+ "dist/",
24
+ ".git/",
25
+ // Local project metadata, per-device by design.
26
+ ".genex/",
27
+ // Secrets — never publish them; `!` keeps the non-secret template.
28
+ ".env",
29
+ ".env.*",
30
+ "!.env.example"
31
+ ];
32
+ function excludeFile() {
33
+ return [...SOURCE_EXCLUDE, ""].join("\n");
34
+ }
35
+
20
36
  // src/utils/run.ts
21
37
  import { spawn } from "child_process";
22
38
  var WIN_SHELL_COMMANDS = /* @__PURE__ */ new Set(["npm", "npx"]);
@@ -91,10 +107,7 @@ async function sourceTreeHash(cwd) {
91
107
  const base = { GIT_DIR: gitDir };
92
108
  try {
93
109
  if ((await run("git", ["init", "-q"], base)).code !== 0) return null;
94
- await fs.writeFile(
95
- path.join(gitDir, "info", "exclude"),
96
- ["node_modules/", "dist/", ".git/", ".genex/", ".env", ".env.*", "!.env.example", ""].join("\n")
97
- );
110
+ await fs.writeFile(path.join(gitDir, "info", "exclude"), excludeFile());
98
111
  if ((await run("git", ["lfs", "version"], base)).code === 0) {
99
112
  const filters = [
100
113
  ["filter.lfs.clean", "git-lfs clean -- %f"],
@@ -768,6 +781,16 @@ ${json.trace.slice(-4e3)}` : "";
768
781
  throw new Error(`${route} failed (${res.status}): ${json.error ?? text.slice(0, 200)}${stage}${detail}${mutationWarning}${trace}`);
769
782
  }
770
783
  if (seat?.kind === "cli") void touchCliSeat();
784
+ if (seat?.kind === "hosted" && seat.seatId && route === "/health") {
785
+ const token = await readUserToken();
786
+ if (!token) throw new Error("Cannot acknowledge Blender readiness: not signed in");
787
+ const claim = await apiFetch(`${getApiUrl()}/api/blender/seat/touch`, {
788
+ method: "POST",
789
+ headers: { Authorization: `Bearer ${token}`, "Content-Type": "application/json" },
790
+ body: JSON.stringify({ seatId: seat.seatId })
791
+ });
792
+ if (!claim.ok) throw new Error("Blender readiness acknowledgement failed; no scene command was sent. Run the command again.");
793
+ }
771
794
  return json;
772
795
  } catch (err) {
773
796
  if (err instanceof Error && err.name === "AbortError") {
@@ -802,14 +825,15 @@ async function acquireSeat(opts) {
802
825
  for (; ; ) {
803
826
  const res = await doFetch(`${getApiUrl()}/api/blender/seat`, {
804
827
  method: "POST",
805
- headers: { Authorization: `Bearer ${token}` }
828
+ headers: { Authorization: `Bearer ${token}`, "Content-Type": "application/json" },
829
+ body: JSON.stringify({ acknowledgeReadiness: true })
806
830
  });
807
831
  if (res.status === 201) {
808
832
  const body = await res.json();
809
833
  if (typeof body.url !== "string" || typeof body.token !== "string") {
810
834
  return { kind: "refused", reason: "the API answered a seat without a url and token" };
811
835
  }
812
- const grant = { url: body.url, token: body.token, kind: "hosted" };
836
+ const grant = { url: body.url, token: body.token, kind: "hosted", ...typeof body.seatId === "string" ? { seatId: body.seatId } : {} };
813
837
  writeSeatGrant(grant, opts.cwd);
814
838
  return { kind: "granted", grant };
815
839
  }
@@ -843,7 +867,7 @@ async function acquireCliSeat(opts) {
843
867
  const res = await doFetch(`${getApiUrl()}/api/blender/seat`, {
844
868
  method: "POST",
845
869
  headers: { Authorization: `Bearer ${token}`, "Content-Type": "application/json" },
846
- body: JSON.stringify({ cli: true, scope: opts.scope })
870
+ body: JSON.stringify({ cli: true, scope: opts.scope, acknowledgeReadiness: true })
847
871
  });
848
872
  if (res.status === 201) {
849
873
  const body = await res.json();
@@ -898,6 +922,7 @@ async function releaseCliSeat(opts) {
898
922
  }
899
923
 
900
924
  export {
925
+ excludeFile,
901
926
  run,
902
927
  readRemoteSource,
903
928
  isStale,
package/dist/index.js CHANGED
@@ -12,6 +12,7 @@ import {
12
12
  blenderEndpoint,
13
13
  blenderSetupHint,
14
14
  cloneSource,
15
+ excludeFile,
15
16
  fetchCloneGrant,
16
17
  fetchSignedInEmail,
17
18
  inHostedSession,
@@ -41,7 +42,7 @@ import {
41
42
  writeProject,
42
43
  writeUserToken,
43
44
  writeWorkspace
44
- } from "./chunk-42MHGAXI.js";
45
+ } from "./chunk-2COG4P3T.js";
45
46
  import {
46
47
  CLI_CHANNEL,
47
48
  DEFAULT_API_URL,
@@ -5392,11 +5393,7 @@ async function pushWorktree(cwd, pushUrl, managed, log, branch = "main", onCommi
5392
5393
  };
5393
5394
  try {
5394
5395
  if ((await run("git", ["init", "-q"], base)).code !== 0) return failed();
5395
- await fs16.writeFile(
5396
- path15.join(gitDir, "info", "exclude"),
5397
- // .env* are secrets — never publish them; `!` keeps the non-secret template.
5398
- ["node_modules/", "dist/", ".git/", ".genex/", ".env", ".env.*", "!.env.example", ""].join("\n")
5399
- );
5396
+ await fs16.writeFile(path15.join(gitDir, "info", "exclude"), excludeFile());
5400
5397
  const env = { ...base, GIT_WORK_TREE: cwd, GIT_INDEX_FILE: path15.join(gitDir, "index-source") };
5401
5398
  let lfs = (await run("git", ["lfs", "version"], base)).code !== 0 ? false : true;
5402
5399
  if (!lfs) {
@@ -22012,7 +22009,7 @@ async function runBlender(opts) {
22012
22009
  return serveLocalBlender({ port, log });
22013
22010
  }
22014
22011
  if (sub === "mcp") {
22015
- const { runBlenderMcp } = await import("./blender-mcp-VU5KLCZG.js");
22012
+ const { runBlenderMcp } = await import("./blender-mcp-Q6PSFYSE.js");
22016
22013
  return runBlenderMcp();
22017
22014
  }
22018
22015
  if (sub === "seat") {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@genex-ai/cli-demo",
3
- "version": "1.28.0-dev.632",
3
+ "version": "1.29.1-dev.634",
4
4
  "description": "Set up your project's agent workspace (.claude/.codex/.cursor in the game folder), authorize, create a game project, generate AI assets, and publish (genex CLI).",
5
5
  "type": "module",
6
6
  "bin": {