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
|
@@ -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, w as writeCredentials, j as unrealMcpPythonDir, k as acquireDaemonLock, m as writeDaemonState, n as ApiMachineClient,
|
|
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-D1UKSrkg.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';
|
|
@@ -10,33 +10,32 @@ import { createInterface } from 'node:readline';
|
|
|
10
10
|
import * as fs from 'node:fs';
|
|
11
11
|
import fs__default, { existsSync, readFileSync, mkdirSync, readdirSync, accessSync, constants, statSync, createReadStream, writeFileSync, unlinkSync } from 'node:fs';
|
|
12
12
|
import process$1 from 'node:process';
|
|
13
|
-
import fs$1, { readFile, access as access$1, mkdir, readdir, stat, writeFile, copyFile, rename, open
|
|
13
|
+
import fs$1, { readFile, access as access$1, mkdir, readdir, stat, writeFile, copyFile, rename, open } from 'node:fs/promises';
|
|
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
17
|
import { fileURLToPath } from 'node:url';
|
|
18
18
|
import axios from 'axios';
|
|
19
|
-
import { EventEmitter } from 'node:events';
|
|
20
19
|
import 'socket.io-client';
|
|
21
|
-
import { spawn as spawn$1, execFileSync as execFileSync$1
|
|
22
|
-
import { createHash
|
|
20
|
+
import { spawn as spawn$1, execFileSync as execFileSync$1 } from 'child_process';
|
|
21
|
+
import { createHash } from 'crypto';
|
|
23
22
|
import { join as join$1, basename, dirname as dirname$1 } from 'path';
|
|
24
23
|
import os$1 from 'os';
|
|
25
24
|
import 'node:net';
|
|
25
|
+
import 'http';
|
|
26
|
+
import 'open';
|
|
26
27
|
import { readFileSync as readFileSync$1, mkdirSync as mkdirSync$1, writeFileSync as writeFileSync$1, existsSync as existsSync$1, unlinkSync as unlinkSync$1 } from 'fs';
|
|
27
28
|
import psList from 'ps-list';
|
|
28
29
|
import spawn$2 from 'cross-spawn';
|
|
29
30
|
import * as tmp from 'tmp';
|
|
30
|
-
import open from 'open';
|
|
31
31
|
import fastify from 'fastify';
|
|
32
32
|
import { z } from 'zod';
|
|
33
33
|
import { validatorCompiler, serializerCompiler } from 'fastify-type-provider-zod';
|
|
34
34
|
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
35
35
|
import { createServer } from 'node:http';
|
|
36
36
|
import { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js';
|
|
37
|
+
import { EventEmitter } from 'node:events';
|
|
37
38
|
import 'tweetnacl';
|
|
38
|
-
import { createServer as createServer$1 } from 'http';
|
|
39
|
-
import { promisify } from 'util';
|
|
40
39
|
import { deflateSync } from 'node:zlib';
|
|
41
40
|
|
|
42
41
|
class Session {
|
|
@@ -5180,23 +5179,6 @@ ${typeLabels[type] || type}:`));
|
|
|
5180
5179
|
console.log(chalk.green("\n\u2705 Doctor diagnosis complete!\n"));
|
|
5181
5180
|
}
|
|
5182
5181
|
|
|
5183
|
-
async function openBrowser(url) {
|
|
5184
|
-
try {
|
|
5185
|
-
const forceOpen = process.env.FLOCKBAY_FORCE_BROWSER === "1" || process.env.FLOCKBAY_FORCE_BROWSER === "true";
|
|
5186
|
-
if (!forceOpen && (!process.stdout.isTTY || process.env.CI || process.env.HEADLESS)) {
|
|
5187
|
-
logger.debug("[browser] Headless/non-interactive environment detected, skipping browser open");
|
|
5188
|
-
return false;
|
|
5189
|
-
}
|
|
5190
|
-
logger.debug(`[browser] Attempting to open URL: ${url}`);
|
|
5191
|
-
await open(url, { wait: false });
|
|
5192
|
-
logger.debug("[browser] Browser opened successfully");
|
|
5193
|
-
return true;
|
|
5194
|
-
} catch (error) {
|
|
5195
|
-
logger.debug("[browser] Failed to open browser:", error);
|
|
5196
|
-
return false;
|
|
5197
|
-
}
|
|
5198
|
-
}
|
|
5199
|
-
|
|
5200
5182
|
async function loginWithClerkAndPairMachine() {
|
|
5201
5183
|
logger.debug("[AUTH] Starting Clerk-based CLI login + machine pairing");
|
|
5202
5184
|
const settings = await updateSettings(async (s) => {
|
|
@@ -7877,7 +7859,7 @@ function detectImageMimeTypeFromBuffer$1(buf) {
|
|
|
7877
7859
|
return null;
|
|
7878
7860
|
}
|
|
7879
7861
|
async function readFileHeader(filePath, bytes) {
|
|
7880
|
-
const fh = await open
|
|
7862
|
+
const fh = await open(filePath, "r");
|
|
7881
7863
|
try {
|
|
7882
7864
|
const maxBytes = Math.max(1, Math.floor(bytes));
|
|
7883
7865
|
const buf = Buffer.allocUnsafe(maxBytes);
|
|
@@ -13164,7 +13146,7 @@ Update: ${updateCommand}`);
|
|
|
13164
13146
|
summary: currentMetadata?.summary
|
|
13165
13147
|
}));
|
|
13166
13148
|
}
|
|
13167
|
-
await session.connectAndWait(
|
|
13149
|
+
await session.connectAndWait();
|
|
13168
13150
|
session.keepAlive(false, options.startingMode === "remote" ? "remote" : "local");
|
|
13169
13151
|
try {
|
|
13170
13152
|
logger.debug(`[START] Reporting session ${response.id} to daemon`);
|
|
@@ -13806,511 +13788,6 @@ ${chalk.bold("Usage:")}
|
|
|
13806
13788
|
`);
|
|
13807
13789
|
}
|
|
13808
13790
|
|
|
13809
|
-
const CLIENT_ID$2 = "app_EMoamEEZ73f0CkXaXp7hrann";
|
|
13810
|
-
const AUTH_BASE_URL = "https://auth.openai.com";
|
|
13811
|
-
const DEFAULT_PORT$2 = 1455;
|
|
13812
|
-
function generatePKCE$2() {
|
|
13813
|
-
const verifier = randomBytes$1(32).toString("base64url").replace(/[^a-zA-Z0-9\-._~]/g, "");
|
|
13814
|
-
const challenge = createHash("sha256").update(verifier).digest("base64url").replace(/=/g, "").replace(/\+/g, "-").replace(/\//g, "_");
|
|
13815
|
-
return { verifier, challenge };
|
|
13816
|
-
}
|
|
13817
|
-
function generateState$2() {
|
|
13818
|
-
return randomBytes$1(16).toString("hex");
|
|
13819
|
-
}
|
|
13820
|
-
function parseJWT(token) {
|
|
13821
|
-
const parts = token.split(".");
|
|
13822
|
-
if (parts.length !== 3) {
|
|
13823
|
-
throw new Error("Invalid JWT format");
|
|
13824
|
-
}
|
|
13825
|
-
const payload = Buffer.from(parts[1], "base64url").toString();
|
|
13826
|
-
return JSON.parse(payload);
|
|
13827
|
-
}
|
|
13828
|
-
async function findAvailablePort$2() {
|
|
13829
|
-
return new Promise((resolve) => {
|
|
13830
|
-
const server = createServer$1();
|
|
13831
|
-
server.listen(0, "127.0.0.1", () => {
|
|
13832
|
-
const port = server.address().port;
|
|
13833
|
-
server.close(() => resolve(port));
|
|
13834
|
-
});
|
|
13835
|
-
});
|
|
13836
|
-
}
|
|
13837
|
-
async function isPortAvailable$2(port) {
|
|
13838
|
-
return new Promise((resolve) => {
|
|
13839
|
-
const testServer = createServer$1();
|
|
13840
|
-
testServer.once("error", () => {
|
|
13841
|
-
testServer.close();
|
|
13842
|
-
resolve(false);
|
|
13843
|
-
});
|
|
13844
|
-
testServer.listen(port, "127.0.0.1", () => {
|
|
13845
|
-
testServer.close(() => resolve(true));
|
|
13846
|
-
});
|
|
13847
|
-
});
|
|
13848
|
-
}
|
|
13849
|
-
async function exchangeCodeForTokens$2(code, verifier, port) {
|
|
13850
|
-
const response = await fetch(`${AUTH_BASE_URL}/oauth/token`, {
|
|
13851
|
-
method: "POST",
|
|
13852
|
-
headers: {
|
|
13853
|
-
"Content-Type": "application/x-www-form-urlencoded"
|
|
13854
|
-
},
|
|
13855
|
-
body: new URLSearchParams({
|
|
13856
|
-
grant_type: "authorization_code",
|
|
13857
|
-
client_id: CLIENT_ID$2,
|
|
13858
|
-
code,
|
|
13859
|
-
code_verifier: verifier,
|
|
13860
|
-
redirect_uri: `http://localhost:${port}/auth/callback`
|
|
13861
|
-
})
|
|
13862
|
-
});
|
|
13863
|
-
if (!response.ok) {
|
|
13864
|
-
const error = await response.text();
|
|
13865
|
-
throw new Error(`Token exchange failed: ${error}`);
|
|
13866
|
-
}
|
|
13867
|
-
const data = await response.json();
|
|
13868
|
-
const idTokenPayload = parseJWT(data.id_token);
|
|
13869
|
-
let accountId = idTokenPayload.chatgpt_account_id;
|
|
13870
|
-
if (!accountId) {
|
|
13871
|
-
const authClaim = idTokenPayload["https://api.openai.com/auth"];
|
|
13872
|
-
if (authClaim && typeof authClaim === "object") {
|
|
13873
|
-
accountId = authClaim.chatgpt_account_id || authClaim.account_id;
|
|
13874
|
-
}
|
|
13875
|
-
}
|
|
13876
|
-
return {
|
|
13877
|
-
id_token: data.id_token,
|
|
13878
|
-
access_token: data.access_token || data.id_token,
|
|
13879
|
-
refresh_token: data.refresh_token,
|
|
13880
|
-
account_id: accountId
|
|
13881
|
-
};
|
|
13882
|
-
}
|
|
13883
|
-
async function startCallbackServer$2(state, verifier, port) {
|
|
13884
|
-
return new Promise((resolve, reject) => {
|
|
13885
|
-
const server = createServer$1(async (req, res) => {
|
|
13886
|
-
const url = new URL(req.url, `http://localhost:${port}`);
|
|
13887
|
-
if (url.pathname === "/auth/callback") {
|
|
13888
|
-
const code = url.searchParams.get("code");
|
|
13889
|
-
const receivedState = url.searchParams.get("state");
|
|
13890
|
-
if (receivedState !== state) {
|
|
13891
|
-
res.writeHead(400);
|
|
13892
|
-
res.end("Invalid state parameter");
|
|
13893
|
-
server.close();
|
|
13894
|
-
reject(new Error("Invalid state parameter"));
|
|
13895
|
-
return;
|
|
13896
|
-
}
|
|
13897
|
-
if (!code) {
|
|
13898
|
-
res.writeHead(400);
|
|
13899
|
-
res.end("No authorization code received");
|
|
13900
|
-
server.close();
|
|
13901
|
-
reject(new Error("No authorization code received"));
|
|
13902
|
-
return;
|
|
13903
|
-
}
|
|
13904
|
-
try {
|
|
13905
|
-
const tokens = await exchangeCodeForTokens$2(code, verifier, port);
|
|
13906
|
-
res.writeHead(200, { "Content-Type": "text/html" });
|
|
13907
|
-
res.end(`
|
|
13908
|
-
<html>
|
|
13909
|
-
<body style="font-family: sans-serif; padding: 20px;">
|
|
13910
|
-
<h2>\u2705 Authentication Successful!</h2>
|
|
13911
|
-
<p>You can close this window and return to your terminal.</p>
|
|
13912
|
-
<script>setTimeout(() => window.close(), 3000);<\/script>
|
|
13913
|
-
</body>
|
|
13914
|
-
</html>
|
|
13915
|
-
`);
|
|
13916
|
-
server.close();
|
|
13917
|
-
resolve(tokens);
|
|
13918
|
-
} catch (error) {
|
|
13919
|
-
res.writeHead(500);
|
|
13920
|
-
res.end("Token exchange failed");
|
|
13921
|
-
server.close();
|
|
13922
|
-
reject(error);
|
|
13923
|
-
}
|
|
13924
|
-
}
|
|
13925
|
-
});
|
|
13926
|
-
server.listen(port, "127.0.0.1", () => {
|
|
13927
|
-
});
|
|
13928
|
-
setTimeout(() => {
|
|
13929
|
-
server.close();
|
|
13930
|
-
reject(new Error("Authentication timeout"));
|
|
13931
|
-
}, 5 * 60 * 1e3);
|
|
13932
|
-
});
|
|
13933
|
-
}
|
|
13934
|
-
async function authenticateCodex() {
|
|
13935
|
-
const { verifier, challenge } = generatePKCE$2();
|
|
13936
|
-
const state = generateState$2();
|
|
13937
|
-
let port = DEFAULT_PORT$2;
|
|
13938
|
-
const portAvailable = await isPortAvailable$2(port);
|
|
13939
|
-
if (!portAvailable) {
|
|
13940
|
-
port = await findAvailablePort$2();
|
|
13941
|
-
}
|
|
13942
|
-
const serverPromise = startCallbackServer$2(state, verifier, port);
|
|
13943
|
-
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
13944
|
-
const redirect_uri = `http://localhost:${port}/auth/callback`;
|
|
13945
|
-
const params = [
|
|
13946
|
-
["response_type", "code"],
|
|
13947
|
-
["client_id", CLIENT_ID$2],
|
|
13948
|
-
["redirect_uri", redirect_uri],
|
|
13949
|
-
["scope", "openid profile email offline_access"],
|
|
13950
|
-
["code_challenge", challenge],
|
|
13951
|
-
["code_challenge_method", "S256"],
|
|
13952
|
-
["id_token_add_organizations", "true"],
|
|
13953
|
-
["codex_cli_simplified_flow", "true"],
|
|
13954
|
-
["state", state]
|
|
13955
|
-
];
|
|
13956
|
-
const queryString = params.map(([key, value]) => `${key}=${encodeURIComponent(value)}`).join("&");
|
|
13957
|
-
const authUrl = `${AUTH_BASE_URL}/oauth/authorize?${queryString}`;
|
|
13958
|
-
console.log("\u{1F4CB} Opening browser for authentication...");
|
|
13959
|
-
console.log(`If browser doesn't open, visit:
|
|
13960
|
-
${authUrl}
|
|
13961
|
-
`);
|
|
13962
|
-
await openBrowser(authUrl);
|
|
13963
|
-
const tokens = await serverPromise;
|
|
13964
|
-
console.log("\u{1F389} Authentication successful!");
|
|
13965
|
-
return tokens;
|
|
13966
|
-
}
|
|
13967
|
-
|
|
13968
|
-
const CLIENT_ID$1 = "9d1c250a-e61b-44d9-88ed-5944d1962f5e";
|
|
13969
|
-
const CLAUDE_AI_AUTHORIZE_URL = "https://claude.ai/oauth/authorize";
|
|
13970
|
-
const TOKEN_URL$1 = "https://console.anthropic.com/v1/oauth/token";
|
|
13971
|
-
const DEFAULT_PORT$1 = 54545;
|
|
13972
|
-
const SCOPE = "user:inference";
|
|
13973
|
-
function generatePKCE$1() {
|
|
13974
|
-
const verifier = randomBytes$1(32).toString("base64url").replace(/[^a-zA-Z0-9\-._~]/g, "");
|
|
13975
|
-
const challenge = createHash("sha256").update(verifier).digest("base64url").replace(/=/g, "").replace(/\+/g, "-").replace(/\//g, "_");
|
|
13976
|
-
return { verifier, challenge };
|
|
13977
|
-
}
|
|
13978
|
-
function generateState$1() {
|
|
13979
|
-
return randomBytes$1(32).toString("base64url");
|
|
13980
|
-
}
|
|
13981
|
-
async function findAvailablePort$1() {
|
|
13982
|
-
return new Promise((resolve) => {
|
|
13983
|
-
const server = createServer$1();
|
|
13984
|
-
server.listen(0, "127.0.0.1", () => {
|
|
13985
|
-
const port = server.address().port;
|
|
13986
|
-
server.close(() => resolve(port));
|
|
13987
|
-
});
|
|
13988
|
-
});
|
|
13989
|
-
}
|
|
13990
|
-
async function isPortAvailable$1(port) {
|
|
13991
|
-
return new Promise((resolve) => {
|
|
13992
|
-
const testServer = createServer$1();
|
|
13993
|
-
testServer.once("error", () => {
|
|
13994
|
-
testServer.close();
|
|
13995
|
-
resolve(false);
|
|
13996
|
-
});
|
|
13997
|
-
testServer.listen(port, "127.0.0.1", () => {
|
|
13998
|
-
testServer.close(() => resolve(true));
|
|
13999
|
-
});
|
|
14000
|
-
});
|
|
14001
|
-
}
|
|
14002
|
-
async function exchangeCodeForTokens$1(code, verifier, port, state) {
|
|
14003
|
-
const tokenResponse = await fetch(TOKEN_URL$1, {
|
|
14004
|
-
method: "POST",
|
|
14005
|
-
headers: {
|
|
14006
|
-
"Content-Type": "application/json"
|
|
14007
|
-
},
|
|
14008
|
-
body: JSON.stringify({
|
|
14009
|
-
grant_type: "authorization_code",
|
|
14010
|
-
code,
|
|
14011
|
-
redirect_uri: `http://localhost:${port}/callback`,
|
|
14012
|
-
client_id: CLIENT_ID$1,
|
|
14013
|
-
code_verifier: verifier,
|
|
14014
|
-
state
|
|
14015
|
-
})
|
|
14016
|
-
});
|
|
14017
|
-
if (!tokenResponse.ok) {
|
|
14018
|
-
throw new Error(`Token exchange failed: ${tokenResponse.statusText}`);
|
|
14019
|
-
}
|
|
14020
|
-
const tokenData = await tokenResponse.json();
|
|
14021
|
-
return {
|
|
14022
|
-
raw: tokenData,
|
|
14023
|
-
token: tokenData.access_token,
|
|
14024
|
-
expires: Date.now() + tokenData.expires_in * 1e3
|
|
14025
|
-
};
|
|
14026
|
-
}
|
|
14027
|
-
async function startCallbackServer$1(state, verifier, port) {
|
|
14028
|
-
return new Promise((resolve, reject) => {
|
|
14029
|
-
const server = createServer$1(async (req, res) => {
|
|
14030
|
-
const url = new URL(req.url, `http://localhost:${port}`);
|
|
14031
|
-
if (url.pathname === "/callback") {
|
|
14032
|
-
const code = url.searchParams.get("code");
|
|
14033
|
-
const receivedState = url.searchParams.get("state");
|
|
14034
|
-
if (receivedState !== state) {
|
|
14035
|
-
res.writeHead(400);
|
|
14036
|
-
res.end("Invalid state parameter");
|
|
14037
|
-
server.close();
|
|
14038
|
-
reject(new Error("Invalid state parameter"));
|
|
14039
|
-
return;
|
|
14040
|
-
}
|
|
14041
|
-
if (!code) {
|
|
14042
|
-
res.writeHead(400);
|
|
14043
|
-
res.end("No authorization code received");
|
|
14044
|
-
server.close();
|
|
14045
|
-
reject(new Error("No authorization code received"));
|
|
14046
|
-
return;
|
|
14047
|
-
}
|
|
14048
|
-
try {
|
|
14049
|
-
const tokens = await exchangeCodeForTokens$1(code, verifier, port, state);
|
|
14050
|
-
res.writeHead(302, {
|
|
14051
|
-
"Location": "https://console.anthropic.com/oauth/code/success?app=claude-code"
|
|
14052
|
-
});
|
|
14053
|
-
res.end();
|
|
14054
|
-
server.close();
|
|
14055
|
-
resolve(tokens);
|
|
14056
|
-
} catch (error) {
|
|
14057
|
-
res.writeHead(500);
|
|
14058
|
-
res.end("Token exchange failed");
|
|
14059
|
-
server.close();
|
|
14060
|
-
reject(error);
|
|
14061
|
-
}
|
|
14062
|
-
}
|
|
14063
|
-
});
|
|
14064
|
-
server.listen(port, "127.0.0.1", () => {
|
|
14065
|
-
});
|
|
14066
|
-
setTimeout(() => {
|
|
14067
|
-
server.close();
|
|
14068
|
-
reject(new Error("Authentication timeout"));
|
|
14069
|
-
}, 5 * 60 * 1e3);
|
|
14070
|
-
});
|
|
14071
|
-
}
|
|
14072
|
-
async function authenticateClaude() {
|
|
14073
|
-
console.log("\u{1F680} Starting Anthropic Claude authentication...");
|
|
14074
|
-
const { verifier, challenge } = generatePKCE$1();
|
|
14075
|
-
const state = generateState$1();
|
|
14076
|
-
let port = DEFAULT_PORT$1;
|
|
14077
|
-
const portAvailable = await isPortAvailable$1(port);
|
|
14078
|
-
if (!portAvailable) {
|
|
14079
|
-
console.log(`Port ${port} is in use, finding an available port...`);
|
|
14080
|
-
port = await findAvailablePort$1();
|
|
14081
|
-
}
|
|
14082
|
-
console.log(`\u{1F4E1} Using callback port: ${port}`);
|
|
14083
|
-
const serverPromise = startCallbackServer$1(state, verifier, port);
|
|
14084
|
-
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
14085
|
-
const redirect_uri = `http://localhost:${port}/callback`;
|
|
14086
|
-
const params = new URLSearchParams({
|
|
14087
|
-
code: "true",
|
|
14088
|
-
// This tells Claude.ai to show the code AND redirect
|
|
14089
|
-
client_id: CLIENT_ID$1,
|
|
14090
|
-
response_type: "code",
|
|
14091
|
-
redirect_uri,
|
|
14092
|
-
scope: SCOPE,
|
|
14093
|
-
code_challenge: challenge,
|
|
14094
|
-
code_challenge_method: "S256",
|
|
14095
|
-
state
|
|
14096
|
-
});
|
|
14097
|
-
const authUrl = `${CLAUDE_AI_AUTHORIZE_URL}?${params}`;
|
|
14098
|
-
console.log("\u{1F4CB} Opening browser for authentication...");
|
|
14099
|
-
console.log("If browser doesn't open, visit this URL:");
|
|
14100
|
-
console.log();
|
|
14101
|
-
console.log(`${authUrl}`);
|
|
14102
|
-
console.log();
|
|
14103
|
-
await openBrowser(authUrl);
|
|
14104
|
-
try {
|
|
14105
|
-
const tokens = await serverPromise;
|
|
14106
|
-
console.log("\u{1F389} Authentication successful!");
|
|
14107
|
-
console.log("\u2705 OAuth tokens received");
|
|
14108
|
-
return tokens;
|
|
14109
|
-
} catch (error) {
|
|
14110
|
-
console.error("\n\u274C Failed to authenticate with Anthropic");
|
|
14111
|
-
throw error;
|
|
14112
|
-
}
|
|
14113
|
-
}
|
|
14114
|
-
|
|
14115
|
-
const execAsync = promisify(exec);
|
|
14116
|
-
const CLIENT_ID = "681255809395-oo8ft2oprdrnp9e3aqf6av3hmdib135j.apps.googleusercontent.com";
|
|
14117
|
-
const CLIENT_SECRET = "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";
|
|
14118
|
-
const AUTHORIZE_URL = "https://accounts.google.com/o/oauth2/v2/auth";
|
|
14119
|
-
const TOKEN_URL = "https://oauth2.googleapis.com/token";
|
|
14120
|
-
const DEFAULT_PORT = 54545;
|
|
14121
|
-
const SCOPES = [
|
|
14122
|
-
"https://www.googleapis.com/auth/cloud-platform",
|
|
14123
|
-
"https://www.googleapis.com/auth/userinfo.email",
|
|
14124
|
-
"https://www.googleapis.com/auth/userinfo.profile"
|
|
14125
|
-
].join(" ");
|
|
14126
|
-
function generatePKCE() {
|
|
14127
|
-
const verifier = randomBytes$1(32).toString("base64url").replace(/[^a-zA-Z0-9\-._~]/g, "");
|
|
14128
|
-
const challenge = createHash("sha256").update(verifier).digest("base64url").replace(/=/g, "").replace(/\+/g, "-").replace(/\//g, "_");
|
|
14129
|
-
return { verifier, challenge };
|
|
14130
|
-
}
|
|
14131
|
-
function generateState() {
|
|
14132
|
-
return randomBytes$1(32).toString("hex");
|
|
14133
|
-
}
|
|
14134
|
-
async function findAvailablePort() {
|
|
14135
|
-
return new Promise((resolve) => {
|
|
14136
|
-
const server = createServer$1();
|
|
14137
|
-
server.listen(0, "127.0.0.1", () => {
|
|
14138
|
-
const port = server.address().port;
|
|
14139
|
-
server.close(() => resolve(port));
|
|
14140
|
-
});
|
|
14141
|
-
});
|
|
14142
|
-
}
|
|
14143
|
-
async function isPortAvailable(port) {
|
|
14144
|
-
return new Promise((resolve) => {
|
|
14145
|
-
const testServer = createServer$1();
|
|
14146
|
-
testServer.once("error", () => {
|
|
14147
|
-
testServer.close();
|
|
14148
|
-
resolve(false);
|
|
14149
|
-
});
|
|
14150
|
-
testServer.listen(port, "127.0.0.1", () => {
|
|
14151
|
-
testServer.close(() => resolve(true));
|
|
14152
|
-
});
|
|
14153
|
-
});
|
|
14154
|
-
}
|
|
14155
|
-
async function exchangeCodeForTokens(code, verifier, port) {
|
|
14156
|
-
const response = await fetch(TOKEN_URL, {
|
|
14157
|
-
method: "POST",
|
|
14158
|
-
headers: {
|
|
14159
|
-
"Content-Type": "application/x-www-form-urlencoded"
|
|
14160
|
-
},
|
|
14161
|
-
body: new URLSearchParams({
|
|
14162
|
-
grant_type: "authorization_code",
|
|
14163
|
-
client_id: CLIENT_ID,
|
|
14164
|
-
client_secret: CLIENT_SECRET,
|
|
14165
|
-
code,
|
|
14166
|
-
code_verifier: verifier,
|
|
14167
|
-
redirect_uri: `http://localhost:${port}/oauth2callback`
|
|
14168
|
-
})
|
|
14169
|
-
});
|
|
14170
|
-
if (!response.ok) {
|
|
14171
|
-
const error = await response.text();
|
|
14172
|
-
throw new Error(`Token exchange failed: ${error}`);
|
|
14173
|
-
}
|
|
14174
|
-
const data = await response.json();
|
|
14175
|
-
return data;
|
|
14176
|
-
}
|
|
14177
|
-
async function startCallbackServer(state, verifier, port) {
|
|
14178
|
-
return new Promise((resolve, reject) => {
|
|
14179
|
-
const server = createServer$1(async (req, res) => {
|
|
14180
|
-
const url = new URL(req.url, `http://localhost:${port}`);
|
|
14181
|
-
if (url.pathname === "/oauth2callback") {
|
|
14182
|
-
const code = url.searchParams.get("code");
|
|
14183
|
-
const receivedState = url.searchParams.get("state");
|
|
14184
|
-
const error = url.searchParams.get("error");
|
|
14185
|
-
if (error) {
|
|
14186
|
-
res.writeHead(302, {
|
|
14187
|
-
"Location": "https://developers.google.com/gemini-code-assist/auth_failure_gemini"
|
|
14188
|
-
});
|
|
14189
|
-
res.end();
|
|
14190
|
-
server.close();
|
|
14191
|
-
reject(new Error(`Authentication error: ${error}`));
|
|
14192
|
-
return;
|
|
14193
|
-
}
|
|
14194
|
-
if (receivedState !== state) {
|
|
14195
|
-
res.writeHead(400);
|
|
14196
|
-
res.end("State mismatch. Possible CSRF attack");
|
|
14197
|
-
server.close();
|
|
14198
|
-
reject(new Error("Invalid state parameter"));
|
|
14199
|
-
return;
|
|
14200
|
-
}
|
|
14201
|
-
if (!code) {
|
|
14202
|
-
res.writeHead(400);
|
|
14203
|
-
res.end("No authorization code received");
|
|
14204
|
-
server.close();
|
|
14205
|
-
reject(new Error("No authorization code received"));
|
|
14206
|
-
return;
|
|
14207
|
-
}
|
|
14208
|
-
try {
|
|
14209
|
-
const tokens = await exchangeCodeForTokens(code, verifier, port);
|
|
14210
|
-
res.writeHead(302, {
|
|
14211
|
-
"Location": "https://developers.google.com/gemini-code-assist/auth_success_gemini"
|
|
14212
|
-
});
|
|
14213
|
-
res.end();
|
|
14214
|
-
server.close();
|
|
14215
|
-
resolve(tokens);
|
|
14216
|
-
} catch (error2) {
|
|
14217
|
-
res.writeHead(500);
|
|
14218
|
-
res.end("Token exchange failed");
|
|
14219
|
-
server.close();
|
|
14220
|
-
reject(error2);
|
|
14221
|
-
}
|
|
14222
|
-
}
|
|
14223
|
-
});
|
|
14224
|
-
server.listen(port, "127.0.0.1", () => {
|
|
14225
|
-
});
|
|
14226
|
-
setTimeout(() => {
|
|
14227
|
-
server.close();
|
|
14228
|
-
reject(new Error("Authentication timeout"));
|
|
14229
|
-
}, 5 * 60 * 1e3);
|
|
14230
|
-
});
|
|
14231
|
-
}
|
|
14232
|
-
async function authenticateGemini() {
|
|
14233
|
-
console.log("\u{1F680} Starting Google Gemini authentication...");
|
|
14234
|
-
const { verifier, challenge } = generatePKCE();
|
|
14235
|
-
const state = generateState();
|
|
14236
|
-
let port = DEFAULT_PORT;
|
|
14237
|
-
const portAvailable = await isPortAvailable(port);
|
|
14238
|
-
if (!portAvailable) {
|
|
14239
|
-
console.log(`Port ${port} is in use, finding an available port...`);
|
|
14240
|
-
port = await findAvailablePort();
|
|
14241
|
-
}
|
|
14242
|
-
console.log(`\u{1F4E1} Using callback port: ${port}`);
|
|
14243
|
-
const serverPromise = startCallbackServer(state, verifier, port);
|
|
14244
|
-
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
14245
|
-
const redirect_uri = `http://localhost:${port}/oauth2callback`;
|
|
14246
|
-
const params = new URLSearchParams({
|
|
14247
|
-
client_id: CLIENT_ID,
|
|
14248
|
-
response_type: "code",
|
|
14249
|
-
redirect_uri,
|
|
14250
|
-
scope: SCOPES,
|
|
14251
|
-
access_type: "offline",
|
|
14252
|
-
// To get refresh token
|
|
14253
|
-
code_challenge: challenge,
|
|
14254
|
-
code_challenge_method: "S256",
|
|
14255
|
-
state,
|
|
14256
|
-
prompt: "consent"
|
|
14257
|
-
// Force consent to get refresh token
|
|
14258
|
-
});
|
|
14259
|
-
const authUrl = `${AUTHORIZE_URL}?${params}`;
|
|
14260
|
-
console.log("\n\u{1F4CB} Opening browser for authentication...");
|
|
14261
|
-
console.log("If browser doesn't open, visit this URL:");
|
|
14262
|
-
console.log(`
|
|
14263
|
-
${authUrl}
|
|
14264
|
-
`);
|
|
14265
|
-
const platform = process.platform;
|
|
14266
|
-
const openCommand = platform === "darwin" ? "open" : platform === "win32" ? "start" : "xdg-open";
|
|
14267
|
-
try {
|
|
14268
|
-
await execAsync(`${openCommand} "${authUrl}"`);
|
|
14269
|
-
} catch {
|
|
14270
|
-
console.log("\u26A0\uFE0F Could not open browser automatically");
|
|
14271
|
-
}
|
|
14272
|
-
try {
|
|
14273
|
-
const tokens = await serverPromise;
|
|
14274
|
-
console.log("\n\u{1F389} Authentication successful!");
|
|
14275
|
-
console.log("\u2705 OAuth tokens received");
|
|
14276
|
-
return tokens;
|
|
14277
|
-
} catch (error) {
|
|
14278
|
-
console.error("\n\u274C Failed to authenticate with Google");
|
|
14279
|
-
throw error;
|
|
14280
|
-
}
|
|
14281
|
-
}
|
|
14282
|
-
|
|
14283
|
-
async function syncCodexCliAuth(tokens) {
|
|
14284
|
-
const authFilePath = path__default.join(os__default.homedir(), ".codex", "auth.json");
|
|
14285
|
-
const authDir = path__default.dirname(authFilePath);
|
|
14286
|
-
let previousAccountId;
|
|
14287
|
-
let previousApiKey = null;
|
|
14288
|
-
try {
|
|
14289
|
-
const existingRaw = await fs$1.readFile(authFilePath, "utf8");
|
|
14290
|
-
const existing = JSON.parse(existingRaw);
|
|
14291
|
-
previousAccountId = existing?.tokens?.account_id;
|
|
14292
|
-
previousApiKey = typeof existing?.OPENAI_API_KEY === "string" ? existing.OPENAI_API_KEY : null;
|
|
14293
|
-
} catch {
|
|
14294
|
-
}
|
|
14295
|
-
await fs$1.mkdir(authDir, { recursive: true });
|
|
14296
|
-
const next = {
|
|
14297
|
-
OPENAI_API_KEY: previousApiKey,
|
|
14298
|
-
tokens: {
|
|
14299
|
-
id_token: tokens.id_token,
|
|
14300
|
-
access_token: tokens.access_token,
|
|
14301
|
-
refresh_token: tokens.refresh_token,
|
|
14302
|
-
account_id: tokens.account_id
|
|
14303
|
-
},
|
|
14304
|
-
last_refresh: (/* @__PURE__ */ new Date()).toISOString()
|
|
14305
|
-
};
|
|
14306
|
-
await fs$1.writeFile(authFilePath, JSON.stringify(next, null, 2) + "\n", "utf8");
|
|
14307
|
-
return {
|
|
14308
|
-
authFilePath,
|
|
14309
|
-
previousAccountId,
|
|
14310
|
-
newAccountId: tokens.account_id
|
|
14311
|
-
};
|
|
14312
|
-
}
|
|
14313
|
-
|
|
14314
13791
|
async function handleConnectCommand(args) {
|
|
14315
13792
|
const subcommand = args[0];
|
|
14316
13793
|
const flags = args.slice(1);
|
|
@@ -14650,7 +14127,8 @@ async function runSmokeForAgent(agent, args) {
|
|
|
14650
14127
|
const skipUnreal = !readFlag(args, "--with-unreal");
|
|
14651
14128
|
const baseDir = readArgValue$2(args, "--directory") || readArgValue$2(args, "--dir");
|
|
14652
14129
|
const timeoutMsRaw = readArgValue$2(args, "--timeout-ms");
|
|
14653
|
-
const
|
|
14130
|
+
const defaultTimeoutMs = process.platform === "win32" ? 24e4 : 9e4;
|
|
14131
|
+
const timeoutMs = timeoutMsRaw && Number.isFinite(Number(timeoutMsRaw)) ? Number(timeoutMsRaw) : defaultTimeoutMs;
|
|
14654
14132
|
let sessionId;
|
|
14655
14133
|
let directory;
|
|
14656
14134
|
let sessionClient = null;
|
|
@@ -14698,7 +14176,7 @@ Update: ${updateCommand}`);
|
|
|
14698
14176
|
throw new Error(msg);
|
|
14699
14177
|
}
|
|
14700
14178
|
sessionClient = api.sessionSyncClient(session);
|
|
14701
|
-
await sessionClient.connectAndWait(
|
|
14179
|
+
await sessionClient.connectAndWait();
|
|
14702
14180
|
await ensureSessionActive(api, sessionId, 25e3);
|
|
14703
14181
|
const permissionMode = permissionModeForAgent(agent);
|
|
14704
14182
|
scenarios.push(await runScenario("basic-message", async () => {
|
|
@@ -14803,7 +14281,7 @@ Options:
|
|
|
14803
14281
|
--agent, -a Run a single agent
|
|
14804
14282
|
--agents Comma-separated list of agents
|
|
14805
14283
|
--directory, --dir Directory to run the session in (defaults to a temp folder)
|
|
14806
|
-
--timeout-ms Per-scenario timeout (default 90000)
|
|
14284
|
+
--timeout-ms Per-scenario timeout (default 90000; Windows default 240000)
|
|
14807
14285
|
--keep Do not stop session or delete temp dir
|
|
14808
14286
|
--json Write results JSON to a file
|
|
14809
14287
|
--with-unreal Allow Unreal MCP prompts (off by default)
|
|
@@ -14867,6 +14345,18 @@ function splitList(value) {
|
|
|
14867
14345
|
function ensureDir(dir) {
|
|
14868
14346
|
fs__default.mkdirSync(dir, { recursive: true });
|
|
14869
14347
|
}
|
|
14348
|
+
function canWriteDir(dir) {
|
|
14349
|
+
const root = (dir || "").trim();
|
|
14350
|
+
if (!root) return false;
|
|
14351
|
+
try {
|
|
14352
|
+
const tmp = path__default.join(root, `.__flockbay_write_test_${Date.now()}_${Math.random().toString(16).slice(2)}.tmp`);
|
|
14353
|
+
fs__default.writeFileSync(tmp, "ok", "utf8");
|
|
14354
|
+
fs__default.unlinkSync(tmp);
|
|
14355
|
+
return true;
|
|
14356
|
+
} catch {
|
|
14357
|
+
return false;
|
|
14358
|
+
}
|
|
14359
|
+
}
|
|
14870
14360
|
function detectImageMimeTypeFromBuffer(buf) {
|
|
14871
14361
|
if (!buf || buf.length < 12) return null;
|
|
14872
14362
|
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) {
|
|
@@ -14885,7 +14375,7 @@ async function waitForUnreal(options) {
|
|
|
14885
14375
|
while (Date.now() - startedAt < options.timeoutMs) {
|
|
14886
14376
|
try {
|
|
14887
14377
|
const res = await sendUnrealMcpTcpCommand({ type: "ping", host: options.host, port: options.port, timeoutMs: 2e3 });
|
|
14888
|
-
const msg = typeof res?.message === "string" ? res.message : null;
|
|
14378
|
+
const msg = typeof res?.message === "string" ? res.message : typeof res?.result?.message === "string" ? res.result.message : null;
|
|
14889
14379
|
if (msg === "pong") return { ok: true };
|
|
14890
14380
|
} catch (err) {
|
|
14891
14381
|
lastErr = err instanceof Error ? err.message : String(err);
|
|
@@ -14933,22 +14423,23 @@ async function runRuntimeSmoke(options) {
|
|
|
14933
14423
|
}
|
|
14934
14424
|
try {
|
|
14935
14425
|
const pluginInfo = await sendUnrealMcpTcpCommand({ type: "get_plugin_info", host: options.host, port: options.port, timeoutMs: options.timeoutMs });
|
|
14936
|
-
const
|
|
14937
|
-
const
|
|
14938
|
-
const
|
|
14939
|
-
const
|
|
14940
|
-
const
|
|
14941
|
-
|
|
14426
|
+
const pluginInfoResult = pluginInfo?.result && typeof pluginInfo.result === "object" ? pluginInfo.result : pluginInfo;
|
|
14427
|
+
const createdBy = String(pluginInfoResult?.createdBy || "").trim();
|
|
14428
|
+
const friendlyName = String(pluginInfoResult?.friendlyName || "").trim();
|
|
14429
|
+
const baseDir = String(pluginInfoResult?.baseDir || "").trim();
|
|
14430
|
+
const schemaVersion = Number(pluginInfoResult?.schemaVersion);
|
|
14431
|
+
const commands = Array.isArray(pluginInfoResult?.commands) ? pluginInfoResult.commands.filter((c) => typeof c === "string") : [];
|
|
14432
|
+
if (friendlyName !== "Flockbay MCP" || createdBy !== "Respaced Inc.") {
|
|
14942
14433
|
return {
|
|
14943
14434
|
ok: false,
|
|
14944
14435
|
error: `Unexpected plugin identity loaded by Unreal.
|
|
14945
14436
|
friendlyName=${friendlyName || "(missing)"} createdBy=${createdBy || "(missing)"}
|
|
14946
14437
|
baseDir=${baseDir || "(missing)"}
|
|
14947
|
-
Expected FriendlyName="
|
|
14438
|
+
Expected FriendlyName="Flockbay MCP" CreatedBy="Respaced Inc."`
|
|
14948
14439
|
};
|
|
14949
14440
|
}
|
|
14950
14441
|
if (!Number.isFinite(schemaVersion) || schemaVersion <= 0) {
|
|
14951
|
-
return { ok: false, error: `Invalid schemaVersion from get_plugin_info: ${String(
|
|
14442
|
+
return { ok: false, error: `Invalid schemaVersion from get_plugin_info: ${String(pluginInfoResult?.schemaVersion)}` };
|
|
14952
14443
|
}
|
|
14953
14444
|
const requireCommands = [
|
|
14954
14445
|
"ping",
|
|
@@ -14968,7 +14459,8 @@ Expected FriendlyName="Unreal MCP Plugin" CreatedBy="Respaced Inc."`
|
|
|
14968
14459
|
return { ok: false, error: `Missing required commands in this Unreal MCP build: ${missing.join(", ")}` };
|
|
14969
14460
|
}
|
|
14970
14461
|
const playStatus0 = await sendUnrealMcpTcpCommand({ type: "get_play_in_editor_status", host: options.host, port: options.port, timeoutMs: options.timeoutMs });
|
|
14971
|
-
const
|
|
14462
|
+
const playStatusResult = playStatus0?.result && typeof playStatus0.result === "object" ? playStatus0.result : playStatus0;
|
|
14463
|
+
const isPlaying = Boolean(playStatusResult?.isPlaySessionInProgress);
|
|
14972
14464
|
if (isPlaying) {
|
|
14973
14465
|
await sendUnrealMcpTcpCommand({ type: "stop_play_in_editor", host: options.host, port: options.port, timeoutMs: options.timeoutMs });
|
|
14974
14466
|
}
|
|
@@ -14995,7 +14487,9 @@ Expected FriendlyName="Unreal MCP Plugin" CreatedBy="Respaced Inc."`
|
|
|
14995
14487
|
const bpName = `BP_Smoke_${Date.now()}`;
|
|
14996
14488
|
await sendUnrealMcpTcpCommand({
|
|
14997
14489
|
type: "create_blueprint",
|
|
14998
|
-
|
|
14490
|
+
// Important: pass only the name so the plugin's default (/Game/Blueprints/) is used.
|
|
14491
|
+
// The plugin's "compile_blueprint" name-only lookup searches /Game/Blueprints by design.
|
|
14492
|
+
params: { name: bpName, parent_class: "Actor" },
|
|
14999
14493
|
host: options.host,
|
|
15000
14494
|
port: options.port,
|
|
15001
14495
|
timeoutMs: Math.max(options.timeoutMs, 2e4)
|
|
@@ -15062,26 +14556,73 @@ async function runUnrealMcpMatrixSmoke(args) {
|
|
|
15062
14556
|
if (!engineRoot) continue;
|
|
15063
14557
|
console.log(chalk.bold(`== Engine: ${engineRoot} ==`));
|
|
15064
14558
|
if (doBuild) {
|
|
15065
|
-
|
|
15066
|
-
const
|
|
15067
|
-
|
|
15068
|
-
|
|
15069
|
-
|
|
14559
|
+
const enginePluginsDir = path__default.join(engineRoot, "Engine", "Plugins");
|
|
14560
|
+
const enginePluginDir = path__default.join(enginePluginsDir, "FlockbayMCP");
|
|
14561
|
+
const enginePluginUplugin = path__default.join(enginePluginDir, "FlockbayMCP.uplugin");
|
|
14562
|
+
const enginePluginHasBinaries = fs__default.existsSync(path__default.join(enginePluginDir, "Binaries"));
|
|
14563
|
+
const projectUprojectPath = project ? path__default.resolve(project) : null;
|
|
14564
|
+
if (fs__default.existsSync(enginePluginUplugin) && enginePluginHasBinaries) {
|
|
14565
|
+
console.log(chalk.green(`Build: engine plugin already installed + built (${enginePluginDir})`));
|
|
14566
|
+
} else if (canWriteDir(enginePluginsDir)) {
|
|
14567
|
+
console.log(chalk.cyan("Build: installing Flockbay MCP plugin sources into the engine (folder: FlockbayMCP)..."));
|
|
14568
|
+
const installed = installUnrealMcpPluginToEngine(engineRoot);
|
|
14569
|
+
if (!installed.ok) {
|
|
14570
|
+
failures.push({ engineRoot, phase: "build", error: installed.errorMessage });
|
|
14571
|
+
console.log(chalk.red(`Build: failed (install)
|
|
15070
14572
|
${installed.errorMessage}
|
|
15071
14573
|
`));
|
|
15072
|
-
|
|
15073
|
-
|
|
15074
|
-
|
|
15075
|
-
|
|
15076
|
-
|
|
15077
|
-
|
|
15078
|
-
|
|
15079
|
-
|
|
14574
|
+
if (!doRuntime) continue;
|
|
14575
|
+
} else {
|
|
14576
|
+
console.log(chalk.green(`Build: sources installed to ${installed.destDir}`));
|
|
14577
|
+
console.log(chalk.cyan("Build: compiling plugin via RunUAT BuildPlugin..."));
|
|
14578
|
+
const built = await buildAndInstallUnrealMcpPlugin({ engineRoot, flockbayHomeDir: configuration.flockbayHomeDir });
|
|
14579
|
+
if (!built.ok) {
|
|
14580
|
+
failures.push({ engineRoot, phase: "build", error: built.errorMessage });
|
|
14581
|
+
console.log(chalk.red(`Build: failed
|
|
15080
14582
|
${built.errorMessage}
|
|
15081
14583
|
`));
|
|
14584
|
+
} else {
|
|
14585
|
+
console.log(chalk.green(`Build: ok (log: ${built.buildLogPath})`));
|
|
14586
|
+
}
|
|
14587
|
+
}
|
|
14588
|
+
} else if (projectUprojectPath) {
|
|
14589
|
+
console.log(chalk.cyan("Build: engine install not writable; installing plugin into the project instead..."));
|
|
14590
|
+
const installedProject = installUnrealMcpPluginToProject(projectUprojectPath);
|
|
14591
|
+
if (!installedProject.ok) {
|
|
14592
|
+
failures.push({ engineRoot, phase: "build", error: installedProject.errorMessage });
|
|
14593
|
+
console.log(chalk.red(`Build: failed (project install)
|
|
14594
|
+
${installedProject.errorMessage}
|
|
14595
|
+
`));
|
|
14596
|
+
if (!doRuntime) continue;
|
|
15082
14597
|
} else {
|
|
15083
|
-
console.log(chalk.green(`Build:
|
|
14598
|
+
console.log(chalk.green(`Build: sources installed to ${installedProject.destDir}`));
|
|
14599
|
+
console.log(chalk.cyan("Build: compiling plugin via RunUAT BuildPlugin..."));
|
|
14600
|
+
const built = await buildAndInstallUnrealMcpPlugin({
|
|
14601
|
+
engineRoot,
|
|
14602
|
+
flockbayHomeDir: configuration.flockbayHomeDir,
|
|
14603
|
+
pluginDir: installedProject.destDir
|
|
14604
|
+
});
|
|
14605
|
+
if (!built.ok) {
|
|
14606
|
+
failures.push({ engineRoot, phase: "build", error: built.errorMessage });
|
|
14607
|
+
console.log(chalk.red(`Build: failed
|
|
14608
|
+
${built.errorMessage}
|
|
14609
|
+
`));
|
|
14610
|
+
} else {
|
|
14611
|
+
console.log(chalk.green(`Build: ok (log: ${built.buildLogPath})`));
|
|
14612
|
+
}
|
|
15084
14613
|
}
|
|
14614
|
+
} else {
|
|
14615
|
+
const error = `Engine plugins folder is not writable:
|
|
14616
|
+
${enginePluginsDir}
|
|
14617
|
+
|
|
14618
|
+
Fix:
|
|
14619
|
+
- Re-run with --project "<path-to-your-project>.uproject" so we can install the plugin into the project (no admin), OR
|
|
14620
|
+
- Run the installer with Windows admin permissions.`;
|
|
14621
|
+
failures.push({ engineRoot, phase: "build", error });
|
|
14622
|
+
console.log(chalk.red(`Build: failed
|
|
14623
|
+
${error}
|
|
14624
|
+
`));
|
|
14625
|
+
if (!doRuntime) continue;
|
|
15085
14626
|
}
|
|
15086
14627
|
}
|
|
15087
14628
|
if (doRuntime) {
|
|
@@ -15540,7 +15081,7 @@ async function authAndSetupMachineIfNeeded() {
|
|
|
15540
15081
|
process.exit(1);
|
|
15541
15082
|
}
|
|
15542
15083
|
try {
|
|
15543
|
-
const { migrateUnrealMcpToFlockbayMcp } = await import('./migratePlugin-
|
|
15084
|
+
const { migrateUnrealMcpToFlockbayMcp } = await import('./migratePlugin-CCepAUqm.mjs');
|
|
15544
15085
|
const result = migrateUnrealMcpToFlockbayMcp({
|
|
15545
15086
|
engineRoot,
|
|
15546
15087
|
projectUprojectPath: project || void 0,
|
|
@@ -15679,7 +15220,7 @@ ${engineRoot}`, {
|
|
|
15679
15220
|
} else if (subcommand === "codex") {
|
|
15680
15221
|
try {
|
|
15681
15222
|
await chdirToNearestUprojectRootIfPresent();
|
|
15682
|
-
const { runCodex } = await import('./runCodex-
|
|
15223
|
+
const { runCodex } = await import('./runCodex-7GeFJuM_.mjs');
|
|
15683
15224
|
let startedBy = void 0;
|
|
15684
15225
|
let sessionId = void 0;
|
|
15685
15226
|
for (let i = 1; i < args.length; i++) {
|
|
@@ -15781,7 +15322,7 @@ ${engineRoot}`, {
|
|
|
15781
15322
|
}
|
|
15782
15323
|
try {
|
|
15783
15324
|
await chdirToNearestUprojectRootIfPresent();
|
|
15784
|
-
const { runGemini } = await import('./runGemini-
|
|
15325
|
+
const { runGemini } = await import('./runGemini-9LGJaWVk.mjs');
|
|
15785
15326
|
let startedBy = void 0;
|
|
15786
15327
|
let sessionId = void 0;
|
|
15787
15328
|
for (let i = 1; i < args.length; i++) {
|