@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/chunk-NUPJYPFU.mjs +801 -0
- package/dist/cli/index.js +62 -38
- package/dist/cli/index.mjs +5 -6
- package/dist/dev-server.js +3 -3
- package/dist/dev-server.mjs +1 -1
- package/dist/engine-binary-FKTZAR56.mjs +480 -0
- package/dist/index.js +3 -3
- package/dist/index.mjs +1 -1
- package/package.json +2 -2
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
|
-
|
|
14458
|
-
|
|
14459
|
-
|
|
14460
|
-
|
|
14461
|
-
|
|
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
|
|
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 = "
|
|
15789
|
+
src = ".",
|
|
15765
15790
|
mode = "infer",
|
|
15766
|
-
include = ["**/*.workflow.tsx"],
|
|
15767
|
-
outDir = "dist
|
|
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) => {
|
package/dist/cli/index.mjs
CHANGED
|
@@ -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-
|
|
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-
|
|
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();
|
package/dist/dev-server.js
CHANGED
|
@@ -12289,10 +12289,10 @@ async function createDevServer(options = {}) {
|
|
|
12289
12289
|
}
|
|
12290
12290
|
const {
|
|
12291
12291
|
port = 5199,
|
|
12292
|
-
src = "
|
|
12292
|
+
src = ".",
|
|
12293
12293
|
mode = "infer",
|
|
12294
|
-
include = ["**/*.workflow.tsx"],
|
|
12295
|
-
outDir = "dist
|
|
12294
|
+
include = ["models/**/*.ts", "app/**/*.tsx", "**/*.workflow.tsx"],
|
|
12295
|
+
outDir = "dist",
|
|
12296
12296
|
seed = false,
|
|
12297
12297
|
apiUrl: rawApiUrl = "auto",
|
|
12298
12298
|
authToken: explicitToken,
|
package/dist/dev-server.mjs
CHANGED
|
@@ -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
|
+
};
|