flockbay 0.10.40 → 0.10.42
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{index-COD6HpzC.mjs → index-B6WkRhlp.mjs} +104 -563
- package/dist/{index-hc8sYVfl.cjs → index-F8r81l86.cjs} +106 -565
- package/dist/index.cjs +5 -6
- package/dist/index.mjs +5 -6
- package/dist/lib.cjs +3 -1
- package/dist/lib.d.cts +3 -0
- package/dist/lib.d.mts +3 -0
- package/dist/lib.mjs +3 -1
- package/dist/{migratePlugin-Beo3Vgvz.mjs → migratePlugin-CCepAUqm.mjs} +3 -1
- package/dist/{migratePlugin-DNHywpj6.cjs → migratePlugin-T0MOGk0T.cjs} +3 -1
- package/dist/{runCodex-BAbRZt7Y.mjs → runCodex-7GeFJuM_.mjs} +5 -6
- package/dist/{runCodex-B3Qjwkr6.cjs → runCodex-Bx4E0ukk.cjs} +5 -6
- package/dist/{runGemini-D9WGwILY.mjs → runGemini-9LGJaWVk.mjs} +5 -6
- package/dist/{runGemini-BED5hBNz.cjs → runGemini-xvROo10g.cjs} +5 -6
- package/dist/{types-4acLcOdW.mjs → types-D1UKSrkg.mjs} +966 -33
- package/dist/{types-2Bs_CNcy.cjs → types-wdJcHT5x.cjs} +970 -31
- package/package.json +1 -1
- package/scripts/unpack-tools.cjs +1 -2
|
@@ -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-wdJcHT5x.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');
|
|
@@ -15,27 +15,26 @@ var ink = require('ink');
|
|
|
15
15
|
var React = require('react');
|
|
16
16
|
var node_url = require('node:url');
|
|
17
17
|
var axios = require('axios');
|
|
18
|
-
var node_events = require('node:events');
|
|
19
18
|
require('socket.io-client');
|
|
20
19
|
var child_process = require('child_process');
|
|
21
20
|
var crypto = require('crypto');
|
|
22
21
|
var path$1 = require('path');
|
|
23
22
|
var os$1 = require('os');
|
|
24
23
|
require('node:net');
|
|
24
|
+
require('http');
|
|
25
|
+
require('open');
|
|
25
26
|
var fs$3 = require('fs');
|
|
26
27
|
var psList = require('ps-list');
|
|
27
28
|
var spawn = require('cross-spawn');
|
|
28
29
|
var tmp = require('tmp');
|
|
29
|
-
var open = require('open');
|
|
30
30
|
var fastify = require('fastify');
|
|
31
31
|
var z = require('zod');
|
|
32
32
|
var fastifyTypeProviderZod = require('fastify-type-provider-zod');
|
|
33
33
|
var mcp_js = require('@modelcontextprotocol/sdk/server/mcp.js');
|
|
34
34
|
var node_http = require('node:http');
|
|
35
35
|
var streamableHttp_js = require('@modelcontextprotocol/sdk/server/streamableHttp.js');
|
|
36
|
+
var node_events = require('node:events');
|
|
36
37
|
require('tweetnacl');
|
|
37
|
-
var http = require('http');
|
|
38
|
-
var util = require('util');
|
|
39
38
|
var node_zlib = require('node:zlib');
|
|
40
39
|
|
|
41
40
|
var _documentCurrentScript = typeof document !== 'undefined' ? document.currentScript : null;
|
|
@@ -1317,7 +1316,7 @@ function buildDaemonSafeEnv(baseEnv, binPath) {
|
|
|
1317
1316
|
env[pathKey] = [...prepend, ...existingParts].join(pathSep);
|
|
1318
1317
|
return env;
|
|
1319
1318
|
}
|
|
1320
|
-
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-F8r81l86.cjs', document.baseURI).href)));
|
|
1321
1320
|
const __dirname$1 = path.join(__filename$1, "..");
|
|
1322
1321
|
function getGlobalClaudeVersion(claudeExecutable) {
|
|
1323
1322
|
try {
|
|
@@ -5202,23 +5201,6 @@ ${typeLabels[type] || type}:`));
|
|
|
5202
5201
|
console.log(chalk.green("\n\u2705 Doctor diagnosis complete!\n"));
|
|
5203
5202
|
}
|
|
5204
5203
|
|
|
5205
|
-
async function openBrowser(url) {
|
|
5206
|
-
try {
|
|
5207
|
-
const forceOpen = process.env.FLOCKBAY_FORCE_BROWSER === "1" || process.env.FLOCKBAY_FORCE_BROWSER === "true";
|
|
5208
|
-
if (!forceOpen && (!process.stdout.isTTY || process.env.CI || process.env.HEADLESS)) {
|
|
5209
|
-
types.logger.debug("[browser] Headless/non-interactive environment detected, skipping browser open");
|
|
5210
|
-
return false;
|
|
5211
|
-
}
|
|
5212
|
-
types.logger.debug(`[browser] Attempting to open URL: ${url}`);
|
|
5213
|
-
await open(url, { wait: false });
|
|
5214
|
-
types.logger.debug("[browser] Browser opened successfully");
|
|
5215
|
-
return true;
|
|
5216
|
-
} catch (error) {
|
|
5217
|
-
types.logger.debug("[browser] Failed to open browser:", error);
|
|
5218
|
-
return false;
|
|
5219
|
-
}
|
|
5220
|
-
}
|
|
5221
|
-
|
|
5222
5204
|
async function loginWithClerkAndPairMachine() {
|
|
5223
5205
|
types.logger.debug("[AUTH] Starting Clerk-based CLI login + machine pairing");
|
|
5224
5206
|
const settings = await types.updateSettings(async (s) => {
|
|
@@ -5251,7 +5233,7 @@ async function loginWithClerkAndPairMachine() {
|
|
|
5251
5233
|
console.log("Open this link to sign in with Clerk and approve this machine:");
|
|
5252
5234
|
console.log(approveUrl);
|
|
5253
5235
|
console.log("");
|
|
5254
|
-
void openBrowser(approveUrl).catch(() => null);
|
|
5236
|
+
void types.openBrowser(approveUrl).catch(() => null);
|
|
5255
5237
|
const deadline = Date.now() + 10 * 6e4;
|
|
5256
5238
|
while (Date.now() < deadline) {
|
|
5257
5239
|
await types.delay(1e3);
|
|
@@ -13186,7 +13168,7 @@ Update: ${updateCommand}`);
|
|
|
13186
13168
|
summary: currentMetadata?.summary
|
|
13187
13169
|
}));
|
|
13188
13170
|
}
|
|
13189
|
-
await session.connectAndWait(
|
|
13171
|
+
await session.connectAndWait();
|
|
13190
13172
|
session.keepAlive(false, options.startingMode === "remote" ? "remote" : "local");
|
|
13191
13173
|
try {
|
|
13192
13174
|
types.logger.debug(`[START] Reporting session ${response.id} to daemon`);
|
|
@@ -13828,511 +13810,6 @@ ${chalk.bold("Usage:")}
|
|
|
13828
13810
|
`);
|
|
13829
13811
|
}
|
|
13830
13812
|
|
|
13831
|
-
const CLIENT_ID$2 = "app_EMoamEEZ73f0CkXaXp7hrann";
|
|
13832
|
-
const AUTH_BASE_URL = "https://auth.openai.com";
|
|
13833
|
-
const DEFAULT_PORT$2 = 1455;
|
|
13834
|
-
function generatePKCE$2() {
|
|
13835
|
-
const verifier = crypto.randomBytes(32).toString("base64url").replace(/[^a-zA-Z0-9\-._~]/g, "");
|
|
13836
|
-
const challenge = crypto.createHash("sha256").update(verifier).digest("base64url").replace(/=/g, "").replace(/\+/g, "-").replace(/\//g, "_");
|
|
13837
|
-
return { verifier, challenge };
|
|
13838
|
-
}
|
|
13839
|
-
function generateState$2() {
|
|
13840
|
-
return crypto.randomBytes(16).toString("hex");
|
|
13841
|
-
}
|
|
13842
|
-
function parseJWT(token) {
|
|
13843
|
-
const parts = token.split(".");
|
|
13844
|
-
if (parts.length !== 3) {
|
|
13845
|
-
throw new Error("Invalid JWT format");
|
|
13846
|
-
}
|
|
13847
|
-
const payload = Buffer.from(parts[1], "base64url").toString();
|
|
13848
|
-
return JSON.parse(payload);
|
|
13849
|
-
}
|
|
13850
|
-
async function findAvailablePort$2() {
|
|
13851
|
-
return new Promise((resolve) => {
|
|
13852
|
-
const server = http.createServer();
|
|
13853
|
-
server.listen(0, "127.0.0.1", () => {
|
|
13854
|
-
const port = server.address().port;
|
|
13855
|
-
server.close(() => resolve(port));
|
|
13856
|
-
});
|
|
13857
|
-
});
|
|
13858
|
-
}
|
|
13859
|
-
async function isPortAvailable$2(port) {
|
|
13860
|
-
return new Promise((resolve) => {
|
|
13861
|
-
const testServer = http.createServer();
|
|
13862
|
-
testServer.once("error", () => {
|
|
13863
|
-
testServer.close();
|
|
13864
|
-
resolve(false);
|
|
13865
|
-
});
|
|
13866
|
-
testServer.listen(port, "127.0.0.1", () => {
|
|
13867
|
-
testServer.close(() => resolve(true));
|
|
13868
|
-
});
|
|
13869
|
-
});
|
|
13870
|
-
}
|
|
13871
|
-
async function exchangeCodeForTokens$2(code, verifier, port) {
|
|
13872
|
-
const response = await fetch(`${AUTH_BASE_URL}/oauth/token`, {
|
|
13873
|
-
method: "POST",
|
|
13874
|
-
headers: {
|
|
13875
|
-
"Content-Type": "application/x-www-form-urlencoded"
|
|
13876
|
-
},
|
|
13877
|
-
body: new URLSearchParams({
|
|
13878
|
-
grant_type: "authorization_code",
|
|
13879
|
-
client_id: CLIENT_ID$2,
|
|
13880
|
-
code,
|
|
13881
|
-
code_verifier: verifier,
|
|
13882
|
-
redirect_uri: `http://localhost:${port}/auth/callback`
|
|
13883
|
-
})
|
|
13884
|
-
});
|
|
13885
|
-
if (!response.ok) {
|
|
13886
|
-
const error = await response.text();
|
|
13887
|
-
throw new Error(`Token exchange failed: ${error}`);
|
|
13888
|
-
}
|
|
13889
|
-
const data = await response.json();
|
|
13890
|
-
const idTokenPayload = parseJWT(data.id_token);
|
|
13891
|
-
let accountId = idTokenPayload.chatgpt_account_id;
|
|
13892
|
-
if (!accountId) {
|
|
13893
|
-
const authClaim = idTokenPayload["https://api.openai.com/auth"];
|
|
13894
|
-
if (authClaim && typeof authClaim === "object") {
|
|
13895
|
-
accountId = authClaim.chatgpt_account_id || authClaim.account_id;
|
|
13896
|
-
}
|
|
13897
|
-
}
|
|
13898
|
-
return {
|
|
13899
|
-
id_token: data.id_token,
|
|
13900
|
-
access_token: data.access_token || data.id_token,
|
|
13901
|
-
refresh_token: data.refresh_token,
|
|
13902
|
-
account_id: accountId
|
|
13903
|
-
};
|
|
13904
|
-
}
|
|
13905
|
-
async function startCallbackServer$2(state, verifier, port) {
|
|
13906
|
-
return new Promise((resolve, reject) => {
|
|
13907
|
-
const server = http.createServer(async (req, res) => {
|
|
13908
|
-
const url = new URL(req.url, `http://localhost:${port}`);
|
|
13909
|
-
if (url.pathname === "/auth/callback") {
|
|
13910
|
-
const code = url.searchParams.get("code");
|
|
13911
|
-
const receivedState = url.searchParams.get("state");
|
|
13912
|
-
if (receivedState !== state) {
|
|
13913
|
-
res.writeHead(400);
|
|
13914
|
-
res.end("Invalid state parameter");
|
|
13915
|
-
server.close();
|
|
13916
|
-
reject(new Error("Invalid state parameter"));
|
|
13917
|
-
return;
|
|
13918
|
-
}
|
|
13919
|
-
if (!code) {
|
|
13920
|
-
res.writeHead(400);
|
|
13921
|
-
res.end("No authorization code received");
|
|
13922
|
-
server.close();
|
|
13923
|
-
reject(new Error("No authorization code received"));
|
|
13924
|
-
return;
|
|
13925
|
-
}
|
|
13926
|
-
try {
|
|
13927
|
-
const tokens = await exchangeCodeForTokens$2(code, verifier, port);
|
|
13928
|
-
res.writeHead(200, { "Content-Type": "text/html" });
|
|
13929
|
-
res.end(`
|
|
13930
|
-
<html>
|
|
13931
|
-
<body style="font-family: sans-serif; padding: 20px;">
|
|
13932
|
-
<h2>\u2705 Authentication Successful!</h2>
|
|
13933
|
-
<p>You can close this window and return to your terminal.</p>
|
|
13934
|
-
<script>setTimeout(() => window.close(), 3000);<\/script>
|
|
13935
|
-
</body>
|
|
13936
|
-
</html>
|
|
13937
|
-
`);
|
|
13938
|
-
server.close();
|
|
13939
|
-
resolve(tokens);
|
|
13940
|
-
} catch (error) {
|
|
13941
|
-
res.writeHead(500);
|
|
13942
|
-
res.end("Token exchange failed");
|
|
13943
|
-
server.close();
|
|
13944
|
-
reject(error);
|
|
13945
|
-
}
|
|
13946
|
-
}
|
|
13947
|
-
});
|
|
13948
|
-
server.listen(port, "127.0.0.1", () => {
|
|
13949
|
-
});
|
|
13950
|
-
setTimeout(() => {
|
|
13951
|
-
server.close();
|
|
13952
|
-
reject(new Error("Authentication timeout"));
|
|
13953
|
-
}, 5 * 60 * 1e3);
|
|
13954
|
-
});
|
|
13955
|
-
}
|
|
13956
|
-
async function authenticateCodex() {
|
|
13957
|
-
const { verifier, challenge } = generatePKCE$2();
|
|
13958
|
-
const state = generateState$2();
|
|
13959
|
-
let port = DEFAULT_PORT$2;
|
|
13960
|
-
const portAvailable = await isPortAvailable$2(port);
|
|
13961
|
-
if (!portAvailable) {
|
|
13962
|
-
port = await findAvailablePort$2();
|
|
13963
|
-
}
|
|
13964
|
-
const serverPromise = startCallbackServer$2(state, verifier, port);
|
|
13965
|
-
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
13966
|
-
const redirect_uri = `http://localhost:${port}/auth/callback`;
|
|
13967
|
-
const params = [
|
|
13968
|
-
["response_type", "code"],
|
|
13969
|
-
["client_id", CLIENT_ID$2],
|
|
13970
|
-
["redirect_uri", redirect_uri],
|
|
13971
|
-
["scope", "openid profile email offline_access"],
|
|
13972
|
-
["code_challenge", challenge],
|
|
13973
|
-
["code_challenge_method", "S256"],
|
|
13974
|
-
["id_token_add_organizations", "true"],
|
|
13975
|
-
["codex_cli_simplified_flow", "true"],
|
|
13976
|
-
["state", state]
|
|
13977
|
-
];
|
|
13978
|
-
const queryString = params.map(([key, value]) => `${key}=${encodeURIComponent(value)}`).join("&");
|
|
13979
|
-
const authUrl = `${AUTH_BASE_URL}/oauth/authorize?${queryString}`;
|
|
13980
|
-
console.log("\u{1F4CB} Opening browser for authentication...");
|
|
13981
|
-
console.log(`If browser doesn't open, visit:
|
|
13982
|
-
${authUrl}
|
|
13983
|
-
`);
|
|
13984
|
-
await openBrowser(authUrl);
|
|
13985
|
-
const tokens = await serverPromise;
|
|
13986
|
-
console.log("\u{1F389} Authentication successful!");
|
|
13987
|
-
return tokens;
|
|
13988
|
-
}
|
|
13989
|
-
|
|
13990
|
-
const CLIENT_ID$1 = "9d1c250a-e61b-44d9-88ed-5944d1962f5e";
|
|
13991
|
-
const CLAUDE_AI_AUTHORIZE_URL = "https://claude.ai/oauth/authorize";
|
|
13992
|
-
const TOKEN_URL$1 = "https://console.anthropic.com/v1/oauth/token";
|
|
13993
|
-
const DEFAULT_PORT$1 = 54545;
|
|
13994
|
-
const SCOPE = "user:inference";
|
|
13995
|
-
function generatePKCE$1() {
|
|
13996
|
-
const verifier = crypto.randomBytes(32).toString("base64url").replace(/[^a-zA-Z0-9\-._~]/g, "");
|
|
13997
|
-
const challenge = crypto.createHash("sha256").update(verifier).digest("base64url").replace(/=/g, "").replace(/\+/g, "-").replace(/\//g, "_");
|
|
13998
|
-
return { verifier, challenge };
|
|
13999
|
-
}
|
|
14000
|
-
function generateState$1() {
|
|
14001
|
-
return crypto.randomBytes(32).toString("base64url");
|
|
14002
|
-
}
|
|
14003
|
-
async function findAvailablePort$1() {
|
|
14004
|
-
return new Promise((resolve) => {
|
|
14005
|
-
const server = http.createServer();
|
|
14006
|
-
server.listen(0, "127.0.0.1", () => {
|
|
14007
|
-
const port = server.address().port;
|
|
14008
|
-
server.close(() => resolve(port));
|
|
14009
|
-
});
|
|
14010
|
-
});
|
|
14011
|
-
}
|
|
14012
|
-
async function isPortAvailable$1(port) {
|
|
14013
|
-
return new Promise((resolve) => {
|
|
14014
|
-
const testServer = http.createServer();
|
|
14015
|
-
testServer.once("error", () => {
|
|
14016
|
-
testServer.close();
|
|
14017
|
-
resolve(false);
|
|
14018
|
-
});
|
|
14019
|
-
testServer.listen(port, "127.0.0.1", () => {
|
|
14020
|
-
testServer.close(() => resolve(true));
|
|
14021
|
-
});
|
|
14022
|
-
});
|
|
14023
|
-
}
|
|
14024
|
-
async function exchangeCodeForTokens$1(code, verifier, port, state) {
|
|
14025
|
-
const tokenResponse = await fetch(TOKEN_URL$1, {
|
|
14026
|
-
method: "POST",
|
|
14027
|
-
headers: {
|
|
14028
|
-
"Content-Type": "application/json"
|
|
14029
|
-
},
|
|
14030
|
-
body: JSON.stringify({
|
|
14031
|
-
grant_type: "authorization_code",
|
|
14032
|
-
code,
|
|
14033
|
-
redirect_uri: `http://localhost:${port}/callback`,
|
|
14034
|
-
client_id: CLIENT_ID$1,
|
|
14035
|
-
code_verifier: verifier,
|
|
14036
|
-
state
|
|
14037
|
-
})
|
|
14038
|
-
});
|
|
14039
|
-
if (!tokenResponse.ok) {
|
|
14040
|
-
throw new Error(`Token exchange failed: ${tokenResponse.statusText}`);
|
|
14041
|
-
}
|
|
14042
|
-
const tokenData = await tokenResponse.json();
|
|
14043
|
-
return {
|
|
14044
|
-
raw: tokenData,
|
|
14045
|
-
token: tokenData.access_token,
|
|
14046
|
-
expires: Date.now() + tokenData.expires_in * 1e3
|
|
14047
|
-
};
|
|
14048
|
-
}
|
|
14049
|
-
async function startCallbackServer$1(state, verifier, port) {
|
|
14050
|
-
return new Promise((resolve, reject) => {
|
|
14051
|
-
const server = http.createServer(async (req, res) => {
|
|
14052
|
-
const url = new URL(req.url, `http://localhost:${port}`);
|
|
14053
|
-
if (url.pathname === "/callback") {
|
|
14054
|
-
const code = url.searchParams.get("code");
|
|
14055
|
-
const receivedState = url.searchParams.get("state");
|
|
14056
|
-
if (receivedState !== state) {
|
|
14057
|
-
res.writeHead(400);
|
|
14058
|
-
res.end("Invalid state parameter");
|
|
14059
|
-
server.close();
|
|
14060
|
-
reject(new Error("Invalid state parameter"));
|
|
14061
|
-
return;
|
|
14062
|
-
}
|
|
14063
|
-
if (!code) {
|
|
14064
|
-
res.writeHead(400);
|
|
14065
|
-
res.end("No authorization code received");
|
|
14066
|
-
server.close();
|
|
14067
|
-
reject(new Error("No authorization code received"));
|
|
14068
|
-
return;
|
|
14069
|
-
}
|
|
14070
|
-
try {
|
|
14071
|
-
const tokens = await exchangeCodeForTokens$1(code, verifier, port, state);
|
|
14072
|
-
res.writeHead(302, {
|
|
14073
|
-
"Location": "https://console.anthropic.com/oauth/code/success?app=claude-code"
|
|
14074
|
-
});
|
|
14075
|
-
res.end();
|
|
14076
|
-
server.close();
|
|
14077
|
-
resolve(tokens);
|
|
14078
|
-
} catch (error) {
|
|
14079
|
-
res.writeHead(500);
|
|
14080
|
-
res.end("Token exchange failed");
|
|
14081
|
-
server.close();
|
|
14082
|
-
reject(error);
|
|
14083
|
-
}
|
|
14084
|
-
}
|
|
14085
|
-
});
|
|
14086
|
-
server.listen(port, "127.0.0.1", () => {
|
|
14087
|
-
});
|
|
14088
|
-
setTimeout(() => {
|
|
14089
|
-
server.close();
|
|
14090
|
-
reject(new Error("Authentication timeout"));
|
|
14091
|
-
}, 5 * 60 * 1e3);
|
|
14092
|
-
});
|
|
14093
|
-
}
|
|
14094
|
-
async function authenticateClaude() {
|
|
14095
|
-
console.log("\u{1F680} Starting Anthropic Claude authentication...");
|
|
14096
|
-
const { verifier, challenge } = generatePKCE$1();
|
|
14097
|
-
const state = generateState$1();
|
|
14098
|
-
let port = DEFAULT_PORT$1;
|
|
14099
|
-
const portAvailable = await isPortAvailable$1(port);
|
|
14100
|
-
if (!portAvailable) {
|
|
14101
|
-
console.log(`Port ${port} is in use, finding an available port...`);
|
|
14102
|
-
port = await findAvailablePort$1();
|
|
14103
|
-
}
|
|
14104
|
-
console.log(`\u{1F4E1} Using callback port: ${port}`);
|
|
14105
|
-
const serverPromise = startCallbackServer$1(state, verifier, port);
|
|
14106
|
-
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
14107
|
-
const redirect_uri = `http://localhost:${port}/callback`;
|
|
14108
|
-
const params = new URLSearchParams({
|
|
14109
|
-
code: "true",
|
|
14110
|
-
// This tells Claude.ai to show the code AND redirect
|
|
14111
|
-
client_id: CLIENT_ID$1,
|
|
14112
|
-
response_type: "code",
|
|
14113
|
-
redirect_uri,
|
|
14114
|
-
scope: SCOPE,
|
|
14115
|
-
code_challenge: challenge,
|
|
14116
|
-
code_challenge_method: "S256",
|
|
14117
|
-
state
|
|
14118
|
-
});
|
|
14119
|
-
const authUrl = `${CLAUDE_AI_AUTHORIZE_URL}?${params}`;
|
|
14120
|
-
console.log("\u{1F4CB} Opening browser for authentication...");
|
|
14121
|
-
console.log("If browser doesn't open, visit this URL:");
|
|
14122
|
-
console.log();
|
|
14123
|
-
console.log(`${authUrl}`);
|
|
14124
|
-
console.log();
|
|
14125
|
-
await openBrowser(authUrl);
|
|
14126
|
-
try {
|
|
14127
|
-
const tokens = await serverPromise;
|
|
14128
|
-
console.log("\u{1F389} Authentication successful!");
|
|
14129
|
-
console.log("\u2705 OAuth tokens received");
|
|
14130
|
-
return tokens;
|
|
14131
|
-
} catch (error) {
|
|
14132
|
-
console.error("\n\u274C Failed to authenticate with Anthropic");
|
|
14133
|
-
throw error;
|
|
14134
|
-
}
|
|
14135
|
-
}
|
|
14136
|
-
|
|
14137
|
-
const execAsync = util.promisify(child_process.exec);
|
|
14138
|
-
const CLIENT_ID = "681255809395-oo8ft2oprdrnp9e3aqf6av3hmdib135j.apps.googleusercontent.com";
|
|
14139
|
-
const CLIENT_SECRET = "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";
|
|
14140
|
-
const AUTHORIZE_URL = "https://accounts.google.com/o/oauth2/v2/auth";
|
|
14141
|
-
const TOKEN_URL = "https://oauth2.googleapis.com/token";
|
|
14142
|
-
const DEFAULT_PORT = 54545;
|
|
14143
|
-
const SCOPES = [
|
|
14144
|
-
"https://www.googleapis.com/auth/cloud-platform",
|
|
14145
|
-
"https://www.googleapis.com/auth/userinfo.email",
|
|
14146
|
-
"https://www.googleapis.com/auth/userinfo.profile"
|
|
14147
|
-
].join(" ");
|
|
14148
|
-
function generatePKCE() {
|
|
14149
|
-
const verifier = crypto.randomBytes(32).toString("base64url").replace(/[^a-zA-Z0-9\-._~]/g, "");
|
|
14150
|
-
const challenge = crypto.createHash("sha256").update(verifier).digest("base64url").replace(/=/g, "").replace(/\+/g, "-").replace(/\//g, "_");
|
|
14151
|
-
return { verifier, challenge };
|
|
14152
|
-
}
|
|
14153
|
-
function generateState() {
|
|
14154
|
-
return crypto.randomBytes(32).toString("hex");
|
|
14155
|
-
}
|
|
14156
|
-
async function findAvailablePort() {
|
|
14157
|
-
return new Promise((resolve) => {
|
|
14158
|
-
const server = http.createServer();
|
|
14159
|
-
server.listen(0, "127.0.0.1", () => {
|
|
14160
|
-
const port = server.address().port;
|
|
14161
|
-
server.close(() => resolve(port));
|
|
14162
|
-
});
|
|
14163
|
-
});
|
|
14164
|
-
}
|
|
14165
|
-
async function isPortAvailable(port) {
|
|
14166
|
-
return new Promise((resolve) => {
|
|
14167
|
-
const testServer = http.createServer();
|
|
14168
|
-
testServer.once("error", () => {
|
|
14169
|
-
testServer.close();
|
|
14170
|
-
resolve(false);
|
|
14171
|
-
});
|
|
14172
|
-
testServer.listen(port, "127.0.0.1", () => {
|
|
14173
|
-
testServer.close(() => resolve(true));
|
|
14174
|
-
});
|
|
14175
|
-
});
|
|
14176
|
-
}
|
|
14177
|
-
async function exchangeCodeForTokens(code, verifier, port) {
|
|
14178
|
-
const response = await fetch(TOKEN_URL, {
|
|
14179
|
-
method: "POST",
|
|
14180
|
-
headers: {
|
|
14181
|
-
"Content-Type": "application/x-www-form-urlencoded"
|
|
14182
|
-
},
|
|
14183
|
-
body: new URLSearchParams({
|
|
14184
|
-
grant_type: "authorization_code",
|
|
14185
|
-
client_id: CLIENT_ID,
|
|
14186
|
-
client_secret: CLIENT_SECRET,
|
|
14187
|
-
code,
|
|
14188
|
-
code_verifier: verifier,
|
|
14189
|
-
redirect_uri: `http://localhost:${port}/oauth2callback`
|
|
14190
|
-
})
|
|
14191
|
-
});
|
|
14192
|
-
if (!response.ok) {
|
|
14193
|
-
const error = await response.text();
|
|
14194
|
-
throw new Error(`Token exchange failed: ${error}`);
|
|
14195
|
-
}
|
|
14196
|
-
const data = await response.json();
|
|
14197
|
-
return data;
|
|
14198
|
-
}
|
|
14199
|
-
async function startCallbackServer(state, verifier, port) {
|
|
14200
|
-
return new Promise((resolve, reject) => {
|
|
14201
|
-
const server = http.createServer(async (req, res) => {
|
|
14202
|
-
const url = new URL(req.url, `http://localhost:${port}`);
|
|
14203
|
-
if (url.pathname === "/oauth2callback") {
|
|
14204
|
-
const code = url.searchParams.get("code");
|
|
14205
|
-
const receivedState = url.searchParams.get("state");
|
|
14206
|
-
const error = url.searchParams.get("error");
|
|
14207
|
-
if (error) {
|
|
14208
|
-
res.writeHead(302, {
|
|
14209
|
-
"Location": "https://developers.google.com/gemini-code-assist/auth_failure_gemini"
|
|
14210
|
-
});
|
|
14211
|
-
res.end();
|
|
14212
|
-
server.close();
|
|
14213
|
-
reject(new Error(`Authentication error: ${error}`));
|
|
14214
|
-
return;
|
|
14215
|
-
}
|
|
14216
|
-
if (receivedState !== state) {
|
|
14217
|
-
res.writeHead(400);
|
|
14218
|
-
res.end("State mismatch. Possible CSRF attack");
|
|
14219
|
-
server.close();
|
|
14220
|
-
reject(new Error("Invalid state parameter"));
|
|
14221
|
-
return;
|
|
14222
|
-
}
|
|
14223
|
-
if (!code) {
|
|
14224
|
-
res.writeHead(400);
|
|
14225
|
-
res.end("No authorization code received");
|
|
14226
|
-
server.close();
|
|
14227
|
-
reject(new Error("No authorization code received"));
|
|
14228
|
-
return;
|
|
14229
|
-
}
|
|
14230
|
-
try {
|
|
14231
|
-
const tokens = await exchangeCodeForTokens(code, verifier, port);
|
|
14232
|
-
res.writeHead(302, {
|
|
14233
|
-
"Location": "https://developers.google.com/gemini-code-assist/auth_success_gemini"
|
|
14234
|
-
});
|
|
14235
|
-
res.end();
|
|
14236
|
-
server.close();
|
|
14237
|
-
resolve(tokens);
|
|
14238
|
-
} catch (error2) {
|
|
14239
|
-
res.writeHead(500);
|
|
14240
|
-
res.end("Token exchange failed");
|
|
14241
|
-
server.close();
|
|
14242
|
-
reject(error2);
|
|
14243
|
-
}
|
|
14244
|
-
}
|
|
14245
|
-
});
|
|
14246
|
-
server.listen(port, "127.0.0.1", () => {
|
|
14247
|
-
});
|
|
14248
|
-
setTimeout(() => {
|
|
14249
|
-
server.close();
|
|
14250
|
-
reject(new Error("Authentication timeout"));
|
|
14251
|
-
}, 5 * 60 * 1e3);
|
|
14252
|
-
});
|
|
14253
|
-
}
|
|
14254
|
-
async function authenticateGemini() {
|
|
14255
|
-
console.log("\u{1F680} Starting Google Gemini authentication...");
|
|
14256
|
-
const { verifier, challenge } = generatePKCE();
|
|
14257
|
-
const state = generateState();
|
|
14258
|
-
let port = DEFAULT_PORT;
|
|
14259
|
-
const portAvailable = await isPortAvailable(port);
|
|
14260
|
-
if (!portAvailable) {
|
|
14261
|
-
console.log(`Port ${port} is in use, finding an available port...`);
|
|
14262
|
-
port = await findAvailablePort();
|
|
14263
|
-
}
|
|
14264
|
-
console.log(`\u{1F4E1} Using callback port: ${port}`);
|
|
14265
|
-
const serverPromise = startCallbackServer(state, verifier, port);
|
|
14266
|
-
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
14267
|
-
const redirect_uri = `http://localhost:${port}/oauth2callback`;
|
|
14268
|
-
const params = new URLSearchParams({
|
|
14269
|
-
client_id: CLIENT_ID,
|
|
14270
|
-
response_type: "code",
|
|
14271
|
-
redirect_uri,
|
|
14272
|
-
scope: SCOPES,
|
|
14273
|
-
access_type: "offline",
|
|
14274
|
-
// To get refresh token
|
|
14275
|
-
code_challenge: challenge,
|
|
14276
|
-
code_challenge_method: "S256",
|
|
14277
|
-
state,
|
|
14278
|
-
prompt: "consent"
|
|
14279
|
-
// Force consent to get refresh token
|
|
14280
|
-
});
|
|
14281
|
-
const authUrl = `${AUTHORIZE_URL}?${params}`;
|
|
14282
|
-
console.log("\n\u{1F4CB} Opening browser for authentication...");
|
|
14283
|
-
console.log("If browser doesn't open, visit this URL:");
|
|
14284
|
-
console.log(`
|
|
14285
|
-
${authUrl}
|
|
14286
|
-
`);
|
|
14287
|
-
const platform = process.platform;
|
|
14288
|
-
const openCommand = platform === "darwin" ? "open" : platform === "win32" ? "start" : "xdg-open";
|
|
14289
|
-
try {
|
|
14290
|
-
await execAsync(`${openCommand} "${authUrl}"`);
|
|
14291
|
-
} catch {
|
|
14292
|
-
console.log("\u26A0\uFE0F Could not open browser automatically");
|
|
14293
|
-
}
|
|
14294
|
-
try {
|
|
14295
|
-
const tokens = await serverPromise;
|
|
14296
|
-
console.log("\n\u{1F389} Authentication successful!");
|
|
14297
|
-
console.log("\u2705 OAuth tokens received");
|
|
14298
|
-
return tokens;
|
|
14299
|
-
} catch (error) {
|
|
14300
|
-
console.error("\n\u274C Failed to authenticate with Google");
|
|
14301
|
-
throw error;
|
|
14302
|
-
}
|
|
14303
|
-
}
|
|
14304
|
-
|
|
14305
|
-
async function syncCodexCliAuth(tokens) {
|
|
14306
|
-
const authFilePath = path.join(os.homedir(), ".codex", "auth.json");
|
|
14307
|
-
const authDir = path.dirname(authFilePath);
|
|
14308
|
-
let previousAccountId;
|
|
14309
|
-
let previousApiKey = null;
|
|
14310
|
-
try {
|
|
14311
|
-
const existingRaw = await fs$2.readFile(authFilePath, "utf8");
|
|
14312
|
-
const existing = JSON.parse(existingRaw);
|
|
14313
|
-
previousAccountId = existing?.tokens?.account_id;
|
|
14314
|
-
previousApiKey = typeof existing?.OPENAI_API_KEY === "string" ? existing.OPENAI_API_KEY : null;
|
|
14315
|
-
} catch {
|
|
14316
|
-
}
|
|
14317
|
-
await fs$2.mkdir(authDir, { recursive: true });
|
|
14318
|
-
const next = {
|
|
14319
|
-
OPENAI_API_KEY: previousApiKey,
|
|
14320
|
-
tokens: {
|
|
14321
|
-
id_token: tokens.id_token,
|
|
14322
|
-
access_token: tokens.access_token,
|
|
14323
|
-
refresh_token: tokens.refresh_token,
|
|
14324
|
-
account_id: tokens.account_id
|
|
14325
|
-
},
|
|
14326
|
-
last_refresh: (/* @__PURE__ */ new Date()).toISOString()
|
|
14327
|
-
};
|
|
14328
|
-
await fs$2.writeFile(authFilePath, JSON.stringify(next, null, 2) + "\n", "utf8");
|
|
14329
|
-
return {
|
|
14330
|
-
authFilePath,
|
|
14331
|
-
previousAccountId,
|
|
14332
|
-
newAccountId: tokens.account_id
|
|
14333
|
-
};
|
|
14334
|
-
}
|
|
14335
|
-
|
|
14336
13813
|
async function handleConnectCommand(args) {
|
|
14337
13814
|
const subcommand = args[0];
|
|
14338
13815
|
const flags = args.slice(1);
|
|
@@ -14408,13 +13885,13 @@ async function handleConnectVendor(vendor, displayName, flags) {
|
|
|
14408
13885
|
const api = await types.ApiClient.create(credentials);
|
|
14409
13886
|
if (vendor === "codex") {
|
|
14410
13887
|
console.log("\u{1F680} Registering Codex token with server");
|
|
14411
|
-
const codexAuthTokens = await authenticateCodex();
|
|
13888
|
+
const codexAuthTokens = await types.authenticateCodex();
|
|
14412
13889
|
await api.registerVendorToken("openai", { oauth: codexAuthTokens });
|
|
14413
13890
|
console.log("\u2705 Codex token registered with server");
|
|
14414
13891
|
const shouldSyncLocal = !noLocal;
|
|
14415
13892
|
if (shouldSyncLocal) {
|
|
14416
13893
|
try {
|
|
14417
|
-
const result = await syncCodexCliAuth(codexAuthTokens);
|
|
13894
|
+
const result = await types.syncCodexCliAuth(codexAuthTokens);
|
|
14418
13895
|
const from = result.previousAccountId ? `from ${result.previousAccountId} ` : "";
|
|
14419
13896
|
const to = result.newAccountId ? `to ${result.newAccountId}` : "to an unknown account";
|
|
14420
13897
|
console.log(chalk.gray(`\u{1F501} Synced local Codex CLI login ${from}${to} (${result.authFilePath})`));
|
|
@@ -14426,13 +13903,13 @@ async function handleConnectVendor(vendor, displayName, flags) {
|
|
|
14426
13903
|
process.exit(0);
|
|
14427
13904
|
} else if (vendor === "claude") {
|
|
14428
13905
|
console.log("\u{1F680} Registering Anthropic token with server");
|
|
14429
|
-
const anthropicAuthTokens = await authenticateClaude();
|
|
13906
|
+
const anthropicAuthTokens = await types.authenticateClaude();
|
|
14430
13907
|
await api.registerVendorToken("anthropic", { oauth: anthropicAuthTokens });
|
|
14431
13908
|
console.log("\u2705 Anthropic token registered with server");
|
|
14432
13909
|
process.exit(0);
|
|
14433
13910
|
} else if (vendor === "gemini") {
|
|
14434
13911
|
console.log("\u{1F680} Registering Gemini token with server");
|
|
14435
|
-
const geminiAuthTokens = await authenticateGemini();
|
|
13912
|
+
const geminiAuthTokens = await types.authenticateGemini();
|
|
14436
13913
|
await api.registerVendorToken("gemini", { oauth: geminiAuthTokens });
|
|
14437
13914
|
console.log("\u2705 Gemini token registered with server");
|
|
14438
13915
|
process.exit(0);
|
|
@@ -14672,7 +14149,8 @@ async function runSmokeForAgent(agent, args) {
|
|
|
14672
14149
|
const skipUnreal = !readFlag(args, "--with-unreal");
|
|
14673
14150
|
const baseDir = readArgValue$2(args, "--directory") || readArgValue$2(args, "--dir");
|
|
14674
14151
|
const timeoutMsRaw = readArgValue$2(args, "--timeout-ms");
|
|
14675
|
-
const
|
|
14152
|
+
const defaultTimeoutMs = process.platform === "win32" ? 24e4 : 9e4;
|
|
14153
|
+
const timeoutMs = timeoutMsRaw && Number.isFinite(Number(timeoutMsRaw)) ? Number(timeoutMsRaw) : defaultTimeoutMs;
|
|
14676
14154
|
let sessionId;
|
|
14677
14155
|
let directory;
|
|
14678
14156
|
let sessionClient = null;
|
|
@@ -14720,7 +14198,7 @@ Update: ${updateCommand}`);
|
|
|
14720
14198
|
throw new Error(msg);
|
|
14721
14199
|
}
|
|
14722
14200
|
sessionClient = api.sessionSyncClient(session);
|
|
14723
|
-
await sessionClient.connectAndWait(
|
|
14201
|
+
await sessionClient.connectAndWait();
|
|
14724
14202
|
await ensureSessionActive(api, sessionId, 25e3);
|
|
14725
14203
|
const permissionMode = permissionModeForAgent(agent);
|
|
14726
14204
|
scenarios.push(await runScenario("basic-message", async () => {
|
|
@@ -14825,7 +14303,7 @@ Options:
|
|
|
14825
14303
|
--agent, -a Run a single agent
|
|
14826
14304
|
--agents Comma-separated list of agents
|
|
14827
14305
|
--directory, --dir Directory to run the session in (defaults to a temp folder)
|
|
14828
|
-
--timeout-ms Per-scenario timeout (default 90000)
|
|
14306
|
+
--timeout-ms Per-scenario timeout (default 90000; Windows default 240000)
|
|
14829
14307
|
--keep Do not stop session or delete temp dir
|
|
14830
14308
|
--json Write results JSON to a file
|
|
14831
14309
|
--with-unreal Allow Unreal MCP prompts (off by default)
|
|
@@ -14889,6 +14367,18 @@ function splitList(value) {
|
|
|
14889
14367
|
function ensureDir(dir) {
|
|
14890
14368
|
fs.mkdirSync(dir, { recursive: true });
|
|
14891
14369
|
}
|
|
14370
|
+
function canWriteDir(dir) {
|
|
14371
|
+
const root = (dir || "").trim();
|
|
14372
|
+
if (!root) return false;
|
|
14373
|
+
try {
|
|
14374
|
+
const tmp = path.join(root, `.__flockbay_write_test_${Date.now()}_${Math.random().toString(16).slice(2)}.tmp`);
|
|
14375
|
+
fs.writeFileSync(tmp, "ok", "utf8");
|
|
14376
|
+
fs.unlinkSync(tmp);
|
|
14377
|
+
return true;
|
|
14378
|
+
} catch {
|
|
14379
|
+
return false;
|
|
14380
|
+
}
|
|
14381
|
+
}
|
|
14892
14382
|
function detectImageMimeTypeFromBuffer(buf) {
|
|
14893
14383
|
if (!buf || buf.length < 12) return null;
|
|
14894
14384
|
if (buf[0] === 137 && buf[1] === 80 && buf[2] === 78 && buf[3] === 71 && buf[4] === 13 && buf[5] === 10 && buf[6] === 26 && buf[7] === 10) {
|
|
@@ -14907,7 +14397,7 @@ async function waitForUnreal(options) {
|
|
|
14907
14397
|
while (Date.now() - startedAt < options.timeoutMs) {
|
|
14908
14398
|
try {
|
|
14909
14399
|
const res = await types.sendUnrealMcpTcpCommand({ type: "ping", host: options.host, port: options.port, timeoutMs: 2e3 });
|
|
14910
|
-
const msg = typeof res?.message === "string" ? res.message : null;
|
|
14400
|
+
const msg = typeof res?.message === "string" ? res.message : typeof res?.result?.message === "string" ? res.result.message : null;
|
|
14911
14401
|
if (msg === "pong") return { ok: true };
|
|
14912
14402
|
} catch (err) {
|
|
14913
14403
|
lastErr = err instanceof Error ? err.message : String(err);
|
|
@@ -14955,22 +14445,23 @@ async function runRuntimeSmoke(options) {
|
|
|
14955
14445
|
}
|
|
14956
14446
|
try {
|
|
14957
14447
|
const pluginInfo = await types.sendUnrealMcpTcpCommand({ type: "get_plugin_info", host: options.host, port: options.port, timeoutMs: options.timeoutMs });
|
|
14958
|
-
const
|
|
14959
|
-
const
|
|
14960
|
-
const
|
|
14961
|
-
const
|
|
14962
|
-
const
|
|
14963
|
-
|
|
14448
|
+
const pluginInfoResult = pluginInfo?.result && typeof pluginInfo.result === "object" ? pluginInfo.result : pluginInfo;
|
|
14449
|
+
const createdBy = String(pluginInfoResult?.createdBy || "").trim();
|
|
14450
|
+
const friendlyName = String(pluginInfoResult?.friendlyName || "").trim();
|
|
14451
|
+
const baseDir = String(pluginInfoResult?.baseDir || "").trim();
|
|
14452
|
+
const schemaVersion = Number(pluginInfoResult?.schemaVersion);
|
|
14453
|
+
const commands = Array.isArray(pluginInfoResult?.commands) ? pluginInfoResult.commands.filter((c) => typeof c === "string") : [];
|
|
14454
|
+
if (friendlyName !== "Flockbay MCP" || createdBy !== "Respaced Inc.") {
|
|
14964
14455
|
return {
|
|
14965
14456
|
ok: false,
|
|
14966
14457
|
error: `Unexpected plugin identity loaded by Unreal.
|
|
14967
14458
|
friendlyName=${friendlyName || "(missing)"} createdBy=${createdBy || "(missing)"}
|
|
14968
14459
|
baseDir=${baseDir || "(missing)"}
|
|
14969
|
-
Expected FriendlyName="
|
|
14460
|
+
Expected FriendlyName="Flockbay MCP" CreatedBy="Respaced Inc."`
|
|
14970
14461
|
};
|
|
14971
14462
|
}
|
|
14972
14463
|
if (!Number.isFinite(schemaVersion) || schemaVersion <= 0) {
|
|
14973
|
-
return { ok: false, error: `Invalid schemaVersion from get_plugin_info: ${String(
|
|
14464
|
+
return { ok: false, error: `Invalid schemaVersion from get_plugin_info: ${String(pluginInfoResult?.schemaVersion)}` };
|
|
14974
14465
|
}
|
|
14975
14466
|
const requireCommands = [
|
|
14976
14467
|
"ping",
|
|
@@ -14990,7 +14481,8 @@ Expected FriendlyName="Unreal MCP Plugin" CreatedBy="Respaced Inc."`
|
|
|
14990
14481
|
return { ok: false, error: `Missing required commands in this Unreal MCP build: ${missing.join(", ")}` };
|
|
14991
14482
|
}
|
|
14992
14483
|
const playStatus0 = await types.sendUnrealMcpTcpCommand({ type: "get_play_in_editor_status", host: options.host, port: options.port, timeoutMs: options.timeoutMs });
|
|
14993
|
-
const
|
|
14484
|
+
const playStatusResult = playStatus0?.result && typeof playStatus0.result === "object" ? playStatus0.result : playStatus0;
|
|
14485
|
+
const isPlaying = Boolean(playStatusResult?.isPlaySessionInProgress);
|
|
14994
14486
|
if (isPlaying) {
|
|
14995
14487
|
await types.sendUnrealMcpTcpCommand({ type: "stop_play_in_editor", host: options.host, port: options.port, timeoutMs: options.timeoutMs });
|
|
14996
14488
|
}
|
|
@@ -15017,7 +14509,9 @@ Expected FriendlyName="Unreal MCP Plugin" CreatedBy="Respaced Inc."`
|
|
|
15017
14509
|
const bpName = `BP_Smoke_${Date.now()}`;
|
|
15018
14510
|
await types.sendUnrealMcpTcpCommand({
|
|
15019
14511
|
type: "create_blueprint",
|
|
15020
|
-
|
|
14512
|
+
// Important: pass only the name so the plugin's default (/Game/Blueprints/) is used.
|
|
14513
|
+
// The plugin's "compile_blueprint" name-only lookup searches /Game/Blueprints by design.
|
|
14514
|
+
params: { name: bpName, parent_class: "Actor" },
|
|
15021
14515
|
host: options.host,
|
|
15022
14516
|
port: options.port,
|
|
15023
14517
|
timeoutMs: Math.max(options.timeoutMs, 2e4)
|
|
@@ -15084,26 +14578,73 @@ async function runUnrealMcpMatrixSmoke(args) {
|
|
|
15084
14578
|
if (!engineRoot) continue;
|
|
15085
14579
|
console.log(chalk.bold(`== Engine: ${engineRoot} ==`));
|
|
15086
14580
|
if (doBuild) {
|
|
15087
|
-
|
|
15088
|
-
const
|
|
15089
|
-
|
|
15090
|
-
|
|
15091
|
-
|
|
14581
|
+
const enginePluginsDir = path.join(engineRoot, "Engine", "Plugins");
|
|
14582
|
+
const enginePluginDir = path.join(enginePluginsDir, "FlockbayMCP");
|
|
14583
|
+
const enginePluginUplugin = path.join(enginePluginDir, "FlockbayMCP.uplugin");
|
|
14584
|
+
const enginePluginHasBinaries = fs.existsSync(path.join(enginePluginDir, "Binaries"));
|
|
14585
|
+
const projectUprojectPath = project ? path.resolve(project) : null;
|
|
14586
|
+
if (fs.existsSync(enginePluginUplugin) && enginePluginHasBinaries) {
|
|
14587
|
+
console.log(chalk.green(`Build: engine plugin already installed + built (${enginePluginDir})`));
|
|
14588
|
+
} else if (canWriteDir(enginePluginsDir)) {
|
|
14589
|
+
console.log(chalk.cyan("Build: installing Flockbay MCP plugin sources into the engine (folder: FlockbayMCP)..."));
|
|
14590
|
+
const installed = types.installUnrealMcpPluginToEngine(engineRoot);
|
|
14591
|
+
if (!installed.ok) {
|
|
14592
|
+
failures.push({ engineRoot, phase: "build", error: installed.errorMessage });
|
|
14593
|
+
console.log(chalk.red(`Build: failed (install)
|
|
15092
14594
|
${installed.errorMessage}
|
|
15093
14595
|
`));
|
|
15094
|
-
|
|
15095
|
-
|
|
15096
|
-
|
|
15097
|
-
|
|
15098
|
-
|
|
15099
|
-
|
|
15100
|
-
|
|
15101
|
-
|
|
14596
|
+
if (!doRuntime) continue;
|
|
14597
|
+
} else {
|
|
14598
|
+
console.log(chalk.green(`Build: sources installed to ${installed.destDir}`));
|
|
14599
|
+
console.log(chalk.cyan("Build: compiling plugin via RunUAT BuildPlugin..."));
|
|
14600
|
+
const built = await types.buildAndInstallUnrealMcpPlugin({ engineRoot, flockbayHomeDir: types.configuration.flockbayHomeDir });
|
|
14601
|
+
if (!built.ok) {
|
|
14602
|
+
failures.push({ engineRoot, phase: "build", error: built.errorMessage });
|
|
14603
|
+
console.log(chalk.red(`Build: failed
|
|
15102
14604
|
${built.errorMessage}
|
|
15103
14605
|
`));
|
|
14606
|
+
} else {
|
|
14607
|
+
console.log(chalk.green(`Build: ok (log: ${built.buildLogPath})`));
|
|
14608
|
+
}
|
|
14609
|
+
}
|
|
14610
|
+
} else if (projectUprojectPath) {
|
|
14611
|
+
console.log(chalk.cyan("Build: engine install not writable; installing plugin into the project instead..."));
|
|
14612
|
+
const installedProject = types.installUnrealMcpPluginToProject(projectUprojectPath);
|
|
14613
|
+
if (!installedProject.ok) {
|
|
14614
|
+
failures.push({ engineRoot, phase: "build", error: installedProject.errorMessage });
|
|
14615
|
+
console.log(chalk.red(`Build: failed (project install)
|
|
14616
|
+
${installedProject.errorMessage}
|
|
14617
|
+
`));
|
|
14618
|
+
if (!doRuntime) continue;
|
|
15104
14619
|
} else {
|
|
15105
|
-
console.log(chalk.green(`Build:
|
|
14620
|
+
console.log(chalk.green(`Build: sources installed to ${installedProject.destDir}`));
|
|
14621
|
+
console.log(chalk.cyan("Build: compiling plugin via RunUAT BuildPlugin..."));
|
|
14622
|
+
const built = await types.buildAndInstallUnrealMcpPlugin({
|
|
14623
|
+
engineRoot,
|
|
14624
|
+
flockbayHomeDir: types.configuration.flockbayHomeDir,
|
|
14625
|
+
pluginDir: installedProject.destDir
|
|
14626
|
+
});
|
|
14627
|
+
if (!built.ok) {
|
|
14628
|
+
failures.push({ engineRoot, phase: "build", error: built.errorMessage });
|
|
14629
|
+
console.log(chalk.red(`Build: failed
|
|
14630
|
+
${built.errorMessage}
|
|
14631
|
+
`));
|
|
14632
|
+
} else {
|
|
14633
|
+
console.log(chalk.green(`Build: ok (log: ${built.buildLogPath})`));
|
|
14634
|
+
}
|
|
15106
14635
|
}
|
|
14636
|
+
} else {
|
|
14637
|
+
const error = `Engine plugins folder is not writable:
|
|
14638
|
+
${enginePluginsDir}
|
|
14639
|
+
|
|
14640
|
+
Fix:
|
|
14641
|
+
- Re-run with --project "<path-to-your-project>.uproject" so we can install the plugin into the project (no admin), OR
|
|
14642
|
+
- Run the installer with Windows admin permissions.`;
|
|
14643
|
+
failures.push({ engineRoot, phase: "build", error });
|
|
14644
|
+
console.log(chalk.red(`Build: failed
|
|
14645
|
+
${error}
|
|
14646
|
+
`));
|
|
14647
|
+
if (!doRuntime) continue;
|
|
15107
14648
|
}
|
|
15108
14649
|
}
|
|
15109
14650
|
if (doRuntime) {
|
|
@@ -15562,7 +15103,7 @@ async function authAndSetupMachineIfNeeded() {
|
|
|
15562
15103
|
process.exit(1);
|
|
15563
15104
|
}
|
|
15564
15105
|
try {
|
|
15565
|
-
const { migrateUnrealMcpToFlockbayMcp } = await Promise.resolve().then(function () { return require('./migratePlugin-
|
|
15106
|
+
const { migrateUnrealMcpToFlockbayMcp } = await Promise.resolve().then(function () { return require('./migratePlugin-T0MOGk0T.cjs'); });
|
|
15566
15107
|
const result = migrateUnrealMcpToFlockbayMcp({
|
|
15567
15108
|
engineRoot,
|
|
15568
15109
|
projectUprojectPath: project || void 0,
|
|
@@ -15701,7 +15242,7 @@ ${engineRoot}`, {
|
|
|
15701
15242
|
} else if (subcommand === "codex") {
|
|
15702
15243
|
try {
|
|
15703
15244
|
await chdirToNearestUprojectRootIfPresent();
|
|
15704
|
-
const { runCodex } = await Promise.resolve().then(function () { return require('./runCodex-
|
|
15245
|
+
const { runCodex } = await Promise.resolve().then(function () { return require('./runCodex-Bx4E0ukk.cjs'); });
|
|
15705
15246
|
let startedBy = void 0;
|
|
15706
15247
|
let sessionId = void 0;
|
|
15707
15248
|
for (let i = 1; i < args.length; i++) {
|
|
@@ -15803,7 +15344,7 @@ ${engineRoot}`, {
|
|
|
15803
15344
|
}
|
|
15804
15345
|
try {
|
|
15805
15346
|
await chdirToNearestUprojectRootIfPresent();
|
|
15806
|
-
const { runGemini } = await Promise.resolve().then(function () { return require('./runGemini-
|
|
15347
|
+
const { runGemini } = await Promise.resolve().then(function () { return require('./runGemini-xvROo10g.cjs'); });
|
|
15807
15348
|
let startedBy = void 0;
|
|
15808
15349
|
let sessionId = void 0;
|
|
15809
15350
|
for (let i = 1; i < args.length; i++) {
|