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.
@@ -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-2Bs_CNcy.cjs');
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-hc8sYVfl.cjs', document.baseURI).href)));
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(15e3);
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 timeoutMs = timeoutMsRaw && Number.isFinite(Number(timeoutMsRaw)) ? Number(timeoutMsRaw) : 9e4;
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(15e3);
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 createdBy = String(pluginInfo?.createdBy || "").trim();
14959
- const friendlyName = String(pluginInfo?.friendlyName || "").trim();
14960
- const baseDir = String(pluginInfo?.baseDir || "").trim();
14961
- const schemaVersion = Number(pluginInfo?.schemaVersion);
14962
- const commands = Array.isArray(pluginInfo?.commands) ? pluginInfo.commands.filter((c) => typeof c === "string") : [];
14963
- if (friendlyName !== "Unreal MCP Plugin" || createdBy !== "Respaced Inc.") {
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="Unreal MCP Plugin" CreatedBy="Respaced Inc."`
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(pluginInfo?.schemaVersion)}` };
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 isPlaying = Boolean(playStatus0?.isPlaySessionInProgress);
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
- params: { name: bpName, path: "/Game/FlockbaySmoke/", parent_class: "Actor" },
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
- console.log(chalk.cyan("Build: installing Flockbay MCP plugin sources (folder: FlockbayMCP)..."));
15088
- const installed = types.installUnrealMcpPluginToEngine(engineRoot);
15089
- if (!installed.ok) {
15090
- failures.push({ engineRoot, phase: "build", error: installed.errorMessage });
15091
- console.log(chalk.red(`Build: failed (install)
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
- if (!doRuntime) continue;
15095
- } else {
15096
- console.log(chalk.green(`Build: sources installed to ${installed.destDir}`));
15097
- console.log(chalk.cyan("Build: compiling plugin via RunUAT BuildPlugin..."));
15098
- const built = await types.buildAndInstallUnrealMcpPlugin({ engineRoot, flockbayHomeDir: types.configuration.flockbayHomeDir });
15099
- if (!built.ok) {
15100
- failures.push({ engineRoot, phase: "build", error: built.errorMessage });
15101
- console.log(chalk.red(`Build: failed
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: ok (log: ${built.buildLogPath})`));
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-DNHywpj6.cjs'); });
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-B3Qjwkr6.cjs'); });
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-BED5hBNz.cjs'); });
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++) {