flockbay 0.10.43 → 0.10.44
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/bin/flockbay-mcp.mjs +8 -2
- package/bin/flockbay.mjs +8 -2
- package/dist/{index-ZFx58JSw.mjs → index-BfBX93aY.mjs} +61 -27
- package/dist/{index-Bih-iANW.cjs → index-CVBvClyV.cjs} +61 -27
- package/dist/index.cjs +2 -2
- package/dist/index.mjs +2 -2
- package/dist/lib.cjs +1 -1
- package/dist/lib.mjs +1 -1
- package/dist/{migratePlugin-CrSh19dY.cjs → migratePlugin-BL02mitg.cjs} +1 -1
- package/dist/{migratePlugin-BenVKITz.mjs → migratePlugin-DAAX2TDX.mjs} +1 -1
- package/dist/{runCodex-aBjsormW.mjs → runCodex-C_dwGw9p.mjs} +2 -2
- package/dist/{runCodex-CJa61r9H.cjs → runCodex-DcQmhprg.cjs} +2 -2
- package/dist/{runGemini-gcPF3ASy.cjs → runGemini-CJF0id5I.cjs} +2 -2
- package/dist/{runGemini-D9bi1Ih3.mjs → runGemini-CWiIoJag.mjs} +2 -2
- package/dist/{types-1s9-Oj5w.mjs → types-D8EqTVgB.mjs} +189 -9
- package/dist/{types-DTy-RPNv.cjs → types-tRJ8NBIX.cjs} +190 -10
- package/package.json +1 -1
package/bin/flockbay-mcp.mjs
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
import { execFileSync } from 'node:child_process';
|
|
4
4
|
import { existsSync } from 'node:fs';
|
|
5
5
|
import { dirname, join } from 'node:path';
|
|
6
|
-
import { fileURLToPath } from 'node:url';
|
|
6
|
+
import { fileURLToPath, pathToFileURL } from 'node:url';
|
|
7
7
|
|
|
8
8
|
// Ensure Node flags to reduce noisy warnings on stdout (which could interfere with MCP).
|
|
9
9
|
const hasNoWarnings = process.execArgv.includes('--no-warnings');
|
|
@@ -25,7 +25,13 @@ function resolveTsxImportArgs() {
|
|
|
25
25
|
join(projectRoot, 'node_modules', 'tsx', 'dist', 'index.js'),
|
|
26
26
|
];
|
|
27
27
|
const resolved = candidates.find(existsSync);
|
|
28
|
-
return resolved ? ['--import', resolved] : ['--import', 'tsx'];
|
|
28
|
+
return resolved ? ['--import', toNodeSpecifier(resolved)] : ['--import', 'tsx'];
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function toNodeSpecifier(p) {
|
|
32
|
+
if (process.platform !== 'win32') return p;
|
|
33
|
+
if (!/^[a-zA-Z]:[\\/]/.test(p)) return p;
|
|
34
|
+
return pathToFileURL(p).href;
|
|
29
35
|
}
|
|
30
36
|
|
|
31
37
|
if (!hasNoWarnings || !hasNoDeprecation || useTsx) {
|
package/bin/flockbay.mjs
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
import { execFileSync } from 'node:child_process';
|
|
4
4
|
import { existsSync, statSync } from 'node:fs';
|
|
5
5
|
import { dirname, join } from 'node:path';
|
|
6
|
-
import { fileURLToPath } from 'node:url';
|
|
6
|
+
import { fileURLToPath, pathToFileURL } from 'node:url';
|
|
7
7
|
|
|
8
8
|
// Ensure Node flags to reduce noisy warnings on stdout.
|
|
9
9
|
const hasNoWarnings = process.execArgv.includes('--no-warnings');
|
|
@@ -54,7 +54,13 @@ function resolveTsxImportArgs() {
|
|
|
54
54
|
join(projectRoot, 'node_modules', 'tsx', 'dist', 'index.js'),
|
|
55
55
|
];
|
|
56
56
|
const resolved = candidates.find(existsSync);
|
|
57
|
-
return resolved ? ['--import', resolved] : ['--import', 'tsx'];
|
|
57
|
+
return resolved ? ['--import', toNodeSpecifier(resolved)] : ['--import', 'tsx'];
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
function toNodeSpecifier(p) {
|
|
61
|
+
if (process.platform !== 'win32') return p;
|
|
62
|
+
if (!/^[a-zA-Z]:[\\/]/.test(p)) return p;
|
|
63
|
+
return pathToFileURL(p).href;
|
|
58
64
|
}
|
|
59
65
|
|
|
60
66
|
const rewrittenArgs = rewriteTopLevelAliases(process.argv.slice(2));
|
|
@@ -2,7 +2,7 @@ import{createRequire as _pkgrollCR}from"node:module";const require=_pkgrollCR(im
|
|
|
2
2
|
import * as os from 'node:os';
|
|
3
3
|
import os__default, { homedir } from 'node:os';
|
|
4
4
|
import { randomUUID, createCipheriv, randomBytes, createHash as createHash$1 } from 'node:crypto';
|
|
5
|
-
import { l as logger, b as projectPath, d as backoff, e as delay, R as RawJSONLinesSchema, c as configuration, f as readDaemonState, g as clearDaemonState, p as packageJson, r as readSettings, h as readCredentials, u as updateSettings, o as openBrowser, w as writeCredentials, j as unrealMcpPythonDir, k as acquireDaemonLock, m as writeDaemonState, n as ApiMachineClient, q as releaseDaemonLock, s as sendUnrealMcpTcpCommand, A as ApiClient, v as validatePath, t as run, x as run$1, y as buildShellInvocation, z as clearCredentials, B as clearMachineId, C as authenticateCodex, D as syncCodexCliAuth, E as authenticateClaude, F as authenticateGemini, i as installUnrealMcpPluginToEngine, G as buildAndInstallUnrealMcpPlugin, H as installUnrealMcpPluginToProject, I as getLatestDaemonLog, J as normalizeServerUrlForNode } from './types-
|
|
5
|
+
import { l as logger, b as projectPath, d as backoff, e as delay, R as RawJSONLinesSchema, c as configuration, f as readDaemonState, g as clearDaemonState, p as packageJson, r as readSettings, h as readCredentials, u as updateSettings, o as openBrowser, w as writeCredentials, j as unrealMcpPythonDir, k as acquireDaemonLock, m as writeDaemonState, n as ApiMachineClient, q as releaseDaemonLock, s as sendUnrealMcpTcpCommand, A as ApiClient, v as validatePath, t as run, x as run$1, y as buildShellInvocation, z as clearCredentials, B as clearMachineId, C as authenticateCodex, D as syncCodexCliAuth, E as authenticateClaude, F as authenticateGemini, i as installUnrealMcpPluginToEngine, G as buildAndInstallUnrealMcpPlugin, H as installUnrealMcpPluginToProject, I as getLatestDaemonLog, J as normalizeServerUrlForNode } from './types-D8EqTVgB.mjs';
|
|
6
6
|
import { spawn, execFileSync, execSync } from 'node:child_process';
|
|
7
7
|
import * as path from 'node:path';
|
|
8
8
|
import path__default, { resolve, join, dirname } from 'node:path';
|
|
@@ -14,7 +14,7 @@ import fs$1, { readFile, access as access$1, mkdir, readdir, stat, writeFile, co
|
|
|
14
14
|
import fs$2, { watch, access, mkdir as mkdir$1, writeFile as writeFile$1, rm } from 'fs/promises';
|
|
15
15
|
import { useStdout, useInput, Box, Text, render } from 'ink';
|
|
16
16
|
import React, { useState, useRef, useEffect, useCallback } from 'react';
|
|
17
|
-
import { fileURLToPath } from 'node:url';
|
|
17
|
+
import { fileURLToPath, pathToFileURL } from 'node:url';
|
|
18
18
|
import axios from 'axios';
|
|
19
19
|
import 'socket.io-client';
|
|
20
20
|
import { spawn as spawn$1, execFileSync as execFileSync$1 } from 'child_process';
|
|
@@ -5261,13 +5261,35 @@ function resolveTsxImportArgs(projectRoot) {
|
|
|
5261
5261
|
join(projectRoot, "node_modules", "tsx", "dist", "index.js")
|
|
5262
5262
|
];
|
|
5263
5263
|
const resolved = candidates.find(existsSync);
|
|
5264
|
-
return resolved ? ["--import", resolved] : ["--import", "tsx"];
|
|
5264
|
+
return resolved ? ["--import", toNodeSpecifier(resolved)] : ["--import", "tsx"];
|
|
5265
|
+
}
|
|
5266
|
+
function toNodeSpecifier(p) {
|
|
5267
|
+
if (process$1.platform !== "win32") return p;
|
|
5268
|
+
if (!/^[a-zA-Z]:[\\/]/.test(p)) return p;
|
|
5269
|
+
return pathToFileURL(p).href;
|
|
5265
5270
|
}
|
|
5266
5271
|
function spawnFlockbayCLI(args, options = {}) {
|
|
5267
5272
|
const projectRoot = projectPath();
|
|
5268
5273
|
const distEntrypoint = join(projectRoot, "dist", "index.mjs");
|
|
5269
5274
|
const devEntrypoint = join(projectRoot, "src", "index.ts");
|
|
5270
|
-
const entrypoint =
|
|
5275
|
+
const entrypoint = (() => {
|
|
5276
|
+
const forceSrc = process$1.env.FLOCKBAY_USE_SRC === "1";
|
|
5277
|
+
const forceDist = process$1.env.FLOCKBAY_USE_DIST === "1";
|
|
5278
|
+
const hasDist = existsSync(distEntrypoint);
|
|
5279
|
+
const hasDev = existsSync(devEntrypoint);
|
|
5280
|
+
if (forceSrc && hasDev) return devEntrypoint;
|
|
5281
|
+
if (forceDist && hasDist) return distEntrypoint;
|
|
5282
|
+
if (hasDist && hasDev) {
|
|
5283
|
+
try {
|
|
5284
|
+
const devTime = statSync(devEntrypoint).mtimeMs;
|
|
5285
|
+
const distTime = statSync(distEntrypoint).mtimeMs;
|
|
5286
|
+
if (devTime > distTime) return devEntrypoint;
|
|
5287
|
+
} catch {
|
|
5288
|
+
}
|
|
5289
|
+
return distEntrypoint;
|
|
5290
|
+
}
|
|
5291
|
+
return hasDist ? distEntrypoint : devEntrypoint;
|
|
5292
|
+
})();
|
|
5271
5293
|
const useTsx = entrypoint.endsWith(".ts");
|
|
5272
5294
|
const desiredCwd = "cwd" in options && typeof options.cwd === "string" ? options.cwd : process$1.cwd();
|
|
5273
5295
|
const windowsHide = typeof options?.windowsHide === "boolean" ? Boolean(options.windowsHide) : process$1.platform === "win32";
|
|
@@ -5683,12 +5705,14 @@ async function enforceCliVersionPolicy(opts) {
|
|
|
5683
5705
|
const policy = await fetchCliVersionPolicy({ serverUrl: opts.serverUrl, timeoutMs: opts.timeoutMs });
|
|
5684
5706
|
const evaluation = evaluateCliVersion({ currentVersion, policy });
|
|
5685
5707
|
if (evaluation.status === "update_required") {
|
|
5686
|
-
|
|
5687
|
-
|
|
5688
|
-
|
|
5689
|
-
|
|
5690
|
-
|
|
5691
|
-
|
|
5708
|
+
try {
|
|
5709
|
+
opts.onUpdateRequired?.({
|
|
5710
|
+
minimumSupported: evaluation.minimumSupported,
|
|
5711
|
+
updateCommand: evaluation.updateCommand,
|
|
5712
|
+
message: evaluation.message
|
|
5713
|
+
});
|
|
5714
|
+
} catch {
|
|
5715
|
+
}
|
|
5692
5716
|
}
|
|
5693
5717
|
if (evaluation.status === "update_available") {
|
|
5694
5718
|
try {
|
|
@@ -5789,6 +5813,14 @@ async function startDaemon() {
|
|
|
5789
5813
|
serverUrl: configuration.serverUrl,
|
|
5790
5814
|
currentVersion: packageJson.version,
|
|
5791
5815
|
timeoutMs: Number.parseInt(process.env.FLOCKBAY_CLI_VERSION_CHECK_TIMEOUT_MS || "3000", 10) || 3e3,
|
|
5816
|
+
onUpdateRequired: ({ minimumSupported, updateCommand, message }) => {
|
|
5817
|
+
const note = message ? `
|
|
5818
|
+
${message}` : "";
|
|
5819
|
+
console.error(
|
|
5820
|
+
`CLI update required (installed: ${packageJson.version}, required: ${minimumSupported})${note}
|
|
5821
|
+
Update: ${updateCommand}`
|
|
5822
|
+
);
|
|
5823
|
+
},
|
|
5792
5824
|
onUpdateAvailable: ({ latest, updateCommand, message }) => {
|
|
5793
5825
|
const note = message ? `
|
|
5794
5826
|
${message}` : "";
|
|
@@ -5798,12 +5830,7 @@ Update: ${updateCommand}`);
|
|
|
5798
5830
|
});
|
|
5799
5831
|
} catch (err) {
|
|
5800
5832
|
const msg = err instanceof Error ? err.message : String(err);
|
|
5801
|
-
|
|
5802
|
-
console.error(msg);
|
|
5803
|
-
process.exit(1);
|
|
5804
|
-
} else {
|
|
5805
|
-
logger.debug("[DAEMON RUN] CLI version policy check failed (non-fatal):", msg);
|
|
5806
|
-
}
|
|
5833
|
+
logger.debug("[DAEMON RUN] CLI version policy check failed (non-fatal):", msg);
|
|
5807
5834
|
}
|
|
5808
5835
|
logger.debug("[DAEMON RUN] Auth and machine setup complete");
|
|
5809
5836
|
const shouldStartUnrealMcp = String(process.env.FLOCKBAY_UNREAL_MCP_ENABLED || "").trim() === "1";
|
|
@@ -6579,10 +6606,18 @@ Log: ${logPath || `not found (check ${configuration.logsDir})`}` + formatLogExce
|
|
|
6579
6606
|
cliPolicyCheckInFlight = true;
|
|
6580
6607
|
lastCliPolicyCheckAtMs = Date.now();
|
|
6581
6608
|
try {
|
|
6582
|
-
await enforceCliVersionPolicy({
|
|
6609
|
+
const { evaluation } = await enforceCliVersionPolicy({
|
|
6583
6610
|
serverUrl: configuration.serverUrl,
|
|
6584
6611
|
currentVersion: packageJson.version,
|
|
6585
6612
|
timeoutMs: Number.parseInt(process.env.FLOCKBAY_CLI_VERSION_CHECK_TIMEOUT_MS || "3000", 10) || 3e3,
|
|
6613
|
+
onUpdateRequired: ({ minimumSupported, updateCommand, message }) => {
|
|
6614
|
+
const note = message ? `
|
|
6615
|
+
${message}` : "";
|
|
6616
|
+
logger.debug(
|
|
6617
|
+
`[DAEMON RUN] CLI update required (installed: ${packageJson.version}, required: ${minimumSupported}).${note}
|
|
6618
|
+
Update: ${updateCommand}`
|
|
6619
|
+
);
|
|
6620
|
+
},
|
|
6586
6621
|
onUpdateAvailable: ({ latest, updateCommand, message }) => {
|
|
6587
6622
|
const note = message ? `
|
|
6588
6623
|
${message}` : "";
|
|
@@ -6592,13 +6627,10 @@ Update: ${updateCommand}`
|
|
|
6592
6627
|
);
|
|
6593
6628
|
}
|
|
6594
6629
|
});
|
|
6630
|
+
if (evaluation.status === "update_required") {
|
|
6631
|
+
}
|
|
6595
6632
|
} catch (err) {
|
|
6596
6633
|
const msg = err instanceof Error ? err.message : String(err);
|
|
6597
|
-
if (/^CLI update required\b/i.test(msg)) {
|
|
6598
|
-
logger.debug("[DAEMON RUN] CLI update required; shutting down daemon:", msg);
|
|
6599
|
-
requestShutdown("exception", msg);
|
|
6600
|
-
return;
|
|
6601
|
-
}
|
|
6602
6634
|
logger.debug("[DAEMON RUN] CLI version policy check failed (non-fatal):", msg);
|
|
6603
6635
|
} finally {
|
|
6604
6636
|
cliPolicyCheckInFlight = false;
|
|
@@ -14882,7 +14914,8 @@ async function startDaemonDetachedOrExit(opts) {
|
|
|
14882
14914
|
console.log(chalk.gray(`Daemon: ${daemon?.pid ? `pid=${daemon.pid} port=${daemon.httpPort}` : "not running"}`));
|
|
14883
14915
|
console.log("");
|
|
14884
14916
|
if (opts?.openWebapp) openUrlBestEffort(configuration.webappUrl);
|
|
14885
|
-
process.
|
|
14917
|
+
process.exitCode = 0;
|
|
14918
|
+
return;
|
|
14886
14919
|
}
|
|
14887
14920
|
const authMismatch = lastUpsertStatus === 401 || /unauthorized/i.test(lastConnectError);
|
|
14888
14921
|
if (authMismatch && !opts?.reauthAttempted) {
|
|
@@ -14953,7 +14986,8 @@ async function startDaemonDetachedOrExit(opts) {
|
|
|
14953
14986
|
console.log(chalk.gray(`Daemon: ${daemon?.pid ? `pid=${daemon.pid} port=${daemon.httpPort}` : "not running"}`));
|
|
14954
14987
|
console.log("");
|
|
14955
14988
|
if (opts?.openWebapp) openUrlBestEffort(configuration.webappUrl);
|
|
14956
|
-
process.
|
|
14989
|
+
process.exitCode = 0;
|
|
14990
|
+
return;
|
|
14957
14991
|
} else {
|
|
14958
14992
|
const latest = await getLatestDaemonLog();
|
|
14959
14993
|
if (latest?.path) console.error(`Latest daemon log: ${latest.path}`);
|
|
@@ -15083,7 +15117,7 @@ async function authAndSetupMachineIfNeeded() {
|
|
|
15083
15117
|
process.exit(1);
|
|
15084
15118
|
}
|
|
15085
15119
|
try {
|
|
15086
|
-
const { migrateUnrealMcpToFlockbayMcp } = await import('./migratePlugin-
|
|
15120
|
+
const { migrateUnrealMcpToFlockbayMcp } = await import('./migratePlugin-DAAX2TDX.mjs');
|
|
15087
15121
|
const result = migrateUnrealMcpToFlockbayMcp({
|
|
15088
15122
|
engineRoot,
|
|
15089
15123
|
projectUprojectPath: project || void 0,
|
|
@@ -15222,7 +15256,7 @@ ${engineRoot}`, {
|
|
|
15222
15256
|
} else if (subcommand === "codex") {
|
|
15223
15257
|
try {
|
|
15224
15258
|
await chdirToNearestUprojectRootIfPresent();
|
|
15225
|
-
const { runCodex } = await import('./runCodex-
|
|
15259
|
+
const { runCodex } = await import('./runCodex-C_dwGw9p.mjs');
|
|
15226
15260
|
let startedBy = void 0;
|
|
15227
15261
|
let sessionId = void 0;
|
|
15228
15262
|
for (let i = 1; i < args.length; i++) {
|
|
@@ -15324,7 +15358,7 @@ ${engineRoot}`, {
|
|
|
15324
15358
|
}
|
|
15325
15359
|
try {
|
|
15326
15360
|
await chdirToNearestUprojectRootIfPresent();
|
|
15327
|
-
const { runGemini } = await import('./runGemini-
|
|
15361
|
+
const { runGemini } = await import('./runGemini-CWiIoJag.mjs');
|
|
15328
15362
|
let startedBy = void 0;
|
|
15329
15363
|
let sessionId = void 0;
|
|
15330
15364
|
for (let i = 1; i < args.length; i++) {
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
var chalk = require('chalk');
|
|
4
4
|
var os = require('node:os');
|
|
5
5
|
var node_crypto = require('node:crypto');
|
|
6
|
-
var types = require('./types-
|
|
6
|
+
var types = require('./types-tRJ8NBIX.cjs');
|
|
7
7
|
var node_child_process = require('node:child_process');
|
|
8
8
|
var path = require('node:path');
|
|
9
9
|
var node_readline = require('node:readline');
|
|
@@ -1316,7 +1316,7 @@ function buildDaemonSafeEnv(baseEnv, binPath) {
|
|
|
1316
1316
|
env[pathKey] = [...prepend, ...existingParts].join(pathSep);
|
|
1317
1317
|
return env;
|
|
1318
1318
|
}
|
|
1319
|
-
const __filename$1 = node_url.fileURLToPath((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index-
|
|
1319
|
+
const __filename$1 = node_url.fileURLToPath((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index-CVBvClyV.cjs', document.baseURI).href)));
|
|
1320
1320
|
const __dirname$1 = path.join(__filename$1, "..");
|
|
1321
1321
|
function getGlobalClaudeVersion(claudeExecutable) {
|
|
1322
1322
|
try {
|
|
@@ -5283,13 +5283,35 @@ function resolveTsxImportArgs(projectRoot) {
|
|
|
5283
5283
|
path.join(projectRoot, "node_modules", "tsx", "dist", "index.js")
|
|
5284
5284
|
];
|
|
5285
5285
|
const resolved = candidates.find(fs.existsSync);
|
|
5286
|
-
return resolved ? ["--import", resolved] : ["--import", "tsx"];
|
|
5286
|
+
return resolved ? ["--import", toNodeSpecifier(resolved)] : ["--import", "tsx"];
|
|
5287
|
+
}
|
|
5288
|
+
function toNodeSpecifier(p) {
|
|
5289
|
+
if (process$1.platform !== "win32") return p;
|
|
5290
|
+
if (!/^[a-zA-Z]:[\\/]/.test(p)) return p;
|
|
5291
|
+
return node_url.pathToFileURL(p).href;
|
|
5287
5292
|
}
|
|
5288
5293
|
function spawnFlockbayCLI(args, options = {}) {
|
|
5289
5294
|
const projectRoot = types.projectPath();
|
|
5290
5295
|
const distEntrypoint = path.join(projectRoot, "dist", "index.mjs");
|
|
5291
5296
|
const devEntrypoint = path.join(projectRoot, "src", "index.ts");
|
|
5292
|
-
const entrypoint =
|
|
5297
|
+
const entrypoint = (() => {
|
|
5298
|
+
const forceSrc = process$1.env.FLOCKBAY_USE_SRC === "1";
|
|
5299
|
+
const forceDist = process$1.env.FLOCKBAY_USE_DIST === "1";
|
|
5300
|
+
const hasDist = fs.existsSync(distEntrypoint);
|
|
5301
|
+
const hasDev = fs.existsSync(devEntrypoint);
|
|
5302
|
+
if (forceSrc && hasDev) return devEntrypoint;
|
|
5303
|
+
if (forceDist && hasDist) return distEntrypoint;
|
|
5304
|
+
if (hasDist && hasDev) {
|
|
5305
|
+
try {
|
|
5306
|
+
const devTime = fs.statSync(devEntrypoint).mtimeMs;
|
|
5307
|
+
const distTime = fs.statSync(distEntrypoint).mtimeMs;
|
|
5308
|
+
if (devTime > distTime) return devEntrypoint;
|
|
5309
|
+
} catch {
|
|
5310
|
+
}
|
|
5311
|
+
return distEntrypoint;
|
|
5312
|
+
}
|
|
5313
|
+
return hasDist ? distEntrypoint : devEntrypoint;
|
|
5314
|
+
})();
|
|
5293
5315
|
const useTsx = entrypoint.endsWith(".ts");
|
|
5294
5316
|
const desiredCwd = "cwd" in options && typeof options.cwd === "string" ? options.cwd : process$1.cwd();
|
|
5295
5317
|
const windowsHide = typeof options?.windowsHide === "boolean" ? Boolean(options.windowsHide) : process$1.platform === "win32";
|
|
@@ -5705,12 +5727,14 @@ async function enforceCliVersionPolicy(opts) {
|
|
|
5705
5727
|
const policy = await fetchCliVersionPolicy({ serverUrl: opts.serverUrl, timeoutMs: opts.timeoutMs });
|
|
5706
5728
|
const evaluation = evaluateCliVersion({ currentVersion, policy });
|
|
5707
5729
|
if (evaluation.status === "update_required") {
|
|
5708
|
-
|
|
5709
|
-
|
|
5710
|
-
|
|
5711
|
-
|
|
5712
|
-
|
|
5713
|
-
|
|
5730
|
+
try {
|
|
5731
|
+
opts.onUpdateRequired?.({
|
|
5732
|
+
minimumSupported: evaluation.minimumSupported,
|
|
5733
|
+
updateCommand: evaluation.updateCommand,
|
|
5734
|
+
message: evaluation.message
|
|
5735
|
+
});
|
|
5736
|
+
} catch {
|
|
5737
|
+
}
|
|
5714
5738
|
}
|
|
5715
5739
|
if (evaluation.status === "update_available") {
|
|
5716
5740
|
try {
|
|
@@ -5811,6 +5835,14 @@ async function startDaemon() {
|
|
|
5811
5835
|
serverUrl: types.configuration.serverUrl,
|
|
5812
5836
|
currentVersion: types.packageJson.version,
|
|
5813
5837
|
timeoutMs: Number.parseInt(process.env.FLOCKBAY_CLI_VERSION_CHECK_TIMEOUT_MS || "3000", 10) || 3e3,
|
|
5838
|
+
onUpdateRequired: ({ minimumSupported, updateCommand, message }) => {
|
|
5839
|
+
const note = message ? `
|
|
5840
|
+
${message}` : "";
|
|
5841
|
+
console.error(
|
|
5842
|
+
`CLI update required (installed: ${types.packageJson.version}, required: ${minimumSupported})${note}
|
|
5843
|
+
Update: ${updateCommand}`
|
|
5844
|
+
);
|
|
5845
|
+
},
|
|
5814
5846
|
onUpdateAvailable: ({ latest, updateCommand, message }) => {
|
|
5815
5847
|
const note = message ? `
|
|
5816
5848
|
${message}` : "";
|
|
@@ -5820,12 +5852,7 @@ Update: ${updateCommand}`);
|
|
|
5820
5852
|
});
|
|
5821
5853
|
} catch (err) {
|
|
5822
5854
|
const msg = err instanceof Error ? err.message : String(err);
|
|
5823
|
-
|
|
5824
|
-
console.error(msg);
|
|
5825
|
-
process.exit(1);
|
|
5826
|
-
} else {
|
|
5827
|
-
types.logger.debug("[DAEMON RUN] CLI version policy check failed (non-fatal):", msg);
|
|
5828
|
-
}
|
|
5855
|
+
types.logger.debug("[DAEMON RUN] CLI version policy check failed (non-fatal):", msg);
|
|
5829
5856
|
}
|
|
5830
5857
|
types.logger.debug("[DAEMON RUN] Auth and machine setup complete");
|
|
5831
5858
|
const shouldStartUnrealMcp = String(process.env.FLOCKBAY_UNREAL_MCP_ENABLED || "").trim() === "1";
|
|
@@ -6601,10 +6628,18 @@ Log: ${logPath || `not found (check ${types.configuration.logsDir})`}` + formatL
|
|
|
6601
6628
|
cliPolicyCheckInFlight = true;
|
|
6602
6629
|
lastCliPolicyCheckAtMs = Date.now();
|
|
6603
6630
|
try {
|
|
6604
|
-
await enforceCliVersionPolicy({
|
|
6631
|
+
const { evaluation } = await enforceCliVersionPolicy({
|
|
6605
6632
|
serverUrl: types.configuration.serverUrl,
|
|
6606
6633
|
currentVersion: types.packageJson.version,
|
|
6607
6634
|
timeoutMs: Number.parseInt(process.env.FLOCKBAY_CLI_VERSION_CHECK_TIMEOUT_MS || "3000", 10) || 3e3,
|
|
6635
|
+
onUpdateRequired: ({ minimumSupported, updateCommand, message }) => {
|
|
6636
|
+
const note = message ? `
|
|
6637
|
+
${message}` : "";
|
|
6638
|
+
types.logger.debug(
|
|
6639
|
+
`[DAEMON RUN] CLI update required (installed: ${types.packageJson.version}, required: ${minimumSupported}).${note}
|
|
6640
|
+
Update: ${updateCommand}`
|
|
6641
|
+
);
|
|
6642
|
+
},
|
|
6608
6643
|
onUpdateAvailable: ({ latest, updateCommand, message }) => {
|
|
6609
6644
|
const note = message ? `
|
|
6610
6645
|
${message}` : "";
|
|
@@ -6614,13 +6649,10 @@ Update: ${updateCommand}`
|
|
|
6614
6649
|
);
|
|
6615
6650
|
}
|
|
6616
6651
|
});
|
|
6652
|
+
if (evaluation.status === "update_required") {
|
|
6653
|
+
}
|
|
6617
6654
|
} catch (err) {
|
|
6618
6655
|
const msg = err instanceof Error ? err.message : String(err);
|
|
6619
|
-
if (/^CLI update required\b/i.test(msg)) {
|
|
6620
|
-
types.logger.debug("[DAEMON RUN] CLI update required; shutting down daemon:", msg);
|
|
6621
|
-
requestShutdown("exception", msg);
|
|
6622
|
-
return;
|
|
6623
|
-
}
|
|
6624
6656
|
types.logger.debug("[DAEMON RUN] CLI version policy check failed (non-fatal):", msg);
|
|
6625
6657
|
} finally {
|
|
6626
6658
|
cliPolicyCheckInFlight = false;
|
|
@@ -14904,7 +14936,8 @@ async function startDaemonDetachedOrExit(opts) {
|
|
|
14904
14936
|
console.log(chalk.gray(`Daemon: ${daemon?.pid ? `pid=${daemon.pid} port=${daemon.httpPort}` : "not running"}`));
|
|
14905
14937
|
console.log("");
|
|
14906
14938
|
if (opts?.openWebapp) openUrlBestEffort(types.configuration.webappUrl);
|
|
14907
|
-
process.
|
|
14939
|
+
process.exitCode = 0;
|
|
14940
|
+
return;
|
|
14908
14941
|
}
|
|
14909
14942
|
const authMismatch = lastUpsertStatus === 401 || /unauthorized/i.test(lastConnectError);
|
|
14910
14943
|
if (authMismatch && !opts?.reauthAttempted) {
|
|
@@ -14975,7 +15008,8 @@ async function startDaemonDetachedOrExit(opts) {
|
|
|
14975
15008
|
console.log(chalk.gray(`Daemon: ${daemon?.pid ? `pid=${daemon.pid} port=${daemon.httpPort}` : "not running"}`));
|
|
14976
15009
|
console.log("");
|
|
14977
15010
|
if (opts?.openWebapp) openUrlBestEffort(types.configuration.webappUrl);
|
|
14978
|
-
process.
|
|
15011
|
+
process.exitCode = 0;
|
|
15012
|
+
return;
|
|
14979
15013
|
} else {
|
|
14980
15014
|
const latest = await types.getLatestDaemonLog();
|
|
14981
15015
|
if (latest?.path) console.error(`Latest daemon log: ${latest.path}`);
|
|
@@ -15105,7 +15139,7 @@ async function authAndSetupMachineIfNeeded() {
|
|
|
15105
15139
|
process.exit(1);
|
|
15106
15140
|
}
|
|
15107
15141
|
try {
|
|
15108
|
-
const { migrateUnrealMcpToFlockbayMcp } = await Promise.resolve().then(function () { return require('./migratePlugin-
|
|
15142
|
+
const { migrateUnrealMcpToFlockbayMcp } = await Promise.resolve().then(function () { return require('./migratePlugin-BL02mitg.cjs'); });
|
|
15109
15143
|
const result = migrateUnrealMcpToFlockbayMcp({
|
|
15110
15144
|
engineRoot,
|
|
15111
15145
|
projectUprojectPath: project || void 0,
|
|
@@ -15244,7 +15278,7 @@ ${engineRoot}`, {
|
|
|
15244
15278
|
} else if (subcommand === "codex") {
|
|
15245
15279
|
try {
|
|
15246
15280
|
await chdirToNearestUprojectRootIfPresent();
|
|
15247
|
-
const { runCodex } = await Promise.resolve().then(function () { return require('./runCodex-
|
|
15281
|
+
const { runCodex } = await Promise.resolve().then(function () { return require('./runCodex-DcQmhprg.cjs'); });
|
|
15248
15282
|
let startedBy = void 0;
|
|
15249
15283
|
let sessionId = void 0;
|
|
15250
15284
|
for (let i = 1; i < args.length; i++) {
|
|
@@ -15346,7 +15380,7 @@ ${engineRoot}`, {
|
|
|
15346
15380
|
}
|
|
15347
15381
|
try {
|
|
15348
15382
|
await chdirToNearestUprojectRootIfPresent();
|
|
15349
|
-
const { runGemini } = await Promise.resolve().then(function () { return require('./runGemini-
|
|
15383
|
+
const { runGemini } = await Promise.resolve().then(function () { return require('./runGemini-CJF0id5I.cjs'); });
|
|
15350
15384
|
let startedBy = void 0;
|
|
15351
15385
|
let sessionId = void 0;
|
|
15352
15386
|
for (let i = 1; i < args.length; i++) {
|
package/dist/index.cjs
CHANGED
package/dist/index.mjs
CHANGED
package/dist/lib.cjs
CHANGED
package/dist/lib.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { A as ApiClient, a as ApiSessionClient, R as RawJSONLinesSchema, c as configuration, l as logger } from './types-
|
|
1
|
+
export { A as ApiClient, a as ApiSessionClient, R as RawJSONLinesSchema, c as configuration, l as logger } from './types-D8EqTVgB.mjs';
|
|
2
2
|
import 'axios';
|
|
3
3
|
import 'node:fs';
|
|
4
4
|
import 'node:os';
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import fs__default from 'node:fs';
|
|
2
2
|
import path__default from 'node:path';
|
|
3
|
-
import { i as installUnrealMcpPluginToEngine } from './types-
|
|
3
|
+
import { i as installUnrealMcpPluginToEngine } from './types-D8EqTVgB.mjs';
|
|
4
4
|
import 'axios';
|
|
5
5
|
import 'node:os';
|
|
6
6
|
import 'node:events';
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { useStdout, useInput, Box, Text, render } from 'ink';
|
|
2
2
|
import React, { useState, useRef, useEffect, useCallback } from 'react';
|
|
3
|
-
import { l as logger, A as ApiClient, p as packageJson, c as configuration, r as readSettings, b as projectPath } from './types-
|
|
3
|
+
import { l as logger, A as ApiClient, p as packageJson, c as configuration, r as readSettings, b as projectPath } from './types-D8EqTVgB.mjs';
|
|
4
4
|
import { Client } from '@modelcontextprotocol/sdk/client/index.js';
|
|
5
5
|
import { StdioClientTransport } from '@modelcontextprotocol/sdk/client/stdio.js';
|
|
6
6
|
import { z } from 'zod';
|
|
@@ -10,7 +10,7 @@ import fs__default from 'node:fs';
|
|
|
10
10
|
import os__default from 'node:os';
|
|
11
11
|
import path__default, { resolve, join } from 'node:path';
|
|
12
12
|
import { spawnSync } from 'node:child_process';
|
|
13
|
-
import { s as shouldCountToolCall, c as consumeToolQuota, f as formatQuotaDeniedReason, h as hashObject, e as enforceCliVersionPolicy, i as initialMachineMetadata, E as ElicitationHub, n as notifyDaemonSessionStarted, M as MessageQueue2, P as PLATFORM_SYSTEM_PROMPT, a as setLatestUserImages, w as withUserImagesMarker, r as registerKillSessionHandler, b as MessageBuffer, d as startFlockbayServer, g as buildProjectCapsule, t as trimIdent, j as autoFinalizeCoordinationWorkItem, k as detectScreenshotsForGate, l as applyCoordinationSideEffectsFromMcpToolResult, m as stopCaffeinate } from './index-
|
|
13
|
+
import { s as shouldCountToolCall, c as consumeToolQuota, f as formatQuotaDeniedReason, h as hashObject, e as enforceCliVersionPolicy, i as initialMachineMetadata, E as ElicitationHub, n as notifyDaemonSessionStarted, M as MessageQueue2, P as PLATFORM_SYSTEM_PROMPT, a as setLatestUserImages, w as withUserImagesMarker, r as registerKillSessionHandler, b as MessageBuffer, d as startFlockbayServer, g as buildProjectCapsule, t as trimIdent, j as autoFinalizeCoordinationWorkItem, k as detectScreenshotsForGate, l as applyCoordinationSideEffectsFromMcpToolResult, m as stopCaffeinate } from './index-BfBX93aY.mjs';
|
|
14
14
|
import 'axios';
|
|
15
15
|
import 'node:events';
|
|
16
16
|
import 'socket.io-client';
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
var ink = require('ink');
|
|
4
4
|
var React = require('react');
|
|
5
|
-
var types = require('./types-
|
|
5
|
+
var types = require('./types-tRJ8NBIX.cjs');
|
|
6
6
|
var index_js = require('@modelcontextprotocol/sdk/client/index.js');
|
|
7
7
|
var stdio_js = require('@modelcontextprotocol/sdk/client/stdio.js');
|
|
8
8
|
var z = require('zod');
|
|
@@ -12,7 +12,7 @@ var fs = require('node:fs');
|
|
|
12
12
|
var os = require('node:os');
|
|
13
13
|
var path = require('node:path');
|
|
14
14
|
var node_child_process = require('node:child_process');
|
|
15
|
-
var index = require('./index-
|
|
15
|
+
var index = require('./index-CVBvClyV.cjs');
|
|
16
16
|
require('axios');
|
|
17
17
|
require('node:events');
|
|
18
18
|
require('socket.io-client');
|
|
@@ -6,8 +6,8 @@ var node_crypto = require('node:crypto');
|
|
|
6
6
|
var os = require('node:os');
|
|
7
7
|
var path = require('node:path');
|
|
8
8
|
var fs$2 = require('node:fs/promises');
|
|
9
|
-
var types = require('./types-
|
|
10
|
-
var index = require('./index-
|
|
9
|
+
var types = require('./types-tRJ8NBIX.cjs');
|
|
10
|
+
var index = require('./index-CVBvClyV.cjs');
|
|
11
11
|
var node_child_process = require('node:child_process');
|
|
12
12
|
var sdk = require('@agentclientprotocol/sdk');
|
|
13
13
|
var fs = require('fs');
|
|
@@ -4,8 +4,8 @@ import { randomUUID, createHash } from 'node:crypto';
|
|
|
4
4
|
import os__default from 'node:os';
|
|
5
5
|
import path__default, { resolve, join as join$1, basename } from 'node:path';
|
|
6
6
|
import { mkdir, writeFile, readFile } from 'node:fs/promises';
|
|
7
|
-
import { l as logger, p as packageJson, A as ApiClient, c as configuration, r as readSettings, b as projectPath } from './types-
|
|
8
|
-
import { s as shouldCountToolCall, c as consumeToolQuota, f as formatQuotaDeniedReason, h as hashObject, e as enforceCliVersionPolicy, i as initialMachineMetadata, n as notifyDaemonSessionStarted, M as MessageQueue2, g as buildProjectCapsule, a as setLatestUserImages, b as MessageBuffer, w as withUserImagesMarker, r as registerKillSessionHandler, d as startFlockbayServer, o as extractUserImagesMarker, p as getLatestUserImages, P as PLATFORM_SYSTEM_PROMPT, j as autoFinalizeCoordinationWorkItem, E as ElicitationHub, k as detectScreenshotsForGate, m as stopCaffeinate } from './index-
|
|
7
|
+
import { l as logger, p as packageJson, A as ApiClient, c as configuration, r as readSettings, b as projectPath } from './types-D8EqTVgB.mjs';
|
|
8
|
+
import { s as shouldCountToolCall, c as consumeToolQuota, f as formatQuotaDeniedReason, h as hashObject, e as enforceCliVersionPolicy, i as initialMachineMetadata, n as notifyDaemonSessionStarted, M as MessageQueue2, g as buildProjectCapsule, a as setLatestUserImages, b as MessageBuffer, w as withUserImagesMarker, r as registerKillSessionHandler, d as startFlockbayServer, o as extractUserImagesMarker, p as getLatestUserImages, P as PLATFORM_SYSTEM_PROMPT, j as autoFinalizeCoordinationWorkItem, E as ElicitationHub, k as detectScreenshotsForGate, m as stopCaffeinate } from './index-BfBX93aY.mjs';
|
|
9
9
|
import { spawn, spawnSync } from 'node:child_process';
|
|
10
10
|
import { ndJsonStream, ClientSideConnection } from '@agentclientprotocol/sdk';
|
|
11
11
|
import { existsSync, readFileSync, mkdirSync, writeFileSync } from 'fs';
|
|
@@ -23,7 +23,7 @@ import { createServer } from 'http';
|
|
|
23
23
|
import open$2 from 'open';
|
|
24
24
|
|
|
25
25
|
var name = "flockbay";
|
|
26
|
-
var version = "0.10.
|
|
26
|
+
var version = "0.10.44";
|
|
27
27
|
var description = "Flockbay CLI (local agent + daemon)";
|
|
28
28
|
var author = "Eduardo Orellana";
|
|
29
29
|
var license = "UNLICENSED";
|
|
@@ -3397,11 +3397,11 @@ function createBackoff(opts) {
|
|
|
3397
3397
|
}
|
|
3398
3398
|
let backoff = createBackoff();
|
|
3399
3399
|
|
|
3400
|
-
function looksLikeEngineRoot(engineRoot) {
|
|
3400
|
+
function looksLikeEngineRoot$1(engineRoot) {
|
|
3401
3401
|
if (!engineRoot) return false;
|
|
3402
3402
|
return fs__default.existsSync(path__default.join(engineRoot, "Engine")) && fs__default.existsSync(path__default.join(engineRoot, "Engine", "Plugins"));
|
|
3403
3403
|
}
|
|
3404
|
-
function findFilesNamedUnderDir(options) {
|
|
3404
|
+
function findFilesNamedUnderDir$1(options) {
|
|
3405
3405
|
const rootDir = options.rootDir;
|
|
3406
3406
|
const filename = options.filename;
|
|
3407
3407
|
const maxDepth = Math.max(0, Math.floor(options.maxDepth));
|
|
@@ -3429,7 +3429,7 @@ function findFilesNamedUnderDir(options) {
|
|
|
3429
3429
|
}
|
|
3430
3430
|
function installUnrealMcpPluginToEngine(engineRootRaw) {
|
|
3431
3431
|
const engineRoot = (engineRootRaw || "").trim();
|
|
3432
|
-
if (!looksLikeEngineRoot(engineRoot)) {
|
|
3432
|
+
if (!looksLikeEngineRoot$1(engineRoot)) {
|
|
3433
3433
|
return {
|
|
3434
3434
|
ok: false,
|
|
3435
3435
|
errorMessage: `Invalid engine root (expected an Unreal Engine install folder containing Engine/\u2026): ${engineRoot || "(empty)"}`
|
|
@@ -3443,7 +3443,7 @@ function installUnrealMcpPluginToEngine(engineRootRaw) {
|
|
|
3443
3443
|
const destUpluginPath = path__default.join(destDir, "FlockbayMCP.uplugin");
|
|
3444
3444
|
try {
|
|
3445
3445
|
const enginePluginsDir = path__default.join(engineRoot, "Engine", "Plugins");
|
|
3446
|
-
const candidates = findFilesNamedUnderDir({ rootDir: enginePluginsDir, filename: "FlockbayMCP.uplugin", maxDepth: 6 });
|
|
3446
|
+
const candidates = findFilesNamedUnderDir$1({ rootDir: enginePluginsDir, filename: "FlockbayMCP.uplugin", maxDepth: 6 });
|
|
3447
3447
|
const otherCopies = candidates.map((p) => path__default.resolve(p)).filter((p) => !p.startsWith(path__default.resolve(destDir) + path__default.sep));
|
|
3448
3448
|
if (otherCopies.length > 0) {
|
|
3449
3449
|
return {
|
|
@@ -3463,7 +3463,7 @@ Fix:
|
|
|
3463
3463
|
- Re-run the Flockbay MCP plugin install, then restart Unreal Editor so it rebuilds the plugin`
|
|
3464
3464
|
};
|
|
3465
3465
|
}
|
|
3466
|
-
const legacyCandidates = findFilesNamedUnderDir({ rootDir: enginePluginsDir, filename: "UnrealMCP.uplugin", maxDepth: 6 });
|
|
3466
|
+
const legacyCandidates = findFilesNamedUnderDir$1({ rootDir: enginePluginsDir, filename: "UnrealMCP.uplugin", maxDepth: 6 });
|
|
3467
3467
|
if (legacyCandidates.length > 0) {
|
|
3468
3468
|
return {
|
|
3469
3469
|
ok: false,
|
|
@@ -3542,7 +3542,7 @@ Error: ${message}`
|
|
|
3542
3542
|
}
|
|
3543
3543
|
}
|
|
3544
3544
|
|
|
3545
|
-
function readJsonIfPossible(filePath) {
|
|
3545
|
+
function readJsonIfPossible$1(filePath) {
|
|
3546
3546
|
try {
|
|
3547
3547
|
return JSON.parse(fs__default.readFileSync(filePath, "utf8"));
|
|
3548
3548
|
} catch {
|
|
@@ -3553,7 +3553,7 @@ function writeJsonPretty(filePath, value) {
|
|
|
3553
3553
|
fs__default.writeFileSync(filePath, JSON.stringify(value, null, 2) + "\n", "utf8");
|
|
3554
3554
|
}
|
|
3555
3555
|
function ensureProjectPluginEnabled(uprojectPath, pluginName) {
|
|
3556
|
-
const parsed = readJsonIfPossible(uprojectPath);
|
|
3556
|
+
const parsed = readJsonIfPossible$1(uprojectPath);
|
|
3557
3557
|
if (!parsed || typeof parsed !== "object") {
|
|
3558
3558
|
return { ok: false, error: `Invalid .uproject (expected JSON): ${uprojectPath}` };
|
|
3559
3559
|
}
|
|
@@ -3638,7 +3638,7 @@ Fix:
|
|
|
3638
3638
|
Expected: ${destUpluginPath}`
|
|
3639
3639
|
};
|
|
3640
3640
|
}
|
|
3641
|
-
const uplugin = readJsonIfPossible(destUpluginPath);
|
|
3641
|
+
const uplugin = readJsonIfPossible$1(destUpluginPath);
|
|
3642
3642
|
const friendlyName = typeof uplugin?.FriendlyName === "string" ? uplugin.FriendlyName : null;
|
|
3643
3643
|
const createdBy = typeof uplugin?.CreatedBy === "string" ? uplugin.CreatedBy : null;
|
|
3644
3644
|
if (friendlyName !== "Flockbay MCP" || createdBy !== "Respaced Inc.") {
|
|
@@ -3800,6 +3800,182 @@ Log: ${buildLogPath}`
|
|
|
3800
3800
|
return { ok: true, buildLogPath };
|
|
3801
3801
|
}
|
|
3802
3802
|
|
|
3803
|
+
function canWriteDir$1(dir) {
|
|
3804
|
+
const root = String(dir || "").trim();
|
|
3805
|
+
if (!root) return false;
|
|
3806
|
+
try {
|
|
3807
|
+
const tmp = path__default.join(root, `.__flockbay_write_test_${Date.now()}_${Math.random().toString(16).slice(2)}.tmp`);
|
|
3808
|
+
fs__default.writeFileSync(tmp, "ok", "utf8");
|
|
3809
|
+
fs__default.unlinkSync(tmp);
|
|
3810
|
+
return true;
|
|
3811
|
+
} catch {
|
|
3812
|
+
return false;
|
|
3813
|
+
}
|
|
3814
|
+
}
|
|
3815
|
+
function looksLikeEngineRoot(engineRoot) {
|
|
3816
|
+
if (!engineRoot) return false;
|
|
3817
|
+
return fs__default.existsSync(path__default.join(engineRoot, "Engine", "Plugins"));
|
|
3818
|
+
}
|
|
3819
|
+
function readJsonIfPossible(filePath) {
|
|
3820
|
+
try {
|
|
3821
|
+
return JSON.parse(fs__default.readFileSync(filePath, "utf8"));
|
|
3822
|
+
} catch {
|
|
3823
|
+
return null;
|
|
3824
|
+
}
|
|
3825
|
+
}
|
|
3826
|
+
function isPluginDescriptorOk(parsed) {
|
|
3827
|
+
const friendlyName = typeof parsed?.FriendlyName === "string" ? parsed.FriendlyName : null;
|
|
3828
|
+
const createdBy = typeof parsed?.CreatedBy === "string" ? parsed.CreatedBy : null;
|
|
3829
|
+
return friendlyName === "Flockbay MCP" && createdBy === "Respaced Inc.";
|
|
3830
|
+
}
|
|
3831
|
+
function isPathUnderDir(childPath, parentDir) {
|
|
3832
|
+
const child = path__default.resolve(childPath);
|
|
3833
|
+
const parent = path__default.resolve(parentDir);
|
|
3834
|
+
return child === parent || child.startsWith(parent + path__default.sep);
|
|
3835
|
+
}
|
|
3836
|
+
function findFilesNamedUnderDir(options) {
|
|
3837
|
+
const rootDir = options.rootDir;
|
|
3838
|
+
const filename = options.filename;
|
|
3839
|
+
const maxDepth = Math.max(0, Math.floor(options.maxDepth));
|
|
3840
|
+
const results = [];
|
|
3841
|
+
const visit = (dir, depth) => {
|
|
3842
|
+
if (depth > maxDepth) return;
|
|
3843
|
+
let entries = [];
|
|
3844
|
+
try {
|
|
3845
|
+
entries = fs__default.readdirSync(dir, { withFileTypes: true });
|
|
3846
|
+
} catch {
|
|
3847
|
+
return;
|
|
3848
|
+
}
|
|
3849
|
+
for (const entry of entries) {
|
|
3850
|
+
if (entry.name === ".DS_Store") continue;
|
|
3851
|
+
const full = path__default.join(dir, entry.name);
|
|
3852
|
+
if (entry.isDirectory()) {
|
|
3853
|
+
visit(full, depth + 1);
|
|
3854
|
+
continue;
|
|
3855
|
+
}
|
|
3856
|
+
if (entry.isFile() && entry.name === filename) results.push(full);
|
|
3857
|
+
}
|
|
3858
|
+
};
|
|
3859
|
+
visit(rootDir, 0);
|
|
3860
|
+
return results;
|
|
3861
|
+
}
|
|
3862
|
+
function readUprojectPluginEnabled(uprojectPath, pluginName) {
|
|
3863
|
+
const parsed = readJsonIfPossible(uprojectPath);
|
|
3864
|
+
if (!parsed || typeof parsed !== "object") {
|
|
3865
|
+
return { ok: false, error: `Invalid .uproject (expected JSON): ${uprojectPath}` };
|
|
3866
|
+
}
|
|
3867
|
+
const plugins = Array.isArray(parsed.Plugins) ? parsed.Plugins : [];
|
|
3868
|
+
for (const p of plugins) {
|
|
3869
|
+
if (!p || typeof p !== "object") continue;
|
|
3870
|
+
if (p.Name === pluginName) return { ok: true, enabled: p.Enabled === true };
|
|
3871
|
+
}
|
|
3872
|
+
return { ok: true, enabled: false };
|
|
3873
|
+
}
|
|
3874
|
+
function getUnrealMcpPluginDiskStatus(params) {
|
|
3875
|
+
const checkedAtMs = Date.now();
|
|
3876
|
+
const engineRoot = String(params?.engineRoot || "").trim();
|
|
3877
|
+
const installScope = String(params?.installScope || "auto");
|
|
3878
|
+
const projectUprojectPathRaw = typeof params?.projectUprojectPath === "string" ? params.projectUprojectPath.trim() : "";
|
|
3879
|
+
if (!engineRoot) return { success: false, error: "Missing engineRoot." };
|
|
3880
|
+
if (!looksLikeEngineRoot(engineRoot)) {
|
|
3881
|
+
return { success: false, error: `Invalid engine root (expected an Unreal Engine install folder containing Engine/Plugins): ${engineRoot}` };
|
|
3882
|
+
}
|
|
3883
|
+
const enginePluginsDir = path__default.join(engineRoot, "Engine", "Plugins");
|
|
3884
|
+
const enginePluginDir = path__default.join(enginePluginsDir, "FlockbayMCP");
|
|
3885
|
+
const engineUpluginPath = path__default.join(enginePluginDir, "FlockbayMCP.uplugin");
|
|
3886
|
+
const engineDescriptor = fs__default.existsSync(engineUpluginPath) ? readJsonIfPossible(engineUpluginPath) : null;
|
|
3887
|
+
const engineInfo = {
|
|
3888
|
+
pluginDir: enginePluginDir,
|
|
3889
|
+
upluginPath: engineUpluginPath,
|
|
3890
|
+
exists: fs__default.existsSync(engineUpluginPath),
|
|
3891
|
+
descriptorOk: engineDescriptor ? isPluginDescriptorOk(engineDescriptor) : false,
|
|
3892
|
+
hasBinaries: fs__default.existsSync(path__default.join(enginePluginDir, "Binaries")),
|
|
3893
|
+
enginePluginsWritable: canWriteDir$1(enginePluginsDir),
|
|
3894
|
+
conflicts: [],
|
|
3895
|
+
legacy: []
|
|
3896
|
+
};
|
|
3897
|
+
const conflictSet = /* @__PURE__ */ new Set();
|
|
3898
|
+
const legacySet = /* @__PURE__ */ new Set();
|
|
3899
|
+
const fastCandidates = [
|
|
3900
|
+
path__default.join(enginePluginsDir, "Marketplace", "FlockbayMCP", "FlockbayMCP.uplugin"),
|
|
3901
|
+
path__default.join(enginePluginsDir, "Marketplace", "UnrealMCP", "UnrealMCP.uplugin"),
|
|
3902
|
+
path__default.join(enginePluginsDir, "UnrealMCP", "UnrealMCP.uplugin")
|
|
3903
|
+
];
|
|
3904
|
+
for (const p of fastCandidates) {
|
|
3905
|
+
if (fs__default.existsSync(p)) {
|
|
3906
|
+
if (p.toLowerCase().endsWith("unrealmcp.uplugin")) legacySet.add(path__default.resolve(p));
|
|
3907
|
+
if (p.toLowerCase().endsWith("flockbaymcp.uplugin")) conflictSet.add(path__default.resolve(p));
|
|
3908
|
+
}
|
|
3909
|
+
}
|
|
3910
|
+
for (const p of findFilesNamedUnderDir({ rootDir: enginePluginsDir, filename: "FlockbayMCP.uplugin", maxDepth: 6 })) {
|
|
3911
|
+
const resolved = path__default.resolve(p);
|
|
3912
|
+
if (isPathUnderDir(resolved, enginePluginDir)) continue;
|
|
3913
|
+
conflictSet.add(resolved);
|
|
3914
|
+
}
|
|
3915
|
+
for (const p of findFilesNamedUnderDir({ rootDir: enginePluginsDir, filename: "UnrealMCP.uplugin", maxDepth: 6 })) {
|
|
3916
|
+
legacySet.add(path__default.resolve(p));
|
|
3917
|
+
}
|
|
3918
|
+
engineInfo.conflicts = Array.from(conflictSet).sort();
|
|
3919
|
+
engineInfo.legacy = Array.from(legacySet).sort();
|
|
3920
|
+
const project = (() => {
|
|
3921
|
+
if (!projectUprojectPathRaw) return null;
|
|
3922
|
+
const uprojectPath = path__default.resolve(projectUprojectPathRaw);
|
|
3923
|
+
if (!uprojectPath.toLowerCase().endsWith(".uproject")) {
|
|
3924
|
+
return { error: `Invalid .uproject path (expected *.uproject): ${uprojectPath}` };
|
|
3925
|
+
}
|
|
3926
|
+
if (!fs__default.existsSync(uprojectPath)) {
|
|
3927
|
+
return { error: `Missing .uproject: ${uprojectPath}` };
|
|
3928
|
+
}
|
|
3929
|
+
const projectRoot = path__default.dirname(uprojectPath);
|
|
3930
|
+
const pluginDir = path__default.join(projectRoot, "Plugins", "FlockbayMCP");
|
|
3931
|
+
const upluginPath = path__default.join(pluginDir, "FlockbayMCP.uplugin");
|
|
3932
|
+
const descriptor = fs__default.existsSync(upluginPath) ? readJsonIfPossible(upluginPath) : null;
|
|
3933
|
+
const enabled = readUprojectPluginEnabled(uprojectPath, "FlockbayMCP");
|
|
3934
|
+
if (!enabled.ok) return { error: enabled.error };
|
|
3935
|
+
return {
|
|
3936
|
+
uprojectPath,
|
|
3937
|
+
pluginDir,
|
|
3938
|
+
upluginPath,
|
|
3939
|
+
exists: fs__default.existsSync(upluginPath),
|
|
3940
|
+
descriptorOk: descriptor ? isPluginDescriptorOk(descriptor) : false,
|
|
3941
|
+
enabledInUproject: enabled.enabled
|
|
3942
|
+
};
|
|
3943
|
+
})();
|
|
3944
|
+
if (project && "error" in project) return { success: false, error: project.error };
|
|
3945
|
+
if (installScope === "project" && !project) {
|
|
3946
|
+
return { success: false, error: "Missing projectUprojectPath (required for installScope=project)." };
|
|
3947
|
+
}
|
|
3948
|
+
const engineInstalled = engineInfo.exists && engineInfo.descriptorOk && engineInfo.hasBinaries;
|
|
3949
|
+
const projectInstalled = Boolean(project && project.exists && project.descriptorOk && project.enabledInUproject);
|
|
3950
|
+
const effectiveScope = installScope === "engine" ? "engine" : installScope === "project" ? "project" : engineInstalled ? "engine" : project && !engineInfo.enginePluginsWritable ? "project" : "engine";
|
|
3951
|
+
const conflict = engineInfo.conflicts.length > 0;
|
|
3952
|
+
const legacyConflict = engineInfo.legacy.length > 0;
|
|
3953
|
+
const baseInstalled = effectiveScope === "engine" ? engineInstalled : projectInstalled;
|
|
3954
|
+
const installed = baseInstalled && !conflict && !legacyConflict;
|
|
3955
|
+
const status = conflict ? "conflict" : legacyConflict ? "legacy_conflict" : installed ? "ok" : "not_installed";
|
|
3956
|
+
const fix = status === "conflict" ? [
|
|
3957
|
+
"Close Unreal Editor.",
|
|
3958
|
+
"Delete/rename the conflicting FlockbayMCP plugin folder(s) listed under engine.conflicts.",
|
|
3959
|
+
"Ensure there is only ONE FlockbayMCP.uplugin under Engine/Plugins (common conflict: Engine/Plugins/Marketplace/FlockbayMCP).",
|
|
3960
|
+
"Reinstall the plugin and restart Unreal Editor so it rebuilds the plugin binaries."
|
|
3961
|
+
] : status === "legacy_conflict" ? [
|
|
3962
|
+
"Close Unreal Editor.",
|
|
3963
|
+
"Delete/rename the legacy UnrealMCP plugin folder(s) listed under engine.legacy.",
|
|
3964
|
+
"Reinstall the Flockbay MCP plugin and restart Unreal Editor."
|
|
3965
|
+
] : void 0;
|
|
3966
|
+
return {
|
|
3967
|
+
success: true,
|
|
3968
|
+
checkedAtMs,
|
|
3969
|
+
engineRoot,
|
|
3970
|
+
effectiveScope,
|
|
3971
|
+
installed,
|
|
3972
|
+
status,
|
|
3973
|
+
engine: engineInfo,
|
|
3974
|
+
project: project || void 0,
|
|
3975
|
+
fix
|
|
3976
|
+
};
|
|
3977
|
+
}
|
|
3978
|
+
|
|
3803
3979
|
async function openBrowser(url) {
|
|
3804
3980
|
try {
|
|
3805
3981
|
const forceOpen = process.env.FLOCKBAY_FORCE_BROWSER === "1" || process.env.FLOCKBAY_FORCE_BROWSER === "true";
|
|
@@ -4525,6 +4701,10 @@ class ApiMachineClient {
|
|
|
4525
4701
|
return { success: true, engineRoot: result.engineRoot, destDir: result.destDir };
|
|
4526
4702
|
}
|
|
4527
4703
|
);
|
|
4704
|
+
this.rpcHandlerManager.registerHandler(
|
|
4705
|
+
"unreal-mcp-plugin-disk-status",
|
|
4706
|
+
async (params) => getUnrealMcpPluginDiskStatus(params)
|
|
4707
|
+
);
|
|
4528
4708
|
}
|
|
4529
4709
|
socket;
|
|
4530
4710
|
keepAliveInterval = null;
|
|
@@ -44,7 +44,7 @@ function _interopNamespaceDefault(e) {
|
|
|
44
44
|
var z__namespace = /*#__PURE__*/_interopNamespaceDefault(z);
|
|
45
45
|
|
|
46
46
|
var name = "flockbay";
|
|
47
|
-
var version = "0.10.
|
|
47
|
+
var version = "0.10.44";
|
|
48
48
|
var description = "Flockbay CLI (local agent + daemon)";
|
|
49
49
|
var author = "Eduardo Orellana";
|
|
50
50
|
var license = "UNLICENSED";
|
|
@@ -774,7 +774,7 @@ class RpcHandlerManager {
|
|
|
774
774
|
}
|
|
775
775
|
}
|
|
776
776
|
|
|
777
|
-
const __dirname$1 = path$1.dirname(url.fileURLToPath((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('types-
|
|
777
|
+
const __dirname$1 = path$1.dirname(url.fileURLToPath((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('types-tRJ8NBIX.cjs', document.baseURI).href))));
|
|
778
778
|
function projectPath() {
|
|
779
779
|
const path = path$1.resolve(__dirname$1, "..");
|
|
780
780
|
return path;
|
|
@@ -3418,11 +3418,11 @@ function createBackoff(opts) {
|
|
|
3418
3418
|
}
|
|
3419
3419
|
let backoff = createBackoff();
|
|
3420
3420
|
|
|
3421
|
-
function looksLikeEngineRoot(engineRoot) {
|
|
3421
|
+
function looksLikeEngineRoot$1(engineRoot) {
|
|
3422
3422
|
if (!engineRoot) return false;
|
|
3423
3423
|
return fs.existsSync(path.join(engineRoot, "Engine")) && fs.existsSync(path.join(engineRoot, "Engine", "Plugins"));
|
|
3424
3424
|
}
|
|
3425
|
-
function findFilesNamedUnderDir(options) {
|
|
3425
|
+
function findFilesNamedUnderDir$1(options) {
|
|
3426
3426
|
const rootDir = options.rootDir;
|
|
3427
3427
|
const filename = options.filename;
|
|
3428
3428
|
const maxDepth = Math.max(0, Math.floor(options.maxDepth));
|
|
@@ -3450,7 +3450,7 @@ function findFilesNamedUnderDir(options) {
|
|
|
3450
3450
|
}
|
|
3451
3451
|
function installUnrealMcpPluginToEngine(engineRootRaw) {
|
|
3452
3452
|
const engineRoot = (engineRootRaw || "").trim();
|
|
3453
|
-
if (!looksLikeEngineRoot(engineRoot)) {
|
|
3453
|
+
if (!looksLikeEngineRoot$1(engineRoot)) {
|
|
3454
3454
|
return {
|
|
3455
3455
|
ok: false,
|
|
3456
3456
|
errorMessage: `Invalid engine root (expected an Unreal Engine install folder containing Engine/\u2026): ${engineRoot || "(empty)"}`
|
|
@@ -3464,7 +3464,7 @@ function installUnrealMcpPluginToEngine(engineRootRaw) {
|
|
|
3464
3464
|
const destUpluginPath = path.join(destDir, "FlockbayMCP.uplugin");
|
|
3465
3465
|
try {
|
|
3466
3466
|
const enginePluginsDir = path.join(engineRoot, "Engine", "Plugins");
|
|
3467
|
-
const candidates = findFilesNamedUnderDir({ rootDir: enginePluginsDir, filename: "FlockbayMCP.uplugin", maxDepth: 6 });
|
|
3467
|
+
const candidates = findFilesNamedUnderDir$1({ rootDir: enginePluginsDir, filename: "FlockbayMCP.uplugin", maxDepth: 6 });
|
|
3468
3468
|
const otherCopies = candidates.map((p) => path.resolve(p)).filter((p) => !p.startsWith(path.resolve(destDir) + path.sep));
|
|
3469
3469
|
if (otherCopies.length > 0) {
|
|
3470
3470
|
return {
|
|
@@ -3484,7 +3484,7 @@ Fix:
|
|
|
3484
3484
|
- Re-run the Flockbay MCP plugin install, then restart Unreal Editor so it rebuilds the plugin`
|
|
3485
3485
|
};
|
|
3486
3486
|
}
|
|
3487
|
-
const legacyCandidates = findFilesNamedUnderDir({ rootDir: enginePluginsDir, filename: "UnrealMCP.uplugin", maxDepth: 6 });
|
|
3487
|
+
const legacyCandidates = findFilesNamedUnderDir$1({ rootDir: enginePluginsDir, filename: "UnrealMCP.uplugin", maxDepth: 6 });
|
|
3488
3488
|
if (legacyCandidates.length > 0) {
|
|
3489
3489
|
return {
|
|
3490
3490
|
ok: false,
|
|
@@ -3563,7 +3563,7 @@ Error: ${message}`
|
|
|
3563
3563
|
}
|
|
3564
3564
|
}
|
|
3565
3565
|
|
|
3566
|
-
function readJsonIfPossible(filePath) {
|
|
3566
|
+
function readJsonIfPossible$1(filePath) {
|
|
3567
3567
|
try {
|
|
3568
3568
|
return JSON.parse(fs.readFileSync(filePath, "utf8"));
|
|
3569
3569
|
} catch {
|
|
@@ -3574,7 +3574,7 @@ function writeJsonPretty(filePath, value) {
|
|
|
3574
3574
|
fs.writeFileSync(filePath, JSON.stringify(value, null, 2) + "\n", "utf8");
|
|
3575
3575
|
}
|
|
3576
3576
|
function ensureProjectPluginEnabled(uprojectPath, pluginName) {
|
|
3577
|
-
const parsed = readJsonIfPossible(uprojectPath);
|
|
3577
|
+
const parsed = readJsonIfPossible$1(uprojectPath);
|
|
3578
3578
|
if (!parsed || typeof parsed !== "object") {
|
|
3579
3579
|
return { ok: false, error: `Invalid .uproject (expected JSON): ${uprojectPath}` };
|
|
3580
3580
|
}
|
|
@@ -3659,7 +3659,7 @@ Fix:
|
|
|
3659
3659
|
Expected: ${destUpluginPath}`
|
|
3660
3660
|
};
|
|
3661
3661
|
}
|
|
3662
|
-
const uplugin = readJsonIfPossible(destUpluginPath);
|
|
3662
|
+
const uplugin = readJsonIfPossible$1(destUpluginPath);
|
|
3663
3663
|
const friendlyName = typeof uplugin?.FriendlyName === "string" ? uplugin.FriendlyName : null;
|
|
3664
3664
|
const createdBy = typeof uplugin?.CreatedBy === "string" ? uplugin.CreatedBy : null;
|
|
3665
3665
|
if (friendlyName !== "Flockbay MCP" || createdBy !== "Respaced Inc.") {
|
|
@@ -3821,6 +3821,182 @@ Log: ${buildLogPath}`
|
|
|
3821
3821
|
return { ok: true, buildLogPath };
|
|
3822
3822
|
}
|
|
3823
3823
|
|
|
3824
|
+
function canWriteDir$1(dir) {
|
|
3825
|
+
const root = String(dir || "").trim();
|
|
3826
|
+
if (!root) return false;
|
|
3827
|
+
try {
|
|
3828
|
+
const tmp = path.join(root, `.__flockbay_write_test_${Date.now()}_${Math.random().toString(16).slice(2)}.tmp`);
|
|
3829
|
+
fs.writeFileSync(tmp, "ok", "utf8");
|
|
3830
|
+
fs.unlinkSync(tmp);
|
|
3831
|
+
return true;
|
|
3832
|
+
} catch {
|
|
3833
|
+
return false;
|
|
3834
|
+
}
|
|
3835
|
+
}
|
|
3836
|
+
function looksLikeEngineRoot(engineRoot) {
|
|
3837
|
+
if (!engineRoot) return false;
|
|
3838
|
+
return fs.existsSync(path.join(engineRoot, "Engine", "Plugins"));
|
|
3839
|
+
}
|
|
3840
|
+
function readJsonIfPossible(filePath) {
|
|
3841
|
+
try {
|
|
3842
|
+
return JSON.parse(fs.readFileSync(filePath, "utf8"));
|
|
3843
|
+
} catch {
|
|
3844
|
+
return null;
|
|
3845
|
+
}
|
|
3846
|
+
}
|
|
3847
|
+
function isPluginDescriptorOk(parsed) {
|
|
3848
|
+
const friendlyName = typeof parsed?.FriendlyName === "string" ? parsed.FriendlyName : null;
|
|
3849
|
+
const createdBy = typeof parsed?.CreatedBy === "string" ? parsed.CreatedBy : null;
|
|
3850
|
+
return friendlyName === "Flockbay MCP" && createdBy === "Respaced Inc.";
|
|
3851
|
+
}
|
|
3852
|
+
function isPathUnderDir(childPath, parentDir) {
|
|
3853
|
+
const child = path.resolve(childPath);
|
|
3854
|
+
const parent = path.resolve(parentDir);
|
|
3855
|
+
return child === parent || child.startsWith(parent + path.sep);
|
|
3856
|
+
}
|
|
3857
|
+
function findFilesNamedUnderDir(options) {
|
|
3858
|
+
const rootDir = options.rootDir;
|
|
3859
|
+
const filename = options.filename;
|
|
3860
|
+
const maxDepth = Math.max(0, Math.floor(options.maxDepth));
|
|
3861
|
+
const results = [];
|
|
3862
|
+
const visit = (dir, depth) => {
|
|
3863
|
+
if (depth > maxDepth) return;
|
|
3864
|
+
let entries = [];
|
|
3865
|
+
try {
|
|
3866
|
+
entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
3867
|
+
} catch {
|
|
3868
|
+
return;
|
|
3869
|
+
}
|
|
3870
|
+
for (const entry of entries) {
|
|
3871
|
+
if (entry.name === ".DS_Store") continue;
|
|
3872
|
+
const full = path.join(dir, entry.name);
|
|
3873
|
+
if (entry.isDirectory()) {
|
|
3874
|
+
visit(full, depth + 1);
|
|
3875
|
+
continue;
|
|
3876
|
+
}
|
|
3877
|
+
if (entry.isFile() && entry.name === filename) results.push(full);
|
|
3878
|
+
}
|
|
3879
|
+
};
|
|
3880
|
+
visit(rootDir, 0);
|
|
3881
|
+
return results;
|
|
3882
|
+
}
|
|
3883
|
+
function readUprojectPluginEnabled(uprojectPath, pluginName) {
|
|
3884
|
+
const parsed = readJsonIfPossible(uprojectPath);
|
|
3885
|
+
if (!parsed || typeof parsed !== "object") {
|
|
3886
|
+
return { ok: false, error: `Invalid .uproject (expected JSON): ${uprojectPath}` };
|
|
3887
|
+
}
|
|
3888
|
+
const plugins = Array.isArray(parsed.Plugins) ? parsed.Plugins : [];
|
|
3889
|
+
for (const p of plugins) {
|
|
3890
|
+
if (!p || typeof p !== "object") continue;
|
|
3891
|
+
if (p.Name === pluginName) return { ok: true, enabled: p.Enabled === true };
|
|
3892
|
+
}
|
|
3893
|
+
return { ok: true, enabled: false };
|
|
3894
|
+
}
|
|
3895
|
+
function getUnrealMcpPluginDiskStatus(params) {
|
|
3896
|
+
const checkedAtMs = Date.now();
|
|
3897
|
+
const engineRoot = String(params?.engineRoot || "").trim();
|
|
3898
|
+
const installScope = String(params?.installScope || "auto");
|
|
3899
|
+
const projectUprojectPathRaw = typeof params?.projectUprojectPath === "string" ? params.projectUprojectPath.trim() : "";
|
|
3900
|
+
if (!engineRoot) return { success: false, error: "Missing engineRoot." };
|
|
3901
|
+
if (!looksLikeEngineRoot(engineRoot)) {
|
|
3902
|
+
return { success: false, error: `Invalid engine root (expected an Unreal Engine install folder containing Engine/Plugins): ${engineRoot}` };
|
|
3903
|
+
}
|
|
3904
|
+
const enginePluginsDir = path.join(engineRoot, "Engine", "Plugins");
|
|
3905
|
+
const enginePluginDir = path.join(enginePluginsDir, "FlockbayMCP");
|
|
3906
|
+
const engineUpluginPath = path.join(enginePluginDir, "FlockbayMCP.uplugin");
|
|
3907
|
+
const engineDescriptor = fs.existsSync(engineUpluginPath) ? readJsonIfPossible(engineUpluginPath) : null;
|
|
3908
|
+
const engineInfo = {
|
|
3909
|
+
pluginDir: enginePluginDir,
|
|
3910
|
+
upluginPath: engineUpluginPath,
|
|
3911
|
+
exists: fs.existsSync(engineUpluginPath),
|
|
3912
|
+
descriptorOk: engineDescriptor ? isPluginDescriptorOk(engineDescriptor) : false,
|
|
3913
|
+
hasBinaries: fs.existsSync(path.join(enginePluginDir, "Binaries")),
|
|
3914
|
+
enginePluginsWritable: canWriteDir$1(enginePluginsDir),
|
|
3915
|
+
conflicts: [],
|
|
3916
|
+
legacy: []
|
|
3917
|
+
};
|
|
3918
|
+
const conflictSet = /* @__PURE__ */ new Set();
|
|
3919
|
+
const legacySet = /* @__PURE__ */ new Set();
|
|
3920
|
+
const fastCandidates = [
|
|
3921
|
+
path.join(enginePluginsDir, "Marketplace", "FlockbayMCP", "FlockbayMCP.uplugin"),
|
|
3922
|
+
path.join(enginePluginsDir, "Marketplace", "UnrealMCP", "UnrealMCP.uplugin"),
|
|
3923
|
+
path.join(enginePluginsDir, "UnrealMCP", "UnrealMCP.uplugin")
|
|
3924
|
+
];
|
|
3925
|
+
for (const p of fastCandidates) {
|
|
3926
|
+
if (fs.existsSync(p)) {
|
|
3927
|
+
if (p.toLowerCase().endsWith("unrealmcp.uplugin")) legacySet.add(path.resolve(p));
|
|
3928
|
+
if (p.toLowerCase().endsWith("flockbaymcp.uplugin")) conflictSet.add(path.resolve(p));
|
|
3929
|
+
}
|
|
3930
|
+
}
|
|
3931
|
+
for (const p of findFilesNamedUnderDir({ rootDir: enginePluginsDir, filename: "FlockbayMCP.uplugin", maxDepth: 6 })) {
|
|
3932
|
+
const resolved = path.resolve(p);
|
|
3933
|
+
if (isPathUnderDir(resolved, enginePluginDir)) continue;
|
|
3934
|
+
conflictSet.add(resolved);
|
|
3935
|
+
}
|
|
3936
|
+
for (const p of findFilesNamedUnderDir({ rootDir: enginePluginsDir, filename: "UnrealMCP.uplugin", maxDepth: 6 })) {
|
|
3937
|
+
legacySet.add(path.resolve(p));
|
|
3938
|
+
}
|
|
3939
|
+
engineInfo.conflicts = Array.from(conflictSet).sort();
|
|
3940
|
+
engineInfo.legacy = Array.from(legacySet).sort();
|
|
3941
|
+
const project = (() => {
|
|
3942
|
+
if (!projectUprojectPathRaw) return null;
|
|
3943
|
+
const uprojectPath = path.resolve(projectUprojectPathRaw);
|
|
3944
|
+
if (!uprojectPath.toLowerCase().endsWith(".uproject")) {
|
|
3945
|
+
return { error: `Invalid .uproject path (expected *.uproject): ${uprojectPath}` };
|
|
3946
|
+
}
|
|
3947
|
+
if (!fs.existsSync(uprojectPath)) {
|
|
3948
|
+
return { error: `Missing .uproject: ${uprojectPath}` };
|
|
3949
|
+
}
|
|
3950
|
+
const projectRoot = path.dirname(uprojectPath);
|
|
3951
|
+
const pluginDir = path.join(projectRoot, "Plugins", "FlockbayMCP");
|
|
3952
|
+
const upluginPath = path.join(pluginDir, "FlockbayMCP.uplugin");
|
|
3953
|
+
const descriptor = fs.existsSync(upluginPath) ? readJsonIfPossible(upluginPath) : null;
|
|
3954
|
+
const enabled = readUprojectPluginEnabled(uprojectPath, "FlockbayMCP");
|
|
3955
|
+
if (!enabled.ok) return { error: enabled.error };
|
|
3956
|
+
return {
|
|
3957
|
+
uprojectPath,
|
|
3958
|
+
pluginDir,
|
|
3959
|
+
upluginPath,
|
|
3960
|
+
exists: fs.existsSync(upluginPath),
|
|
3961
|
+
descriptorOk: descriptor ? isPluginDescriptorOk(descriptor) : false,
|
|
3962
|
+
enabledInUproject: enabled.enabled
|
|
3963
|
+
};
|
|
3964
|
+
})();
|
|
3965
|
+
if (project && "error" in project) return { success: false, error: project.error };
|
|
3966
|
+
if (installScope === "project" && !project) {
|
|
3967
|
+
return { success: false, error: "Missing projectUprojectPath (required for installScope=project)." };
|
|
3968
|
+
}
|
|
3969
|
+
const engineInstalled = engineInfo.exists && engineInfo.descriptorOk && engineInfo.hasBinaries;
|
|
3970
|
+
const projectInstalled = Boolean(project && project.exists && project.descriptorOk && project.enabledInUproject);
|
|
3971
|
+
const effectiveScope = installScope === "engine" ? "engine" : installScope === "project" ? "project" : engineInstalled ? "engine" : project && !engineInfo.enginePluginsWritable ? "project" : "engine";
|
|
3972
|
+
const conflict = engineInfo.conflicts.length > 0;
|
|
3973
|
+
const legacyConflict = engineInfo.legacy.length > 0;
|
|
3974
|
+
const baseInstalled = effectiveScope === "engine" ? engineInstalled : projectInstalled;
|
|
3975
|
+
const installed = baseInstalled && !conflict && !legacyConflict;
|
|
3976
|
+
const status = conflict ? "conflict" : legacyConflict ? "legacy_conflict" : installed ? "ok" : "not_installed";
|
|
3977
|
+
const fix = status === "conflict" ? [
|
|
3978
|
+
"Close Unreal Editor.",
|
|
3979
|
+
"Delete/rename the conflicting FlockbayMCP plugin folder(s) listed under engine.conflicts.",
|
|
3980
|
+
"Ensure there is only ONE FlockbayMCP.uplugin under Engine/Plugins (common conflict: Engine/Plugins/Marketplace/FlockbayMCP).",
|
|
3981
|
+
"Reinstall the plugin and restart Unreal Editor so it rebuilds the plugin binaries."
|
|
3982
|
+
] : status === "legacy_conflict" ? [
|
|
3983
|
+
"Close Unreal Editor.",
|
|
3984
|
+
"Delete/rename the legacy UnrealMCP plugin folder(s) listed under engine.legacy.",
|
|
3985
|
+
"Reinstall the Flockbay MCP plugin and restart Unreal Editor."
|
|
3986
|
+
] : void 0;
|
|
3987
|
+
return {
|
|
3988
|
+
success: true,
|
|
3989
|
+
checkedAtMs,
|
|
3990
|
+
engineRoot,
|
|
3991
|
+
effectiveScope,
|
|
3992
|
+
installed,
|
|
3993
|
+
status,
|
|
3994
|
+
engine: engineInfo,
|
|
3995
|
+
project: project || void 0,
|
|
3996
|
+
fix
|
|
3997
|
+
};
|
|
3998
|
+
}
|
|
3999
|
+
|
|
3824
4000
|
async function openBrowser(url) {
|
|
3825
4001
|
try {
|
|
3826
4002
|
const forceOpen = process.env.FLOCKBAY_FORCE_BROWSER === "1" || process.env.FLOCKBAY_FORCE_BROWSER === "true";
|
|
@@ -4546,6 +4722,10 @@ class ApiMachineClient {
|
|
|
4546
4722
|
return { success: true, engineRoot: result.engineRoot, destDir: result.destDir };
|
|
4547
4723
|
}
|
|
4548
4724
|
);
|
|
4725
|
+
this.rpcHandlerManager.registerHandler(
|
|
4726
|
+
"unreal-mcp-plugin-disk-status",
|
|
4727
|
+
async (params) => getUnrealMcpPluginDiskStatus(params)
|
|
4728
|
+
);
|
|
4549
4729
|
}
|
|
4550
4730
|
socket;
|
|
4551
4731
|
keepAliveInterval = null;
|