@mmapp/react-compiler 0.1.0-alpha.13 → 0.1.0-alpha.15

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/cli/index.js CHANGED
@@ -14454,36 +14454,24 @@ async function verifyBinary(binaryPath) {
14454
14454
  if (!(0, import_fs6.existsSync)(binaryPath)) {
14455
14455
  return { ok: false, error: `Binary not found at ${binaryPath}` };
14456
14456
  }
14457
- return new Promise((resolve7) => {
14458
- try {
14459
- const proc = (0, import_child_process2.spawn)(binaryPath, ["--version"], {
14460
- stdio: ["ignore", "pipe", "pipe"],
14461
- timeout: 1e4
14462
- });
14463
- let stdout = "";
14464
- let stderr = "";
14465
- proc.stdout?.on("data", (d) => {
14466
- stdout += d.toString();
14467
- });
14468
- proc.stderr?.on("data", (d) => {
14469
- stderr += d.toString();
14470
- });
14471
- proc.on("error", (err) => {
14472
- resolve7({ ok: false, error: `Failed to execute: ${err.message}` });
14473
- });
14474
- proc.on("close", (code) => {
14475
- if (code === 0) {
14476
- const output = stdout.trim() || stderr.trim();
14477
- const version = output.replace(/^mm[-_](?:server|api)\s*/i, "").trim() || "unknown";
14478
- resolve7({ ok: true, version });
14479
- } else {
14480
- resolve7({ ok: false, error: `Exited with code ${code}. ${stderr.trim()}` });
14481
- }
14482
- });
14483
- } catch (e) {
14484
- resolve7({ ok: false, error: `Spawn failed: ${e instanceof Error ? e.message : String(e)}` });
14457
+ try {
14458
+ const { statSync: statSync3 } = require("fs");
14459
+ const stat = statSync3(binaryPath);
14460
+ if (stat.size < 1e6) {
14461
+ return { ok: false, error: `Binary too small (${stat.size} bytes) \u2014 likely corrupt` };
14485
14462
  }
14486
- });
14463
+ if (process.platform !== "win32") {
14464
+ const { accessSync, constants } = require("fs");
14465
+ try {
14466
+ accessSync(binaryPath, constants.X_OK);
14467
+ } catch {
14468
+ return { ok: false, error: "Binary is not executable" };
14469
+ }
14470
+ }
14471
+ return { ok: true, version: "unknown" };
14472
+ } catch (e) {
14473
+ return { ok: false, error: e.message };
14474
+ }
14487
14475
  }
14488
14476
  async function healthCheck(url, timeoutMs = 5e3) {
14489
14477
  try {
@@ -14691,11 +14679,46 @@ async function buildFromSource(options) {
14691
14679
  return null;
14692
14680
  }
14693
14681
  }
14694
- console.error("[mmrc] Building mm-api from source (this may take a few minutes)...");
14682
+ console.error("[mmrc] Building mm-api from source (this may take several minutes)...");
14683
+ let engineDir = null;
14684
+ const searchPaths = [
14685
+ (0, import_path5.join)(cwd, "mm-core"),
14686
+ (0, import_path5.join)(cwd, "engine"),
14687
+ (0, import_path5.join)(cwd, "..", "mm-core"),
14688
+ (0, import_path5.join)(cwd, "..", "..", "mm-core"),
14689
+ (0, import_path5.join)(cwd, "..", "..", "mm-app", "mm-core"),
14690
+ (0, import_path5.join)((0, import_os2.homedir)(), ".mmrc", "engine-src")
14691
+ ];
14692
+ for (const p of searchPaths) {
14693
+ if ((0, import_fs6.existsSync)((0, import_path5.join)(p, "Cargo.toml"))) {
14694
+ engineDir = p;
14695
+ console.error(`[mmrc] Found engine source at ${p}`);
14696
+ break;
14697
+ }
14698
+ }
14699
+ if (!engineDir) {
14700
+ const cloneDir = (0, import_path5.join)((0, import_os2.homedir)(), ".mmrc", "engine-src");
14701
+ console.error("[mmrc] Engine source not found locally \u2014 cloning from GitHub...");
14702
+ try {
14703
+ if ((0, import_fs6.existsSync)(cloneDir)) {
14704
+ (0, import_child_process2.execSync)("git pull", { cwd: cloneDir, stdio: "pipe", timeout: 6e4 });
14705
+ } else {
14706
+ (0, import_fs6.mkdirSync)((0, import_path5.join)((0, import_os2.homedir)(), ".mmrc"), { recursive: true });
14707
+ (0, import_child_process2.execSync)(`git clone --depth 1 https://github.com/dev-nested/mm-app.git ${cloneDir}`, {
14708
+ stdio: "inherit",
14709
+ timeout: 12e4
14710
+ });
14711
+ }
14712
+ engineDir = (0, import_path5.join)(cloneDir, "mm-core");
14713
+ } catch (err) {
14714
+ console.error("[mmrc] Failed to clone engine source:", err instanceof Error ? err.message : err);
14715
+ return null;
14716
+ }
14717
+ }
14695
14718
  try {
14696
14719
  (0, import_child_process2.execSync)("cargo build --release -p mm-api", {
14697
14720
  stdio: "inherit",
14698
- cwd,
14721
+ cwd: engineDir,
14699
14722
  timeout: 6e5
14700
14723
  });
14701
14724
  } catch (err) {
@@ -14703,6 +14726,8 @@ async function buildFromSource(options) {
14703
14726
  return null;
14704
14727
  }
14705
14728
  const candidates = [
14729
+ (0, import_path5.join)(engineDir, "target", "release", "mm-server"),
14730
+ (0, import_path5.join)(engineDir, "..", "target", "release", "mm-server"),
14706
14731
  (0, import_path5.join)(cwd, "mm-core", "target", "release", "mm-server"),
14707
14732
  (0, import_path5.join)(cwd, "target", "release", "mm-server")
14708
14733
  ];
@@ -15761,10 +15786,10 @@ async function createDevServer(options = {}) {
15761
15786
  }
15762
15787
  const {
15763
15788
  port = 5199,
15764
- src = "src/workflows",
15789
+ src = ".",
15765
15790
  mode = "infer",
15766
- include = ["**/*.workflow.tsx"],
15767
- outDir = "dist/workflows",
15791
+ include = ["models/**/*.ts", "app/**/*.tsx", "**/*.workflow.tsx"],
15792
+ outDir = "dist",
15768
15793
  seed = false,
15769
15794
  apiUrl: rawApiUrl = "auto",
15770
15795
  authToken: explicitToken,
@@ -19295,15 +19320,14 @@ async function main() {
19295
19320
  } else {
19296
19321
  console.log(`[mmrc] Starting local engine: ${resolution.path} (${resolution.source})`);
19297
19322
  const { spawn: spawnProcess } = require("child_process");
19298
- engineProcess = spawnProcess(resolution.path, [], {
19323
+ engineProcess = spawnProcess(resolution.path, ["--dev"], {
19299
19324
  stdio: ["ignore", "pipe", "pipe"],
19300
19325
  env: {
19301
19326
  ...process.env,
19302
- DATABASE_URL: `sqlite://${process.cwd()}/dev.db`,
19303
- JWT_SECRET: "dev-secret-mmrc-local",
19304
19327
  PORT: String(apiPort),
19305
19328
  RUST_LOG: "mm_api=info,mm_storage=info"
19306
- }
19329
+ },
19330
+ cwd: process.cwd()
19307
19331
  });
19308
19332
  if (engineProcess.stdout) {
19309
19333
  engineProcess.stdout.on("data", (data) => {
@@ -348,7 +348,7 @@ async function main() {
348
348
  const apiPort = getFlag("--api-port") ? parseInt(getFlag("--api-port"), 10) : 4200;
349
349
  let engineProcess = null;
350
350
  if (isLocal) {
351
- const { findEngineBinary, installEngine, verifyBinary } = await import("../engine-binary-QQUDACBJ.mjs");
351
+ const { findEngineBinary, installEngine, verifyBinary } = await import("../engine-binary-FKTZAR56.mjs");
352
352
  let resolution = findEngineBinary(getFlag("--binary"));
353
353
  if (resolution.path) {
354
354
  const verify = await verifyBinary(resolution.path);
@@ -374,15 +374,14 @@ async function main() {
374
374
  } else {
375
375
  console.log(`[mmrc] Starting local engine: ${resolution.path} (${resolution.source})`);
376
376
  const { spawn: spawnProcess } = __require("child_process");
377
- engineProcess = spawnProcess(resolution.path, [], {
377
+ engineProcess = spawnProcess(resolution.path, ["--dev"], {
378
378
  stdio: ["ignore", "pipe", "pipe"],
379
379
  env: {
380
380
  ...process.env,
381
- DATABASE_URL: `sqlite://${process.cwd()}/dev.db`,
382
- JWT_SECRET: "dev-secret-mmrc-local",
383
381
  PORT: String(apiPort),
384
382
  RUST_LOG: "mm_api=info,mm_storage=info"
385
- }
383
+ },
384
+ cwd: process.cwd()
386
385
  });
387
386
  if (engineProcess.stdout) {
388
387
  engineProcess.stdout.on("data", (data) => {
@@ -705,7 +704,7 @@ async function main() {
705
704
  healthCheck,
706
705
  readMetadata,
707
706
  MANAGED_BINARY_PATH: _MANAGED_BINARY_PATH
708
- } = await import("../engine-binary-QQUDACBJ.mjs");
707
+ } = await import("../engine-binary-FKTZAR56.mjs");
709
708
  if (subcommand === "status") {
710
709
  const status = await getEngineStatus(getFlag("--binary"));
711
710
  const plat = detectPlatform();
@@ -12289,10 +12289,10 @@ async function createDevServer(options = {}) {
12289
12289
  }
12290
12290
  const {
12291
12291
  port = 5199,
12292
- src = "src/workflows",
12292
+ src = ".",
12293
12293
  mode = "infer",
12294
- include = ["**/*.workflow.tsx"],
12295
- outDir = "dist/workflows",
12294
+ include = ["models/**/*.ts", "app/**/*.tsx", "**/*.workflow.tsx"],
12295
+ outDir = "dist",
12296
12296
  seed = false,
12297
12297
  apiUrl: rawApiUrl = "auto",
12298
12298
  authToken: explicitToken,
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  createDevServer
3
- } from "./chunk-UBDNXVL2.mjs";
3
+ } from "./chunk-NUPJYPFU.mjs";
4
4
  import "./chunk-BZEXUPDH.mjs";
5
5
  import "./chunk-DNWDIPH2.mjs";
6
6
  import "./chunk-5M7DKKBC.mjs";
@@ -0,0 +1,480 @@
1
+ import {
2
+ __require
3
+ } from "./chunk-CIESM3BP.mjs";
4
+
5
+ // src/cli/engine-binary.ts
6
+ import { existsSync, mkdirSync, writeFileSync, readFileSync, chmodSync, createWriteStream, copyFileSync } from "fs";
7
+ import { join, resolve } from "path";
8
+ import { homedir, platform, arch } from "os";
9
+ import { pipeline } from "stream/promises";
10
+ import { execSync } from "child_process";
11
+ var MMRC_BIN_DIR = join(homedir(), ".mmrc", "bin");
12
+ var BINARY_NAME = platform() === "win32" ? "mm-api.exe" : "mm-api";
13
+ var MANAGED_BINARY_PATH = join(MMRC_BIN_DIR, BINARY_NAME);
14
+ var VERSION_FILE_PATH = join(MMRC_BIN_DIR, "mm-api.version");
15
+ var METADATA_PATH = join(MMRC_BIN_DIR, "mm-api.json");
16
+ var GITHUB_RELEASE_BASE = "https://github.com/dev-nested/mm-app/releases/download";
17
+ var PROJECT_SEARCH_PATHS = [
18
+ "engine/target/release/mm-server",
19
+ "engine/target/debug/mm-server",
20
+ "mm-core/target/release/mm-server",
21
+ "mm-core/target/debug/mm-server",
22
+ "target/release/mm-server",
23
+ "target/debug/mm-server"
24
+ ];
25
+ function detectPlatform() {
26
+ const os = platform();
27
+ const a = arch();
28
+ let triple;
29
+ let releasePlatform = null;
30
+ if (os === "linux" && a === "x64") {
31
+ triple = "x86_64-unknown-linux-gnu";
32
+ releasePlatform = "linux-x64";
33
+ } else if (os === "linux" && a === "arm64") {
34
+ triple = "aarch64-unknown-linux-gnu";
35
+ releasePlatform = "linux-arm64";
36
+ } else if (os === "darwin" && a === "x64") {
37
+ triple = "x86_64-apple-darwin";
38
+ releasePlatform = "darwin-x64";
39
+ } else if (os === "darwin" && a === "arm64") {
40
+ triple = "aarch64-apple-darwin";
41
+ releasePlatform = "darwin-arm64";
42
+ } else if (os === "win32" && a === "x64") {
43
+ triple = "x86_64-pc-windows-msvc";
44
+ releasePlatform = "windows-x64";
45
+ } else {
46
+ triple = `${a}-unknown-${os}`;
47
+ }
48
+ return { os, arch: a, triple, releasePlatform };
49
+ }
50
+ function getCachedVersion() {
51
+ try {
52
+ if (existsSync(VERSION_FILE_PATH)) {
53
+ return readFileSync(VERSION_FILE_PATH, "utf-8").trim();
54
+ }
55
+ } catch {
56
+ }
57
+ return null;
58
+ }
59
+ function setCachedVersion(version) {
60
+ mkdirSync(MMRC_BIN_DIR, { recursive: true });
61
+ writeFileSync(VERSION_FILE_PATH, version, "utf-8");
62
+ }
63
+ function readMetadata() {
64
+ try {
65
+ if (!existsSync(METADATA_PATH)) return null;
66
+ return JSON.parse(readFileSync(METADATA_PATH, "utf-8"));
67
+ } catch {
68
+ return null;
69
+ }
70
+ }
71
+ function writeMetadata(meta) {
72
+ mkdirSync(MMRC_BIN_DIR, { recursive: true });
73
+ writeFileSync(METADATA_PATH, JSON.stringify(meta, null, 2), "utf-8");
74
+ }
75
+ async function verifyBinary(binaryPath) {
76
+ if (!existsSync(binaryPath)) {
77
+ return { ok: false, error: `Binary not found at ${binaryPath}` };
78
+ }
79
+ try {
80
+ const { statSync } = __require("fs");
81
+ const stat = statSync(binaryPath);
82
+ if (stat.size < 1e6) {
83
+ return { ok: false, error: `Binary too small (${stat.size} bytes) \u2014 likely corrupt` };
84
+ }
85
+ if (process.platform !== "win32") {
86
+ const { accessSync, constants } = __require("fs");
87
+ try {
88
+ accessSync(binaryPath, constants.X_OK);
89
+ } catch {
90
+ return { ok: false, error: "Binary is not executable" };
91
+ }
92
+ }
93
+ return { ok: true, version: "unknown" };
94
+ } catch (e) {
95
+ return { ok: false, error: e.message };
96
+ }
97
+ }
98
+ async function healthCheck(url, timeoutMs = 5e3) {
99
+ try {
100
+ const resp = await fetch(url, { signal: AbortSignal.timeout(timeoutMs) });
101
+ if (resp.ok) {
102
+ const data = await resp.json();
103
+ return { ok: true, version: data.version, db: data.database };
104
+ }
105
+ return { ok: resp.status < 500 };
106
+ } catch {
107
+ return { ok: false };
108
+ }
109
+ }
110
+ async function getEngineStatus(explicitPath) {
111
+ const plat = detectPlatform();
112
+ const resolution = findEngineBinary(explicitPath);
113
+ const meta = readMetadata();
114
+ let version = null;
115
+ let verified = false;
116
+ if (resolution.path) {
117
+ const verify = await verifyBinary(resolution.path);
118
+ if (verify.ok) {
119
+ version = verify.version ?? null;
120
+ verified = true;
121
+ }
122
+ }
123
+ return {
124
+ installed: resolution.path !== null,
125
+ path: resolution.path,
126
+ source: resolution.source,
127
+ version,
128
+ platform: plat,
129
+ metadata: meta,
130
+ verified
131
+ };
132
+ }
133
+ async function installEngine(options) {
134
+ const { force = false, preferBuild = false, version = "latest", cwd, prompt, fetch: fetchFn } = options ?? {};
135
+ const plat = detectPlatform();
136
+ if (!force && existsSync(MANAGED_BINARY_PATH)) {
137
+ const meta = readMetadata();
138
+ if (meta?.verified) {
139
+ console.error(`[mmrc] Found cached binary (${meta.version}, ${meta.platform})`);
140
+ }
141
+ const verify = await verifyBinary(MANAGED_BINARY_PATH);
142
+ if (verify.ok) {
143
+ console.error(`[mmrc] Cached binary verified: ${verify.version}`);
144
+ return { path: MANAGED_BINARY_PATH, source: "managed" };
145
+ }
146
+ console.error("[mmrc] Cached binary failed verification \u2014 reinstalling.");
147
+ }
148
+ if (preferBuild) {
149
+ return await installViaBuild(plat, version, cwd, prompt);
150
+ }
151
+ if (plat.releasePlatform) {
152
+ const dl = await downloadBinary({ version, platform: plat.releasePlatform, fetch: fetchFn });
153
+ if (dl.success) {
154
+ console.error("[mmrc] Verifying downloaded binary...");
155
+ const verify = await verifyBinary(dl.path);
156
+ if (verify.ok) {
157
+ console.error(`[mmrc] Verification passed: ${verify.version}`);
158
+ writeMetadata({
159
+ version: verify.version ?? version,
160
+ platform: plat.releasePlatform,
161
+ triple: plat.triple,
162
+ downloadedAt: (/* @__PURE__ */ new Date()).toISOString(),
163
+ verified: true,
164
+ source: "download",
165
+ path: dl.path
166
+ });
167
+ return { path: dl.path, source: "downloaded" };
168
+ }
169
+ console.error(`[mmrc] Binary verification FAILED: ${verify.error}`);
170
+ console.error("");
171
+ console.error(` Platform: ${plat.releasePlatform} (${plat.triple})`);
172
+ console.error(" This usually means:");
173
+ console.error(" - Wrong architecture (e.g., ARM binary on x86)");
174
+ console.error(" - Missing shared libraries (try: ldd " + dl.path + ")");
175
+ console.error(" - Glibc version mismatch");
176
+ console.error("");
177
+ console.error("[mmrc] Falling back to build from source...\n");
178
+ } else {
179
+ console.error(`[mmrc] Download failed: ${dl.error}`);
180
+ }
181
+ } else {
182
+ console.error(`[mmrc] No pre-built binary for ${plat.os}/${plat.arch}.`);
183
+ }
184
+ return await installViaBuild(plat, version, cwd, prompt);
185
+ }
186
+ async function installViaBuild(plat, version, cwd, prompt) {
187
+ if (!hasCargoInstalled()) {
188
+ console.error("[mmrc] Rust toolchain not found (cargo not in PATH).");
189
+ console.error("");
190
+ if (platform() === "win32") {
191
+ console.error(" Install Rust from https://rustup.rs");
192
+ } else {
193
+ console.error(" Install Rust:");
194
+ console.error(' curl --proto "=https" --tlsv1.2 -sSf https://sh.rustup.rs | sh');
195
+ }
196
+ console.error("");
197
+ console.error(" Then restart your shell and run: mmrc engine build");
198
+ return { path: null, source: "not-found" };
199
+ }
200
+ const built = await buildFromSource({ cwd, prompt });
201
+ if (!built) return { path: null, source: "not-found" };
202
+ console.error("[mmrc] Verifying built binary...");
203
+ const verify = await verifyBinary(built);
204
+ if (verify.ok) {
205
+ console.error(`[mmrc] Build verified: ${verify.version}`);
206
+ writeMetadata({
207
+ version: verify.version ?? version,
208
+ platform: plat.releasePlatform ?? `${plat.os}-${plat.arch}`,
209
+ triple: plat.triple,
210
+ downloadedAt: (/* @__PURE__ */ new Date()).toISOString(),
211
+ verified: true,
212
+ source: "build",
213
+ path: built
214
+ });
215
+ return { path: built, source: "built" };
216
+ }
217
+ console.error(`[mmrc] Built binary also failed verification: ${verify.error}`);
218
+ return { path: null, source: "not-found" };
219
+ }
220
+ function buildDownloadUrl(version, releasePlatform) {
221
+ const tag = version.startsWith("v") ? version : `v${version}`;
222
+ return `${GITHUB_RELEASE_BASE}/${tag}/mm-api-${releasePlatform}`;
223
+ }
224
+ async function downloadBinary(options) {
225
+ const plat = options.platform ?? detectPlatform().releasePlatform;
226
+ const dest = options.dest ?? MANAGED_BINARY_PATH;
227
+ const fetchFn = options.fetch ?? globalThis.fetch;
228
+ if (!plat) {
229
+ return { success: false, path: dest, error: "Unsupported platform for pre-built binaries" };
230
+ }
231
+ const url = buildDownloadUrl(options.version, plat);
232
+ console.error(`[mmrc] Downloading mm-api ${options.version} for ${plat}...`);
233
+ console.error(`[mmrc] ${url}`);
234
+ try {
235
+ const response = await fetchFn(url, { redirect: "follow" });
236
+ if (!response.ok) {
237
+ return {
238
+ success: false,
239
+ path: dest,
240
+ error: `HTTP ${response.status}: ${response.statusText} (${url})`
241
+ };
242
+ }
243
+ mkdirSync(MMRC_BIN_DIR, { recursive: true });
244
+ const body = response.body;
245
+ if (!body) {
246
+ return { success: false, path: dest, error: "Empty response body" };
247
+ }
248
+ const fileStream = createWriteStream(dest);
249
+ await pipeline(body, fileStream);
250
+ chmodSync(dest, 493);
251
+ setCachedVersion(options.version);
252
+ console.error(`[mmrc] Downloaded to ${dest}`);
253
+ return { success: true, path: dest };
254
+ } catch (err) {
255
+ const message = err instanceof Error ? err.message : String(err);
256
+ return { success: false, path: dest, error: message };
257
+ }
258
+ }
259
+ function hasCargoInstalled() {
260
+ try {
261
+ execSync("cargo --version", { encoding: "utf-8", timeout: 5e3, stdio: "pipe" });
262
+ return true;
263
+ } catch {
264
+ return false;
265
+ }
266
+ }
267
+ async function askUser(question) {
268
+ const readline = __require("readline");
269
+ const rl = readline.createInterface({ input: process.stdin, output: process.stderr });
270
+ return new Promise((resolve2) => {
271
+ rl.question(question, (answer) => {
272
+ rl.close();
273
+ resolve2(answer.trim().toLowerCase());
274
+ });
275
+ });
276
+ }
277
+ async function buildFromSource(options) {
278
+ const promptFn = options?.prompt ?? askUser;
279
+ const cwd = options?.cwd ?? process.cwd();
280
+ if (hasCargoInstalled()) {
281
+ const answer = await promptFn("[mmrc] No pre-built binary available. Build from source? (y/n) ");
282
+ if (answer !== "y" && answer !== "yes") return null;
283
+ } else {
284
+ const answer = await promptFn(
285
+ "[mmrc] No pre-built binary available and Rust is not installed.\n Install Rust and build from source? (y/n) "
286
+ );
287
+ if (answer !== "y" && answer !== "yes") return null;
288
+ console.error("[mmrc] Installing Rust via rustup...");
289
+ try {
290
+ execSync('curl --proto "=https" --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y', {
291
+ stdio: "inherit",
292
+ cwd,
293
+ timeout: 3e5
294
+ });
295
+ const cargoEnv = join(homedir(), ".cargo", "env");
296
+ if (existsSync(cargoEnv)) {
297
+ execSync(`. ${cargoEnv}`, { stdio: "pipe" });
298
+ }
299
+ } catch (err) {
300
+ console.error("[mmrc] Failed to install Rust:", err instanceof Error ? err.message : err);
301
+ return null;
302
+ }
303
+ }
304
+ console.error("[mmrc] Building mm-api from source (this may take several minutes)...");
305
+ let engineDir = null;
306
+ const searchPaths = [
307
+ join(cwd, "mm-core"),
308
+ join(cwd, "engine"),
309
+ join(cwd, "..", "mm-core"),
310
+ join(cwd, "..", "..", "mm-core"),
311
+ join(cwd, "..", "..", "mm-app", "mm-core"),
312
+ join(homedir(), ".mmrc", "engine-src")
313
+ ];
314
+ for (const p of searchPaths) {
315
+ if (existsSync(join(p, "Cargo.toml"))) {
316
+ engineDir = p;
317
+ console.error(`[mmrc] Found engine source at ${p}`);
318
+ break;
319
+ }
320
+ }
321
+ if (!engineDir) {
322
+ const cloneDir = join(homedir(), ".mmrc", "engine-src");
323
+ console.error("[mmrc] Engine source not found locally \u2014 cloning from GitHub...");
324
+ try {
325
+ if (existsSync(cloneDir)) {
326
+ execSync("git pull", { cwd: cloneDir, stdio: "pipe", timeout: 6e4 });
327
+ } else {
328
+ mkdirSync(join(homedir(), ".mmrc"), { recursive: true });
329
+ execSync(`git clone --depth 1 https://github.com/dev-nested/mm-app.git ${cloneDir}`, {
330
+ stdio: "inherit",
331
+ timeout: 12e4
332
+ });
333
+ }
334
+ engineDir = join(cloneDir, "mm-core");
335
+ } catch (err) {
336
+ console.error("[mmrc] Failed to clone engine source:", err instanceof Error ? err.message : err);
337
+ return null;
338
+ }
339
+ }
340
+ try {
341
+ execSync("cargo build --release -p mm-api", {
342
+ stdio: "inherit",
343
+ cwd: engineDir,
344
+ timeout: 6e5
345
+ });
346
+ } catch (err) {
347
+ console.error("[mmrc] Build failed:", err instanceof Error ? err.message : err);
348
+ return null;
349
+ }
350
+ const candidates = [
351
+ join(engineDir, "target", "release", "mm-server"),
352
+ join(engineDir, "..", "target", "release", "mm-server"),
353
+ join(cwd, "mm-core", "target", "release", "mm-server"),
354
+ join(cwd, "target", "release", "mm-server")
355
+ ];
356
+ for (const p of candidates) {
357
+ if (existsSync(p)) {
358
+ mkdirSync(MMRC_BIN_DIR, { recursive: true });
359
+ copyFileSync(p, MANAGED_BINARY_PATH);
360
+ chmodSync(MANAGED_BINARY_PATH, 493);
361
+ console.error(`[mmrc] Installed to ${MANAGED_BINARY_PATH}`);
362
+ return MANAGED_BINARY_PATH;
363
+ }
364
+ }
365
+ console.error("[mmrc] Build completed but binary not found in expected locations.");
366
+ return null;
367
+ }
368
+ function findEngineBinary(explicitPath, cwd) {
369
+ const workDir = cwd ?? process.cwd();
370
+ if (explicitPath) {
371
+ if (existsSync(explicitPath)) {
372
+ return { path: explicitPath, source: "explicit" };
373
+ }
374
+ return { path: null, source: "not-found" };
375
+ }
376
+ if (existsSync(MANAGED_BINARY_PATH)) {
377
+ return { path: MANAGED_BINARY_PATH, source: "managed" };
378
+ }
379
+ for (const rel of PROJECT_SEARCH_PATHS) {
380
+ const abs = resolve(workDir, rel);
381
+ if (existsSync(abs)) {
382
+ return { path: abs, source: "project" };
383
+ }
384
+ }
385
+ try {
386
+ const cmd = platform() === "win32" ? "where mm-server 2>nul || where mm-api 2>nul" : "which mm-server 2>/dev/null || which mm-api 2>/dev/null";
387
+ const result = execSync(cmd, { encoding: "utf-8", timeout: 5e3 }).trim();
388
+ if (result) {
389
+ return { path: result.split("\n")[0], source: "path" };
390
+ }
391
+ } catch {
392
+ }
393
+ return { path: null, source: "not-found" };
394
+ }
395
+ async function ensureEngineBinary(options) {
396
+ const found = findEngineBinary(options?.explicitPath, options?.cwd);
397
+ if (found.path) return found;
398
+ const plat = detectPlatform();
399
+ const version = options?.version ?? "latest";
400
+ if (plat.releasePlatform) {
401
+ const result = await downloadBinary({
402
+ version,
403
+ platform: plat.releasePlatform,
404
+ fetch: options?.fetch
405
+ });
406
+ if (result.success) {
407
+ return { path: result.path, source: "downloaded" };
408
+ }
409
+ console.error(`[mmrc] Download failed: ${result.error}`);
410
+ } else {
411
+ console.error(`[mmrc] No pre-built binary for ${plat.os}/${plat.arch}`);
412
+ }
413
+ if (!options?.nonInteractive) {
414
+ const built = await buildFromSource({
415
+ prompt: options?.prompt,
416
+ cwd: options?.cwd
417
+ });
418
+ if (built) {
419
+ return { path: built, source: "built" };
420
+ }
421
+ }
422
+ return { path: null, source: "not-found" };
423
+ }
424
+ function printInstallGuide() {
425
+ const plat = detectPlatform();
426
+ console.error("[mmrc] MindMatrix engine binary not found.\n");
427
+ console.error("The engine binary (mm-api) is required for local development.");
428
+ console.error("Choose one of the following options:\n");
429
+ console.error(" 1. Auto-download (recommended):");
430
+ console.error(" mmrc dev # auto-downloads the binary");
431
+ console.error("");
432
+ console.error(" 2. Build from source (requires Rust toolchain):");
433
+ console.error(' curl --proto "=https" --tlsv1.2 -sSf https://sh.rustup.rs | sh');
434
+ console.error(" cargo build --release -p mm-api");
435
+ console.error("");
436
+ console.error(" 3. Download manually:");
437
+ if (plat.releasePlatform) {
438
+ console.error(` curl -L -o ~/.mmrc/bin/mm-api \\`);
439
+ console.error(` ${GITHUB_RELEASE_BASE}/v0.1.0/mm-api-${plat.releasePlatform}`);
440
+ console.error(` chmod +x ~/.mmrc/bin/mm-api`);
441
+ } else {
442
+ console.error(` # No pre-built binary for ${plat.triple} \u2014 build from source`);
443
+ }
444
+ console.error("");
445
+ console.error(" 4. Use a remote backend instead of local:");
446
+ console.error(" mmrc dev --api-url https://dev.mindmatrix.club/api/v1");
447
+ console.error("");
448
+ }
449
+ function requireEngineBinary(explicitPath) {
450
+ const result = findEngineBinary(explicitPath);
451
+ if (!result.path) {
452
+ printInstallGuide();
453
+ process.exit(1);
454
+ }
455
+ return result.path;
456
+ }
457
+ export {
458
+ GITHUB_RELEASE_BASE,
459
+ MANAGED_BINARY_PATH,
460
+ METADATA_PATH,
461
+ VERSION_FILE_PATH,
462
+ askUser,
463
+ buildDownloadUrl,
464
+ buildFromSource,
465
+ detectPlatform,
466
+ downloadBinary,
467
+ ensureEngineBinary,
468
+ findEngineBinary,
469
+ getCachedVersion,
470
+ getEngineStatus,
471
+ hasCargoInstalled,
472
+ healthCheck,
473
+ installEngine,
474
+ printInstallGuide,
475
+ readMetadata,
476
+ requireEngineBinary,
477
+ setCachedVersion,
478
+ verifyBinary,
479
+ writeMetadata
480
+ };