flockbay 0.10.42 → 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-B6WkRhlp.mjs → index-BfBX93aY.mjs} +64 -28
- package/dist/{index-F8r81l86.cjs → index-CVBvClyV.cjs} +64 -28
- 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-T0MOGk0T.cjs → migratePlugin-BL02mitg.cjs} +1 -1
- package/dist/{migratePlugin-CCepAUqm.mjs → migratePlugin-DAAX2TDX.mjs} +1 -1
- package/dist/{runCodex-7GeFJuM_.mjs → runCodex-C_dwGw9p.mjs} +2 -2
- package/dist/{runCodex-Bx4E0ukk.cjs → runCodex-DcQmhprg.cjs} +2 -2
- package/dist/{runGemini-xvROo10g.cjs → runGemini-CJF0id5I.cjs} +2 -2
- package/dist/{runGemini-9LGJaWVk.mjs → runGemini-CWiIoJag.mjs} +2 -2
- package/dist/{types-D1UKSrkg.mjs → types-D8EqTVgB.mjs} +191 -10
- package/dist/{types-wdJcHT5x.cjs → types-tRJ8NBIX.cjs} +192 -11
- 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,17 +5261,41 @@ 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();
|
|
5295
|
+
const windowsHide = typeof options?.windowsHide === "boolean" ? Boolean(options.windowsHide) : process$1.platform === "win32";
|
|
5273
5296
|
const spawnOptions = {
|
|
5274
5297
|
...options,
|
|
5298
|
+
windowsHide,
|
|
5275
5299
|
...useTsx ? { cwd: projectRoot } : {},
|
|
5276
5300
|
env: {
|
|
5277
5301
|
...process$1.env,
|
|
@@ -5681,12 +5705,14 @@ async function enforceCliVersionPolicy(opts) {
|
|
|
5681
5705
|
const policy = await fetchCliVersionPolicy({ serverUrl: opts.serverUrl, timeoutMs: opts.timeoutMs });
|
|
5682
5706
|
const evaluation = evaluateCliVersion({ currentVersion, policy });
|
|
5683
5707
|
if (evaluation.status === "update_required") {
|
|
5684
|
-
|
|
5685
|
-
|
|
5686
|
-
|
|
5687
|
-
|
|
5688
|
-
|
|
5689
|
-
|
|
5708
|
+
try {
|
|
5709
|
+
opts.onUpdateRequired?.({
|
|
5710
|
+
minimumSupported: evaluation.minimumSupported,
|
|
5711
|
+
updateCommand: evaluation.updateCommand,
|
|
5712
|
+
message: evaluation.message
|
|
5713
|
+
});
|
|
5714
|
+
} catch {
|
|
5715
|
+
}
|
|
5690
5716
|
}
|
|
5691
5717
|
if (evaluation.status === "update_available") {
|
|
5692
5718
|
try {
|
|
@@ -5787,6 +5813,14 @@ async function startDaemon() {
|
|
|
5787
5813
|
serverUrl: configuration.serverUrl,
|
|
5788
5814
|
currentVersion: packageJson.version,
|
|
5789
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
|
+
},
|
|
5790
5824
|
onUpdateAvailable: ({ latest, updateCommand, message }) => {
|
|
5791
5825
|
const note = message ? `
|
|
5792
5826
|
${message}` : "";
|
|
@@ -5796,12 +5830,7 @@ Update: ${updateCommand}`);
|
|
|
5796
5830
|
});
|
|
5797
5831
|
} catch (err) {
|
|
5798
5832
|
const msg = err instanceof Error ? err.message : String(err);
|
|
5799
|
-
|
|
5800
|
-
console.error(msg);
|
|
5801
|
-
process.exit(1);
|
|
5802
|
-
} else {
|
|
5803
|
-
logger.debug("[DAEMON RUN] CLI version policy check failed (non-fatal):", msg);
|
|
5804
|
-
}
|
|
5833
|
+
logger.debug("[DAEMON RUN] CLI version policy check failed (non-fatal):", msg);
|
|
5805
5834
|
}
|
|
5806
5835
|
logger.debug("[DAEMON RUN] Auth and machine setup complete");
|
|
5807
5836
|
const shouldStartUnrealMcp = String(process.env.FLOCKBAY_UNREAL_MCP_ENABLED || "").trim() === "1";
|
|
@@ -6577,10 +6606,18 @@ Log: ${logPath || `not found (check ${configuration.logsDir})`}` + formatLogExce
|
|
|
6577
6606
|
cliPolicyCheckInFlight = true;
|
|
6578
6607
|
lastCliPolicyCheckAtMs = Date.now();
|
|
6579
6608
|
try {
|
|
6580
|
-
await enforceCliVersionPolicy({
|
|
6609
|
+
const { evaluation } = await enforceCliVersionPolicy({
|
|
6581
6610
|
serverUrl: configuration.serverUrl,
|
|
6582
6611
|
currentVersion: packageJson.version,
|
|
6583
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
|
+
},
|
|
6584
6621
|
onUpdateAvailable: ({ latest, updateCommand, message }) => {
|
|
6585
6622
|
const note = message ? `
|
|
6586
6623
|
${message}` : "";
|
|
@@ -6590,13 +6627,10 @@ Update: ${updateCommand}`
|
|
|
6590
6627
|
);
|
|
6591
6628
|
}
|
|
6592
6629
|
});
|
|
6630
|
+
if (evaluation.status === "update_required") {
|
|
6631
|
+
}
|
|
6593
6632
|
} catch (err) {
|
|
6594
6633
|
const msg = err instanceof Error ? err.message : String(err);
|
|
6595
|
-
if (/^CLI update required\b/i.test(msg)) {
|
|
6596
|
-
logger.debug("[DAEMON RUN] CLI update required; shutting down daemon:", msg);
|
|
6597
|
-
requestShutdown("exception", msg);
|
|
6598
|
-
return;
|
|
6599
|
-
}
|
|
6600
6634
|
logger.debug("[DAEMON RUN] CLI version policy check failed (non-fatal):", msg);
|
|
6601
6635
|
} finally {
|
|
6602
6636
|
cliPolicyCheckInFlight = false;
|
|
@@ -7013,7 +7047,7 @@ ${scriptCandidates.map((p) => `- ${p}`).join("\n")}
|
|
|
7013
7047
|
logStream.write(`args: ${JSON.stringify(buildArgs)}
|
|
7014
7048
|
|
|
7015
7049
|
`);
|
|
7016
|
-
const child = osPlatform === "win32" ? spawn("cmd.exe", ["/c", script, ...buildArgs], { stdio: ["ignore", "pipe", "pipe"] }) : spawn(script, buildArgs, { stdio: ["ignore", "pipe", "pipe"] });
|
|
7050
|
+
const child = osPlatform === "win32" ? spawn("cmd.exe", ["/c", script, ...buildArgs], { stdio: ["ignore", "pipe", "pipe"], windowsHide: true }) : spawn(script, buildArgs, { stdio: ["ignore", "pipe", "pipe"] });
|
|
7017
7051
|
let combinedTail = "";
|
|
7018
7052
|
const appendTail = (chunk) => {
|
|
7019
7053
|
combinedTail += chunk.toString("utf8");
|
|
@@ -14880,7 +14914,8 @@ async function startDaemonDetachedOrExit(opts) {
|
|
|
14880
14914
|
console.log(chalk.gray(`Daemon: ${daemon?.pid ? `pid=${daemon.pid} port=${daemon.httpPort}` : "not running"}`));
|
|
14881
14915
|
console.log("");
|
|
14882
14916
|
if (opts?.openWebapp) openUrlBestEffort(configuration.webappUrl);
|
|
14883
|
-
process.
|
|
14917
|
+
process.exitCode = 0;
|
|
14918
|
+
return;
|
|
14884
14919
|
}
|
|
14885
14920
|
const authMismatch = lastUpsertStatus === 401 || /unauthorized/i.test(lastConnectError);
|
|
14886
14921
|
if (authMismatch && !opts?.reauthAttempted) {
|
|
@@ -14951,7 +14986,8 @@ async function startDaemonDetachedOrExit(opts) {
|
|
|
14951
14986
|
console.log(chalk.gray(`Daemon: ${daemon?.pid ? `pid=${daemon.pid} port=${daemon.httpPort}` : "not running"}`));
|
|
14952
14987
|
console.log("");
|
|
14953
14988
|
if (opts?.openWebapp) openUrlBestEffort(configuration.webappUrl);
|
|
14954
|
-
process.
|
|
14989
|
+
process.exitCode = 0;
|
|
14990
|
+
return;
|
|
14955
14991
|
} else {
|
|
14956
14992
|
const latest = await getLatestDaemonLog();
|
|
14957
14993
|
if (latest?.path) console.error(`Latest daemon log: ${latest.path}`);
|
|
@@ -15081,7 +15117,7 @@ async function authAndSetupMachineIfNeeded() {
|
|
|
15081
15117
|
process.exit(1);
|
|
15082
15118
|
}
|
|
15083
15119
|
try {
|
|
15084
|
-
const { migrateUnrealMcpToFlockbayMcp } = await import('./migratePlugin-
|
|
15120
|
+
const { migrateUnrealMcpToFlockbayMcp } = await import('./migratePlugin-DAAX2TDX.mjs');
|
|
15085
15121
|
const result = migrateUnrealMcpToFlockbayMcp({
|
|
15086
15122
|
engineRoot,
|
|
15087
15123
|
projectUprojectPath: project || void 0,
|
|
@@ -15220,7 +15256,7 @@ ${engineRoot}`, {
|
|
|
15220
15256
|
} else if (subcommand === "codex") {
|
|
15221
15257
|
try {
|
|
15222
15258
|
await chdirToNearestUprojectRootIfPresent();
|
|
15223
|
-
const { runCodex } = await import('./runCodex-
|
|
15259
|
+
const { runCodex } = await import('./runCodex-C_dwGw9p.mjs');
|
|
15224
15260
|
let startedBy = void 0;
|
|
15225
15261
|
let sessionId = void 0;
|
|
15226
15262
|
for (let i = 1; i < args.length; i++) {
|
|
@@ -15322,7 +15358,7 @@ ${engineRoot}`, {
|
|
|
15322
15358
|
}
|
|
15323
15359
|
try {
|
|
15324
15360
|
await chdirToNearestUprojectRootIfPresent();
|
|
15325
|
-
const { runGemini } = await import('./runGemini-
|
|
15361
|
+
const { runGemini } = await import('./runGemini-CWiIoJag.mjs');
|
|
15326
15362
|
let startedBy = void 0;
|
|
15327
15363
|
let sessionId = void 0;
|
|
15328
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,17 +5283,41 @@ 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();
|
|
5317
|
+
const windowsHide = typeof options?.windowsHide === "boolean" ? Boolean(options.windowsHide) : process$1.platform === "win32";
|
|
5295
5318
|
const spawnOptions = {
|
|
5296
5319
|
...options,
|
|
5320
|
+
windowsHide,
|
|
5297
5321
|
...useTsx ? { cwd: projectRoot } : {},
|
|
5298
5322
|
env: {
|
|
5299
5323
|
...process$1.env,
|
|
@@ -5703,12 +5727,14 @@ async function enforceCliVersionPolicy(opts) {
|
|
|
5703
5727
|
const policy = await fetchCliVersionPolicy({ serverUrl: opts.serverUrl, timeoutMs: opts.timeoutMs });
|
|
5704
5728
|
const evaluation = evaluateCliVersion({ currentVersion, policy });
|
|
5705
5729
|
if (evaluation.status === "update_required") {
|
|
5706
|
-
|
|
5707
|
-
|
|
5708
|
-
|
|
5709
|
-
|
|
5710
|
-
|
|
5711
|
-
|
|
5730
|
+
try {
|
|
5731
|
+
opts.onUpdateRequired?.({
|
|
5732
|
+
minimumSupported: evaluation.minimumSupported,
|
|
5733
|
+
updateCommand: evaluation.updateCommand,
|
|
5734
|
+
message: evaluation.message
|
|
5735
|
+
});
|
|
5736
|
+
} catch {
|
|
5737
|
+
}
|
|
5712
5738
|
}
|
|
5713
5739
|
if (evaluation.status === "update_available") {
|
|
5714
5740
|
try {
|
|
@@ -5809,6 +5835,14 @@ async function startDaemon() {
|
|
|
5809
5835
|
serverUrl: types.configuration.serverUrl,
|
|
5810
5836
|
currentVersion: types.packageJson.version,
|
|
5811
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
|
+
},
|
|
5812
5846
|
onUpdateAvailable: ({ latest, updateCommand, message }) => {
|
|
5813
5847
|
const note = message ? `
|
|
5814
5848
|
${message}` : "";
|
|
@@ -5818,12 +5852,7 @@ Update: ${updateCommand}`);
|
|
|
5818
5852
|
});
|
|
5819
5853
|
} catch (err) {
|
|
5820
5854
|
const msg = err instanceof Error ? err.message : String(err);
|
|
5821
|
-
|
|
5822
|
-
console.error(msg);
|
|
5823
|
-
process.exit(1);
|
|
5824
|
-
} else {
|
|
5825
|
-
types.logger.debug("[DAEMON RUN] CLI version policy check failed (non-fatal):", msg);
|
|
5826
|
-
}
|
|
5855
|
+
types.logger.debug("[DAEMON RUN] CLI version policy check failed (non-fatal):", msg);
|
|
5827
5856
|
}
|
|
5828
5857
|
types.logger.debug("[DAEMON RUN] Auth and machine setup complete");
|
|
5829
5858
|
const shouldStartUnrealMcp = String(process.env.FLOCKBAY_UNREAL_MCP_ENABLED || "").trim() === "1";
|
|
@@ -6599,10 +6628,18 @@ Log: ${logPath || `not found (check ${types.configuration.logsDir})`}` + formatL
|
|
|
6599
6628
|
cliPolicyCheckInFlight = true;
|
|
6600
6629
|
lastCliPolicyCheckAtMs = Date.now();
|
|
6601
6630
|
try {
|
|
6602
|
-
await enforceCliVersionPolicy({
|
|
6631
|
+
const { evaluation } = await enforceCliVersionPolicy({
|
|
6603
6632
|
serverUrl: types.configuration.serverUrl,
|
|
6604
6633
|
currentVersion: types.packageJson.version,
|
|
6605
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
|
+
},
|
|
6606
6643
|
onUpdateAvailable: ({ latest, updateCommand, message }) => {
|
|
6607
6644
|
const note = message ? `
|
|
6608
6645
|
${message}` : "";
|
|
@@ -6612,13 +6649,10 @@ Update: ${updateCommand}`
|
|
|
6612
6649
|
);
|
|
6613
6650
|
}
|
|
6614
6651
|
});
|
|
6652
|
+
if (evaluation.status === "update_required") {
|
|
6653
|
+
}
|
|
6615
6654
|
} catch (err) {
|
|
6616
6655
|
const msg = err instanceof Error ? err.message : String(err);
|
|
6617
|
-
if (/^CLI update required\b/i.test(msg)) {
|
|
6618
|
-
types.logger.debug("[DAEMON RUN] CLI update required; shutting down daemon:", msg);
|
|
6619
|
-
requestShutdown("exception", msg);
|
|
6620
|
-
return;
|
|
6621
|
-
}
|
|
6622
6656
|
types.logger.debug("[DAEMON RUN] CLI version policy check failed (non-fatal):", msg);
|
|
6623
6657
|
} finally {
|
|
6624
6658
|
cliPolicyCheckInFlight = false;
|
|
@@ -7035,7 +7069,7 @@ ${scriptCandidates.map((p) => `- ${p}`).join("\n")}
|
|
|
7035
7069
|
logStream.write(`args: ${JSON.stringify(buildArgs)}
|
|
7036
7070
|
|
|
7037
7071
|
`);
|
|
7038
|
-
const child = osPlatform === "win32" ? node_child_process.spawn("cmd.exe", ["/c", script, ...buildArgs], { stdio: ["ignore", "pipe", "pipe"] }) : node_child_process.spawn(script, buildArgs, { stdio: ["ignore", "pipe", "pipe"] });
|
|
7072
|
+
const child = osPlatform === "win32" ? node_child_process.spawn("cmd.exe", ["/c", script, ...buildArgs], { stdio: ["ignore", "pipe", "pipe"], windowsHide: true }) : node_child_process.spawn(script, buildArgs, { stdio: ["ignore", "pipe", "pipe"] });
|
|
7039
7073
|
let combinedTail = "";
|
|
7040
7074
|
const appendTail = (chunk) => {
|
|
7041
7075
|
combinedTail += chunk.toString("utf8");
|
|
@@ -14902,7 +14936,8 @@ async function startDaemonDetachedOrExit(opts) {
|
|
|
14902
14936
|
console.log(chalk.gray(`Daemon: ${daemon?.pid ? `pid=${daemon.pid} port=${daemon.httpPort}` : "not running"}`));
|
|
14903
14937
|
console.log("");
|
|
14904
14938
|
if (opts?.openWebapp) openUrlBestEffort(types.configuration.webappUrl);
|
|
14905
|
-
process.
|
|
14939
|
+
process.exitCode = 0;
|
|
14940
|
+
return;
|
|
14906
14941
|
}
|
|
14907
14942
|
const authMismatch = lastUpsertStatus === 401 || /unauthorized/i.test(lastConnectError);
|
|
14908
14943
|
if (authMismatch && !opts?.reauthAttempted) {
|
|
@@ -14973,7 +15008,8 @@ async function startDaemonDetachedOrExit(opts) {
|
|
|
14973
15008
|
console.log(chalk.gray(`Daemon: ${daemon?.pid ? `pid=${daemon.pid} port=${daemon.httpPort}` : "not running"}`));
|
|
14974
15009
|
console.log("");
|
|
14975
15010
|
if (opts?.openWebapp) openUrlBestEffort(types.configuration.webappUrl);
|
|
14976
|
-
process.
|
|
15011
|
+
process.exitCode = 0;
|
|
15012
|
+
return;
|
|
14977
15013
|
} else {
|
|
14978
15014
|
const latest = await types.getLatestDaemonLog();
|
|
14979
15015
|
if (latest?.path) console.error(`Latest daemon log: ${latest.path}`);
|
|
@@ -15103,7 +15139,7 @@ async function authAndSetupMachineIfNeeded() {
|
|
|
15103
15139
|
process.exit(1);
|
|
15104
15140
|
}
|
|
15105
15141
|
try {
|
|
15106
|
-
const { migrateUnrealMcpToFlockbayMcp } = await Promise.resolve().then(function () { return require('./migratePlugin-
|
|
15142
|
+
const { migrateUnrealMcpToFlockbayMcp } = await Promise.resolve().then(function () { return require('./migratePlugin-BL02mitg.cjs'); });
|
|
15107
15143
|
const result = migrateUnrealMcpToFlockbayMcp({
|
|
15108
15144
|
engineRoot,
|
|
15109
15145
|
projectUprojectPath: project || void 0,
|
|
@@ -15242,7 +15278,7 @@ ${engineRoot}`, {
|
|
|
15242
15278
|
} else if (subcommand === "codex") {
|
|
15243
15279
|
try {
|
|
15244
15280
|
await chdirToNearestUprojectRootIfPresent();
|
|
15245
|
-
const { runCodex } = await Promise.resolve().then(function () { return require('./runCodex-
|
|
15281
|
+
const { runCodex } = await Promise.resolve().then(function () { return require('./runCodex-DcQmhprg.cjs'); });
|
|
15246
15282
|
let startedBy = void 0;
|
|
15247
15283
|
let sessionId = void 0;
|
|
15248
15284
|
for (let i = 1; i < args.length; i++) {
|
|
@@ -15344,7 +15380,7 @@ ${engineRoot}`, {
|
|
|
15344
15380
|
}
|
|
15345
15381
|
try {
|
|
15346
15382
|
await chdirToNearestUprojectRootIfPresent();
|
|
15347
|
-
const { runGemini } = await Promise.resolve().then(function () { return require('./runGemini-
|
|
15383
|
+
const { runGemini } = await Promise.resolve().then(function () { return require('./runGemini-CJF0id5I.cjs'); });
|
|
15348
15384
|
let startedBy = void 0;
|
|
15349
15385
|
let sessionId = void 0;
|
|
15350
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.") {
|
|
@@ -3741,7 +3741,8 @@ async function buildAndInstallUnrealMcpPlugin(options) {
|
|
|
3741
3741
|
const cmdLine = `""${uat}" ${args.map(quoteCmdArg).join(" ")}`;
|
|
3742
3742
|
return spawn$1("cmd.exe", ["/s", "/c", cmdLine], {
|
|
3743
3743
|
stdio: ["ignore", "pipe", "pipe"],
|
|
3744
|
-
windowsVerbatimArguments: true
|
|
3744
|
+
windowsVerbatimArguments: true,
|
|
3745
|
+
windowsHide: true
|
|
3745
3746
|
});
|
|
3746
3747
|
})() : spawn$1(uat, args, { stdio: ["ignore", "pipe", "pipe"] });
|
|
3747
3748
|
child.stdout?.on("data", (chunk) => logStream.write(chunk));
|
|
@@ -3799,6 +3800,182 @@ Log: ${buildLogPath}`
|
|
|
3799
3800
|
return { ok: true, buildLogPath };
|
|
3800
3801
|
}
|
|
3801
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
|
+
|
|
3802
3979
|
async function openBrowser(url) {
|
|
3803
3980
|
try {
|
|
3804
3981
|
const forceOpen = process.env.FLOCKBAY_FORCE_BROWSER === "1" || process.env.FLOCKBAY_FORCE_BROWSER === "true";
|
|
@@ -4524,6 +4701,10 @@ class ApiMachineClient {
|
|
|
4524
4701
|
return { success: true, engineRoot: result.engineRoot, destDir: result.destDir };
|
|
4525
4702
|
}
|
|
4526
4703
|
);
|
|
4704
|
+
this.rpcHandlerManager.registerHandler(
|
|
4705
|
+
"unreal-mcp-plugin-disk-status",
|
|
4706
|
+
async (params) => getUnrealMcpPluginDiskStatus(params)
|
|
4707
|
+
);
|
|
4527
4708
|
}
|
|
4528
4709
|
socket;
|
|
4529
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.") {
|
|
@@ -3762,7 +3762,8 @@ async function buildAndInstallUnrealMcpPlugin(options) {
|
|
|
3762
3762
|
const cmdLine = `""${uat}" ${args.map(quoteCmdArg).join(" ")}`;
|
|
3763
3763
|
return node_child_process.spawn("cmd.exe", ["/s", "/c", cmdLine], {
|
|
3764
3764
|
stdio: ["ignore", "pipe", "pipe"],
|
|
3765
|
-
windowsVerbatimArguments: true
|
|
3765
|
+
windowsVerbatimArguments: true,
|
|
3766
|
+
windowsHide: true
|
|
3766
3767
|
});
|
|
3767
3768
|
})() : node_child_process.spawn(uat, args, { stdio: ["ignore", "pipe", "pipe"] });
|
|
3768
3769
|
child.stdout?.on("data", (chunk) => logStream.write(chunk));
|
|
@@ -3820,6 +3821,182 @@ Log: ${buildLogPath}`
|
|
|
3820
3821
|
return { ok: true, buildLogPath };
|
|
3821
3822
|
}
|
|
3822
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
|
+
|
|
3823
4000
|
async function openBrowser(url) {
|
|
3824
4001
|
try {
|
|
3825
4002
|
const forceOpen = process.env.FLOCKBAY_FORCE_BROWSER === "1" || process.env.FLOCKBAY_FORCE_BROWSER === "true";
|
|
@@ -4545,6 +4722,10 @@ class ApiMachineClient {
|
|
|
4545
4722
|
return { success: true, engineRoot: result.engineRoot, destDir: result.destDir };
|
|
4546
4723
|
}
|
|
4547
4724
|
);
|
|
4725
|
+
this.rpcHandlerManager.registerHandler(
|
|
4726
|
+
"unreal-mcp-plugin-disk-status",
|
|
4727
|
+
async (params) => getUnrealMcpPluginDiskStatus(params)
|
|
4728
|
+
);
|
|
4548
4729
|
}
|
|
4549
4730
|
socket;
|
|
4550
4731
|
keepAliveInterval = null;
|