flockbay 0.10.41 → 0.10.43

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-2vFbaIZJ.cjs');
6
+ var types = require('./types-DTy-RPNv.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,7 +15,6 @@ 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');
@@ -34,6 +33,7 @@ var fastifyTypeProviderZod = require('fastify-type-provider-zod');
34
33
  var mcp_js = require('@modelcontextprotocol/sdk/server/mcp.js');
35
34
  var node_http = require('node:http');
36
35
  var streamableHttp_js = require('@modelcontextprotocol/sdk/server/streamableHttp.js');
36
+ var node_events = require('node:events');
37
37
  require('tweetnacl');
38
38
  var node_zlib = require('node:zlib');
39
39
 
@@ -1316,7 +1316,7 @@ function buildDaemonSafeEnv(baseEnv, binPath) {
1316
1316
  env[pathKey] = [...prepend, ...existingParts].join(pathSep);
1317
1317
  return env;
1318
1318
  }
1319
- const __filename$1 = node_url.fileURLToPath((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index-X_0a6dpP.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-Bih-iANW.cjs', document.baseURI).href)));
1320
1320
  const __dirname$1 = path.join(__filename$1, "..");
1321
1321
  function getGlobalClaudeVersion(claudeExecutable) {
1322
1322
  try {
@@ -5292,8 +5292,10 @@ function spawnFlockbayCLI(args, options = {}) {
5292
5292
  const entrypoint = fs.existsSync(distEntrypoint) ? distEntrypoint : devEntrypoint;
5293
5293
  const useTsx = entrypoint.endsWith(".ts");
5294
5294
  const desiredCwd = "cwd" in options && typeof options.cwd === "string" ? options.cwd : process$1.cwd();
5295
+ const windowsHide = typeof options?.windowsHide === "boolean" ? Boolean(options.windowsHide) : process$1.platform === "win32";
5295
5296
  const spawnOptions = {
5296
5297
  ...options,
5298
+ windowsHide,
5297
5299
  ...useTsx ? { cwd: projectRoot } : {},
5298
5300
  env: {
5299
5301
  ...process$1.env,
@@ -7035,7 +7037,7 @@ ${scriptCandidates.map((p) => `- ${p}`).join("\n")}
7035
7037
  logStream.write(`args: ${JSON.stringify(buildArgs)}
7036
7038
 
7037
7039
  `);
7038
- const child = osPlatform === "win32" ? node_child_process.spawn("cmd.exe", ["/c", script, ...buildArgs], { stdio: ["ignore", "pipe", "pipe"] }) : node_child_process.spawn(script, buildArgs, { stdio: ["ignore", "pipe", "pipe"] });
7040
+ const child = osPlatform === "win32" ? node_child_process.spawn("cmd.exe", ["/c", script, ...buildArgs], { stdio: ["ignore", "pipe", "pipe"], windowsHide: true }) : node_child_process.spawn(script, buildArgs, { stdio: ["ignore", "pipe", "pipe"] });
7039
7041
  let combinedTail = "";
7040
7042
  const appendTail = (chunk) => {
7041
7043
  combinedTail += chunk.toString("utf8");
@@ -13168,7 +13170,7 @@ Update: ${updateCommand}`);
13168
13170
  summary: currentMetadata?.summary
13169
13171
  }));
13170
13172
  }
13171
- await session.connectAndWait(15e3);
13173
+ await session.connectAndWait();
13172
13174
  session.keepAlive(false, options.startingMode === "remote" ? "remote" : "local");
13173
13175
  try {
13174
13176
  types.logger.debug(`[START] Reporting session ${response.id} to daemon`);
@@ -14149,7 +14151,8 @@ async function runSmokeForAgent(agent, args) {
14149
14151
  const skipUnreal = !readFlag(args, "--with-unreal");
14150
14152
  const baseDir = readArgValue$2(args, "--directory") || readArgValue$2(args, "--dir");
14151
14153
  const timeoutMsRaw = readArgValue$2(args, "--timeout-ms");
14152
- const timeoutMs = timeoutMsRaw && Number.isFinite(Number(timeoutMsRaw)) ? Number(timeoutMsRaw) : 9e4;
14154
+ const defaultTimeoutMs = process.platform === "win32" ? 24e4 : 9e4;
14155
+ const timeoutMs = timeoutMsRaw && Number.isFinite(Number(timeoutMsRaw)) ? Number(timeoutMsRaw) : defaultTimeoutMs;
14153
14156
  let sessionId;
14154
14157
  let directory;
14155
14158
  let sessionClient = null;
@@ -14197,7 +14200,7 @@ Update: ${updateCommand}`);
14197
14200
  throw new Error(msg);
14198
14201
  }
14199
14202
  sessionClient = api.sessionSyncClient(session);
14200
- await sessionClient.connectAndWait(15e3);
14203
+ await sessionClient.connectAndWait();
14201
14204
  await ensureSessionActive(api, sessionId, 25e3);
14202
14205
  const permissionMode = permissionModeForAgent(agent);
14203
14206
  scenarios.push(await runScenario("basic-message", async () => {
@@ -14302,7 +14305,7 @@ Options:
14302
14305
  --agent, -a Run a single agent
14303
14306
  --agents Comma-separated list of agents
14304
14307
  --directory, --dir Directory to run the session in (defaults to a temp folder)
14305
- --timeout-ms Per-scenario timeout (default 90000)
14308
+ --timeout-ms Per-scenario timeout (default 90000; Windows default 240000)
14306
14309
  --keep Do not stop session or delete temp dir
14307
14310
  --json Write results JSON to a file
14308
14311
  --with-unreal Allow Unreal MCP prompts (off by default)
@@ -14366,6 +14369,18 @@ function splitList(value) {
14366
14369
  function ensureDir(dir) {
14367
14370
  fs.mkdirSync(dir, { recursive: true });
14368
14371
  }
14372
+ function canWriteDir(dir) {
14373
+ const root = (dir || "").trim();
14374
+ if (!root) return false;
14375
+ try {
14376
+ const tmp = path.join(root, `.__flockbay_write_test_${Date.now()}_${Math.random().toString(16).slice(2)}.tmp`);
14377
+ fs.writeFileSync(tmp, "ok", "utf8");
14378
+ fs.unlinkSync(tmp);
14379
+ return true;
14380
+ } catch {
14381
+ return false;
14382
+ }
14383
+ }
14369
14384
  function detectImageMimeTypeFromBuffer(buf) {
14370
14385
  if (!buf || buf.length < 12) return null;
14371
14386
  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) {
@@ -14384,7 +14399,7 @@ async function waitForUnreal(options) {
14384
14399
  while (Date.now() - startedAt < options.timeoutMs) {
14385
14400
  try {
14386
14401
  const res = await types.sendUnrealMcpTcpCommand({ type: "ping", host: options.host, port: options.port, timeoutMs: 2e3 });
14387
- const msg = typeof res?.message === "string" ? res.message : null;
14402
+ const msg = typeof res?.message === "string" ? res.message : typeof res?.result?.message === "string" ? res.result.message : null;
14388
14403
  if (msg === "pong") return { ok: true };
14389
14404
  } catch (err) {
14390
14405
  lastErr = err instanceof Error ? err.message : String(err);
@@ -14432,22 +14447,23 @@ async function runRuntimeSmoke(options) {
14432
14447
  }
14433
14448
  try {
14434
14449
  const pluginInfo = await types.sendUnrealMcpTcpCommand({ type: "get_plugin_info", host: options.host, port: options.port, timeoutMs: options.timeoutMs });
14435
- const createdBy = String(pluginInfo?.createdBy || "").trim();
14436
- const friendlyName = String(pluginInfo?.friendlyName || "").trim();
14437
- const baseDir = String(pluginInfo?.baseDir || "").trim();
14438
- const schemaVersion = Number(pluginInfo?.schemaVersion);
14439
- const commands = Array.isArray(pluginInfo?.commands) ? pluginInfo.commands.filter((c) => typeof c === "string") : [];
14440
- if (friendlyName !== "Unreal MCP Plugin" || createdBy !== "Respaced Inc.") {
14450
+ const pluginInfoResult = pluginInfo?.result && typeof pluginInfo.result === "object" ? pluginInfo.result : pluginInfo;
14451
+ const createdBy = String(pluginInfoResult?.createdBy || "").trim();
14452
+ const friendlyName = String(pluginInfoResult?.friendlyName || "").trim();
14453
+ const baseDir = String(pluginInfoResult?.baseDir || "").trim();
14454
+ const schemaVersion = Number(pluginInfoResult?.schemaVersion);
14455
+ const commands = Array.isArray(pluginInfoResult?.commands) ? pluginInfoResult.commands.filter((c) => typeof c === "string") : [];
14456
+ if (friendlyName !== "Flockbay MCP" || createdBy !== "Respaced Inc.") {
14441
14457
  return {
14442
14458
  ok: false,
14443
14459
  error: `Unexpected plugin identity loaded by Unreal.
14444
14460
  friendlyName=${friendlyName || "(missing)"} createdBy=${createdBy || "(missing)"}
14445
14461
  baseDir=${baseDir || "(missing)"}
14446
- Expected FriendlyName="Unreal MCP Plugin" CreatedBy="Respaced Inc."`
14462
+ Expected FriendlyName="Flockbay MCP" CreatedBy="Respaced Inc."`
14447
14463
  };
14448
14464
  }
14449
14465
  if (!Number.isFinite(schemaVersion) || schemaVersion <= 0) {
14450
- return { ok: false, error: `Invalid schemaVersion from get_plugin_info: ${String(pluginInfo?.schemaVersion)}` };
14466
+ return { ok: false, error: `Invalid schemaVersion from get_plugin_info: ${String(pluginInfoResult?.schemaVersion)}` };
14451
14467
  }
14452
14468
  const requireCommands = [
14453
14469
  "ping",
@@ -14467,7 +14483,8 @@ Expected FriendlyName="Unreal MCP Plugin" CreatedBy="Respaced Inc."`
14467
14483
  return { ok: false, error: `Missing required commands in this Unreal MCP build: ${missing.join(", ")}` };
14468
14484
  }
14469
14485
  const playStatus0 = await types.sendUnrealMcpTcpCommand({ type: "get_play_in_editor_status", host: options.host, port: options.port, timeoutMs: options.timeoutMs });
14470
- const isPlaying = Boolean(playStatus0?.isPlaySessionInProgress);
14486
+ const playStatusResult = playStatus0?.result && typeof playStatus0.result === "object" ? playStatus0.result : playStatus0;
14487
+ const isPlaying = Boolean(playStatusResult?.isPlaySessionInProgress);
14471
14488
  if (isPlaying) {
14472
14489
  await types.sendUnrealMcpTcpCommand({ type: "stop_play_in_editor", host: options.host, port: options.port, timeoutMs: options.timeoutMs });
14473
14490
  }
@@ -14494,7 +14511,9 @@ Expected FriendlyName="Unreal MCP Plugin" CreatedBy="Respaced Inc."`
14494
14511
  const bpName = `BP_Smoke_${Date.now()}`;
14495
14512
  await types.sendUnrealMcpTcpCommand({
14496
14513
  type: "create_blueprint",
14497
- params: { name: bpName, path: "/Game/FlockbaySmoke/", parent_class: "Actor" },
14514
+ // Important: pass only the name so the plugin's default (/Game/Blueprints/) is used.
14515
+ // The plugin's "compile_blueprint" name-only lookup searches /Game/Blueprints by design.
14516
+ params: { name: bpName, parent_class: "Actor" },
14498
14517
  host: options.host,
14499
14518
  port: options.port,
14500
14519
  timeoutMs: Math.max(options.timeoutMs, 2e4)
@@ -14561,26 +14580,73 @@ async function runUnrealMcpMatrixSmoke(args) {
14561
14580
  if (!engineRoot) continue;
14562
14581
  console.log(chalk.bold(`== Engine: ${engineRoot} ==`));
14563
14582
  if (doBuild) {
14564
- console.log(chalk.cyan("Build: installing Flockbay MCP plugin sources (folder: FlockbayMCP)..."));
14565
- const installed = types.installUnrealMcpPluginToEngine(engineRoot);
14566
- if (!installed.ok) {
14567
- failures.push({ engineRoot, phase: "build", error: installed.errorMessage });
14568
- console.log(chalk.red(`Build: failed (install)
14583
+ const enginePluginsDir = path.join(engineRoot, "Engine", "Plugins");
14584
+ const enginePluginDir = path.join(enginePluginsDir, "FlockbayMCP");
14585
+ const enginePluginUplugin = path.join(enginePluginDir, "FlockbayMCP.uplugin");
14586
+ const enginePluginHasBinaries = fs.existsSync(path.join(enginePluginDir, "Binaries"));
14587
+ const projectUprojectPath = project ? path.resolve(project) : null;
14588
+ if (fs.existsSync(enginePluginUplugin) && enginePluginHasBinaries) {
14589
+ console.log(chalk.green(`Build: engine plugin already installed + built (${enginePluginDir})`));
14590
+ } else if (canWriteDir(enginePluginsDir)) {
14591
+ console.log(chalk.cyan("Build: installing Flockbay MCP plugin sources into the engine (folder: FlockbayMCP)..."));
14592
+ const installed = types.installUnrealMcpPluginToEngine(engineRoot);
14593
+ if (!installed.ok) {
14594
+ failures.push({ engineRoot, phase: "build", error: installed.errorMessage });
14595
+ console.log(chalk.red(`Build: failed (install)
14569
14596
  ${installed.errorMessage}
14570
14597
  `));
14571
- if (!doRuntime) continue;
14572
- } else {
14573
- console.log(chalk.green(`Build: sources installed to ${installed.destDir}`));
14574
- console.log(chalk.cyan("Build: compiling plugin via RunUAT BuildPlugin..."));
14575
- const built = await types.buildAndInstallUnrealMcpPlugin({ engineRoot, flockbayHomeDir: types.configuration.flockbayHomeDir });
14576
- if (!built.ok) {
14577
- failures.push({ engineRoot, phase: "build", error: built.errorMessage });
14578
- console.log(chalk.red(`Build: failed
14598
+ if (!doRuntime) continue;
14599
+ } else {
14600
+ console.log(chalk.green(`Build: sources installed to ${installed.destDir}`));
14601
+ console.log(chalk.cyan("Build: compiling plugin via RunUAT BuildPlugin..."));
14602
+ const built = await types.buildAndInstallUnrealMcpPlugin({ engineRoot, flockbayHomeDir: types.configuration.flockbayHomeDir });
14603
+ if (!built.ok) {
14604
+ failures.push({ engineRoot, phase: "build", error: built.errorMessage });
14605
+ console.log(chalk.red(`Build: failed
14579
14606
  ${built.errorMessage}
14580
14607
  `));
14608
+ } else {
14609
+ console.log(chalk.green(`Build: ok (log: ${built.buildLogPath})`));
14610
+ }
14611
+ }
14612
+ } else if (projectUprojectPath) {
14613
+ console.log(chalk.cyan("Build: engine install not writable; installing plugin into the project instead..."));
14614
+ const installedProject = types.installUnrealMcpPluginToProject(projectUprojectPath);
14615
+ if (!installedProject.ok) {
14616
+ failures.push({ engineRoot, phase: "build", error: installedProject.errorMessage });
14617
+ console.log(chalk.red(`Build: failed (project install)
14618
+ ${installedProject.errorMessage}
14619
+ `));
14620
+ if (!doRuntime) continue;
14581
14621
  } else {
14582
- console.log(chalk.green(`Build: ok (log: ${built.buildLogPath})`));
14622
+ console.log(chalk.green(`Build: sources installed to ${installedProject.destDir}`));
14623
+ console.log(chalk.cyan("Build: compiling plugin via RunUAT BuildPlugin..."));
14624
+ const built = await types.buildAndInstallUnrealMcpPlugin({
14625
+ engineRoot,
14626
+ flockbayHomeDir: types.configuration.flockbayHomeDir,
14627
+ pluginDir: installedProject.destDir
14628
+ });
14629
+ if (!built.ok) {
14630
+ failures.push({ engineRoot, phase: "build", error: built.errorMessage });
14631
+ console.log(chalk.red(`Build: failed
14632
+ ${built.errorMessage}
14633
+ `));
14634
+ } else {
14635
+ console.log(chalk.green(`Build: ok (log: ${built.buildLogPath})`));
14636
+ }
14583
14637
  }
14638
+ } else {
14639
+ const error = `Engine plugins folder is not writable:
14640
+ ${enginePluginsDir}
14641
+
14642
+ Fix:
14643
+ - Re-run with --project "<path-to-your-project>.uproject" so we can install the plugin into the project (no admin), OR
14644
+ - Run the installer with Windows admin permissions.`;
14645
+ failures.push({ engineRoot, phase: "build", error });
14646
+ console.log(chalk.red(`Build: failed
14647
+ ${error}
14648
+ `));
14649
+ if (!doRuntime) continue;
14584
14650
  }
14585
14651
  }
14586
14652
  if (doRuntime) {
@@ -15039,7 +15105,7 @@ async function authAndSetupMachineIfNeeded() {
15039
15105
  process.exit(1);
15040
15106
  }
15041
15107
  try {
15042
- const { migrateUnrealMcpToFlockbayMcp } = await Promise.resolve().then(function () { return require('./migratePlugin-8J2c5CrP.cjs'); });
15108
+ const { migrateUnrealMcpToFlockbayMcp } = await Promise.resolve().then(function () { return require('./migratePlugin-CrSh19dY.cjs'); });
15043
15109
  const result = migrateUnrealMcpToFlockbayMcp({
15044
15110
  engineRoot,
15045
15111
  projectUprojectPath: project || void 0,
@@ -15178,7 +15244,7 @@ ${engineRoot}`, {
15178
15244
  } else if (subcommand === "codex") {
15179
15245
  try {
15180
15246
  await chdirToNearestUprojectRootIfPresent();
15181
- const { runCodex } = await Promise.resolve().then(function () { return require('./runCodex-BfUYEEBp.cjs'); });
15247
+ const { runCodex } = await Promise.resolve().then(function () { return require('./runCodex-CJa61r9H.cjs'); });
15182
15248
  let startedBy = void 0;
15183
15249
  let sessionId = void 0;
15184
15250
  for (let i = 1; i < args.length; i++) {
@@ -15280,7 +15346,7 @@ ${engineRoot}`, {
15280
15346
  }
15281
15347
  try {
15282
15348
  await chdirToNearestUprojectRootIfPresent();
15283
- const { runGemini } = await Promise.resolve().then(function () { return require('./runGemini-CnyDdQAY.cjs'); });
15349
+ const { runGemini } = await Promise.resolve().then(function () { return require('./runGemini-gcPF3ASy.cjs'); });
15284
15350
  let startedBy = void 0;
15285
15351
  let sessionId = void 0;
15286
15352
  for (let i = 1; i < args.length; i++) {
@@ -2,7 +2,7 @@ import{createRequire as _pkgrollCR}from"node:module";const require=_pkgrollCR(im
2
2
  import * as os from 'node:os';
3
3
  import os__default, { homedir } from 'node:os';
4
4
  import { randomUUID, createCipheriv, randomBytes, createHash as createHash$1 } from 'node:crypto';
5
- import { l as logger, b as projectPath, d as backoff, e as delay, R as RawJSONLinesSchema, c as configuration, f as readDaemonState, g as clearDaemonState, p as packageJson, r as readSettings, h as readCredentials, u as updateSettings, o as openBrowser, w as writeCredentials, j as unrealMcpPythonDir, k as acquireDaemonLock, m as writeDaemonState, n as ApiMachineClient, q as releaseDaemonLock, s as sendUnrealMcpTcpCommand, A as ApiClient, v as validatePath, t as run, x as run$1, y as buildShellInvocation, z as clearCredentials, B as clearMachineId, C as authenticateCodex, D as syncCodexCliAuth, E as authenticateClaude, F as authenticateGemini, i as installUnrealMcpPluginToEngine, G as buildAndInstallUnrealMcpPlugin, H as getLatestDaemonLog, I as normalizeServerUrlForNode } from './types-DQ-HKKy4.mjs';
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-1s9-Oj5w.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';
@@ -16,7 +16,6 @@ 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
20
  import { spawn as spawn$1, execFileSync as execFileSync$1 } from 'child_process';
22
21
  import { createHash } from 'crypto';
@@ -35,6 +34,7 @@ import { validatorCompiler, serializerCompiler } from 'fastify-type-provider-zod
35
34
  import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
36
35
  import { createServer } from 'node:http';
37
36
  import { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js';
37
+ import { EventEmitter } from 'node:events';
38
38
  import 'tweetnacl';
39
39
  import { deflateSync } from 'node:zlib';
40
40
 
@@ -5270,8 +5270,10 @@ function spawnFlockbayCLI(args, options = {}) {
5270
5270
  const entrypoint = existsSync(distEntrypoint) ? distEntrypoint : devEntrypoint;
5271
5271
  const useTsx = entrypoint.endsWith(".ts");
5272
5272
  const desiredCwd = "cwd" in options && typeof options.cwd === "string" ? options.cwd : process$1.cwd();
5273
+ const windowsHide = typeof options?.windowsHide === "boolean" ? Boolean(options.windowsHide) : process$1.platform === "win32";
5273
5274
  const spawnOptions = {
5274
5275
  ...options,
5276
+ windowsHide,
5275
5277
  ...useTsx ? { cwd: projectRoot } : {},
5276
5278
  env: {
5277
5279
  ...process$1.env,
@@ -7013,7 +7015,7 @@ ${scriptCandidates.map((p) => `- ${p}`).join("\n")}
7013
7015
  logStream.write(`args: ${JSON.stringify(buildArgs)}
7014
7016
 
7015
7017
  `);
7016
- const child = osPlatform === "win32" ? spawn("cmd.exe", ["/c", script, ...buildArgs], { stdio: ["ignore", "pipe", "pipe"] }) : spawn(script, buildArgs, { stdio: ["ignore", "pipe", "pipe"] });
7018
+ const child = osPlatform === "win32" ? spawn("cmd.exe", ["/c", script, ...buildArgs], { stdio: ["ignore", "pipe", "pipe"], windowsHide: true }) : spawn(script, buildArgs, { stdio: ["ignore", "pipe", "pipe"] });
7017
7019
  let combinedTail = "";
7018
7020
  const appendTail = (chunk) => {
7019
7021
  combinedTail += chunk.toString("utf8");
@@ -13146,7 +13148,7 @@ Update: ${updateCommand}`);
13146
13148
  summary: currentMetadata?.summary
13147
13149
  }));
13148
13150
  }
13149
- await session.connectAndWait(15e3);
13151
+ await session.connectAndWait();
13150
13152
  session.keepAlive(false, options.startingMode === "remote" ? "remote" : "local");
13151
13153
  try {
13152
13154
  logger.debug(`[START] Reporting session ${response.id} to daemon`);
@@ -14127,7 +14129,8 @@ async function runSmokeForAgent(agent, args) {
14127
14129
  const skipUnreal = !readFlag(args, "--with-unreal");
14128
14130
  const baseDir = readArgValue$2(args, "--directory") || readArgValue$2(args, "--dir");
14129
14131
  const timeoutMsRaw = readArgValue$2(args, "--timeout-ms");
14130
- const timeoutMs = timeoutMsRaw && Number.isFinite(Number(timeoutMsRaw)) ? Number(timeoutMsRaw) : 9e4;
14132
+ const defaultTimeoutMs = process.platform === "win32" ? 24e4 : 9e4;
14133
+ const timeoutMs = timeoutMsRaw && Number.isFinite(Number(timeoutMsRaw)) ? Number(timeoutMsRaw) : defaultTimeoutMs;
14131
14134
  let sessionId;
14132
14135
  let directory;
14133
14136
  let sessionClient = null;
@@ -14175,7 +14178,7 @@ Update: ${updateCommand}`);
14175
14178
  throw new Error(msg);
14176
14179
  }
14177
14180
  sessionClient = api.sessionSyncClient(session);
14178
- await sessionClient.connectAndWait(15e3);
14181
+ await sessionClient.connectAndWait();
14179
14182
  await ensureSessionActive(api, sessionId, 25e3);
14180
14183
  const permissionMode = permissionModeForAgent(agent);
14181
14184
  scenarios.push(await runScenario("basic-message", async () => {
@@ -14280,7 +14283,7 @@ Options:
14280
14283
  --agent, -a Run a single agent
14281
14284
  --agents Comma-separated list of agents
14282
14285
  --directory, --dir Directory to run the session in (defaults to a temp folder)
14283
- --timeout-ms Per-scenario timeout (default 90000)
14286
+ --timeout-ms Per-scenario timeout (default 90000; Windows default 240000)
14284
14287
  --keep Do not stop session or delete temp dir
14285
14288
  --json Write results JSON to a file
14286
14289
  --with-unreal Allow Unreal MCP prompts (off by default)
@@ -14344,6 +14347,18 @@ function splitList(value) {
14344
14347
  function ensureDir(dir) {
14345
14348
  fs__default.mkdirSync(dir, { recursive: true });
14346
14349
  }
14350
+ function canWriteDir(dir) {
14351
+ const root = (dir || "").trim();
14352
+ if (!root) return false;
14353
+ try {
14354
+ const tmp = path__default.join(root, `.__flockbay_write_test_${Date.now()}_${Math.random().toString(16).slice(2)}.tmp`);
14355
+ fs__default.writeFileSync(tmp, "ok", "utf8");
14356
+ fs__default.unlinkSync(tmp);
14357
+ return true;
14358
+ } catch {
14359
+ return false;
14360
+ }
14361
+ }
14347
14362
  function detectImageMimeTypeFromBuffer(buf) {
14348
14363
  if (!buf || buf.length < 12) return null;
14349
14364
  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) {
@@ -14362,7 +14377,7 @@ async function waitForUnreal(options) {
14362
14377
  while (Date.now() - startedAt < options.timeoutMs) {
14363
14378
  try {
14364
14379
  const res = await sendUnrealMcpTcpCommand({ type: "ping", host: options.host, port: options.port, timeoutMs: 2e3 });
14365
- const msg = typeof res?.message === "string" ? res.message : null;
14380
+ const msg = typeof res?.message === "string" ? res.message : typeof res?.result?.message === "string" ? res.result.message : null;
14366
14381
  if (msg === "pong") return { ok: true };
14367
14382
  } catch (err) {
14368
14383
  lastErr = err instanceof Error ? err.message : String(err);
@@ -14410,22 +14425,23 @@ async function runRuntimeSmoke(options) {
14410
14425
  }
14411
14426
  try {
14412
14427
  const pluginInfo = await sendUnrealMcpTcpCommand({ type: "get_plugin_info", host: options.host, port: options.port, timeoutMs: options.timeoutMs });
14413
- const createdBy = String(pluginInfo?.createdBy || "").trim();
14414
- const friendlyName = String(pluginInfo?.friendlyName || "").trim();
14415
- const baseDir = String(pluginInfo?.baseDir || "").trim();
14416
- const schemaVersion = Number(pluginInfo?.schemaVersion);
14417
- const commands = Array.isArray(pluginInfo?.commands) ? pluginInfo.commands.filter((c) => typeof c === "string") : [];
14418
- if (friendlyName !== "Unreal MCP Plugin" || createdBy !== "Respaced Inc.") {
14428
+ const pluginInfoResult = pluginInfo?.result && typeof pluginInfo.result === "object" ? pluginInfo.result : pluginInfo;
14429
+ const createdBy = String(pluginInfoResult?.createdBy || "").trim();
14430
+ const friendlyName = String(pluginInfoResult?.friendlyName || "").trim();
14431
+ const baseDir = String(pluginInfoResult?.baseDir || "").trim();
14432
+ const schemaVersion = Number(pluginInfoResult?.schemaVersion);
14433
+ const commands = Array.isArray(pluginInfoResult?.commands) ? pluginInfoResult.commands.filter((c) => typeof c === "string") : [];
14434
+ if (friendlyName !== "Flockbay MCP" || createdBy !== "Respaced Inc.") {
14419
14435
  return {
14420
14436
  ok: false,
14421
14437
  error: `Unexpected plugin identity loaded by Unreal.
14422
14438
  friendlyName=${friendlyName || "(missing)"} createdBy=${createdBy || "(missing)"}
14423
14439
  baseDir=${baseDir || "(missing)"}
14424
- Expected FriendlyName="Unreal MCP Plugin" CreatedBy="Respaced Inc."`
14440
+ Expected FriendlyName="Flockbay MCP" CreatedBy="Respaced Inc."`
14425
14441
  };
14426
14442
  }
14427
14443
  if (!Number.isFinite(schemaVersion) || schemaVersion <= 0) {
14428
- return { ok: false, error: `Invalid schemaVersion from get_plugin_info: ${String(pluginInfo?.schemaVersion)}` };
14444
+ return { ok: false, error: `Invalid schemaVersion from get_plugin_info: ${String(pluginInfoResult?.schemaVersion)}` };
14429
14445
  }
14430
14446
  const requireCommands = [
14431
14447
  "ping",
@@ -14445,7 +14461,8 @@ Expected FriendlyName="Unreal MCP Plugin" CreatedBy="Respaced Inc."`
14445
14461
  return { ok: false, error: `Missing required commands in this Unreal MCP build: ${missing.join(", ")}` };
14446
14462
  }
14447
14463
  const playStatus0 = await sendUnrealMcpTcpCommand({ type: "get_play_in_editor_status", host: options.host, port: options.port, timeoutMs: options.timeoutMs });
14448
- const isPlaying = Boolean(playStatus0?.isPlaySessionInProgress);
14464
+ const playStatusResult = playStatus0?.result && typeof playStatus0.result === "object" ? playStatus0.result : playStatus0;
14465
+ const isPlaying = Boolean(playStatusResult?.isPlaySessionInProgress);
14449
14466
  if (isPlaying) {
14450
14467
  await sendUnrealMcpTcpCommand({ type: "stop_play_in_editor", host: options.host, port: options.port, timeoutMs: options.timeoutMs });
14451
14468
  }
@@ -14472,7 +14489,9 @@ Expected FriendlyName="Unreal MCP Plugin" CreatedBy="Respaced Inc."`
14472
14489
  const bpName = `BP_Smoke_${Date.now()}`;
14473
14490
  await sendUnrealMcpTcpCommand({
14474
14491
  type: "create_blueprint",
14475
- params: { name: bpName, path: "/Game/FlockbaySmoke/", parent_class: "Actor" },
14492
+ // Important: pass only the name so the plugin's default (/Game/Blueprints/) is used.
14493
+ // The plugin's "compile_blueprint" name-only lookup searches /Game/Blueprints by design.
14494
+ params: { name: bpName, parent_class: "Actor" },
14476
14495
  host: options.host,
14477
14496
  port: options.port,
14478
14497
  timeoutMs: Math.max(options.timeoutMs, 2e4)
@@ -14539,26 +14558,73 @@ async function runUnrealMcpMatrixSmoke(args) {
14539
14558
  if (!engineRoot) continue;
14540
14559
  console.log(chalk.bold(`== Engine: ${engineRoot} ==`));
14541
14560
  if (doBuild) {
14542
- console.log(chalk.cyan("Build: installing Flockbay MCP plugin sources (folder: FlockbayMCP)..."));
14543
- const installed = installUnrealMcpPluginToEngine(engineRoot);
14544
- if (!installed.ok) {
14545
- failures.push({ engineRoot, phase: "build", error: installed.errorMessage });
14546
- console.log(chalk.red(`Build: failed (install)
14561
+ const enginePluginsDir = path__default.join(engineRoot, "Engine", "Plugins");
14562
+ const enginePluginDir = path__default.join(enginePluginsDir, "FlockbayMCP");
14563
+ const enginePluginUplugin = path__default.join(enginePluginDir, "FlockbayMCP.uplugin");
14564
+ const enginePluginHasBinaries = fs__default.existsSync(path__default.join(enginePluginDir, "Binaries"));
14565
+ const projectUprojectPath = project ? path__default.resolve(project) : null;
14566
+ if (fs__default.existsSync(enginePluginUplugin) && enginePluginHasBinaries) {
14567
+ console.log(chalk.green(`Build: engine plugin already installed + built (${enginePluginDir})`));
14568
+ } else if (canWriteDir(enginePluginsDir)) {
14569
+ console.log(chalk.cyan("Build: installing Flockbay MCP plugin sources into the engine (folder: FlockbayMCP)..."));
14570
+ const installed = installUnrealMcpPluginToEngine(engineRoot);
14571
+ if (!installed.ok) {
14572
+ failures.push({ engineRoot, phase: "build", error: installed.errorMessage });
14573
+ console.log(chalk.red(`Build: failed (install)
14547
14574
  ${installed.errorMessage}
14548
14575
  `));
14549
- if (!doRuntime) continue;
14550
- } else {
14551
- console.log(chalk.green(`Build: sources installed to ${installed.destDir}`));
14552
- console.log(chalk.cyan("Build: compiling plugin via RunUAT BuildPlugin..."));
14553
- const built = await buildAndInstallUnrealMcpPlugin({ engineRoot, flockbayHomeDir: configuration.flockbayHomeDir });
14554
- if (!built.ok) {
14555
- failures.push({ engineRoot, phase: "build", error: built.errorMessage });
14556
- console.log(chalk.red(`Build: failed
14576
+ if (!doRuntime) continue;
14577
+ } else {
14578
+ console.log(chalk.green(`Build: sources installed to ${installed.destDir}`));
14579
+ console.log(chalk.cyan("Build: compiling plugin via RunUAT BuildPlugin..."));
14580
+ const built = await buildAndInstallUnrealMcpPlugin({ engineRoot, flockbayHomeDir: configuration.flockbayHomeDir });
14581
+ if (!built.ok) {
14582
+ failures.push({ engineRoot, phase: "build", error: built.errorMessage });
14583
+ console.log(chalk.red(`Build: failed
14557
14584
  ${built.errorMessage}
14558
14585
  `));
14586
+ } else {
14587
+ console.log(chalk.green(`Build: ok (log: ${built.buildLogPath})`));
14588
+ }
14589
+ }
14590
+ } else if (projectUprojectPath) {
14591
+ console.log(chalk.cyan("Build: engine install not writable; installing plugin into the project instead..."));
14592
+ const installedProject = installUnrealMcpPluginToProject(projectUprojectPath);
14593
+ if (!installedProject.ok) {
14594
+ failures.push({ engineRoot, phase: "build", error: installedProject.errorMessage });
14595
+ console.log(chalk.red(`Build: failed (project install)
14596
+ ${installedProject.errorMessage}
14597
+ `));
14598
+ if (!doRuntime) continue;
14559
14599
  } else {
14560
- console.log(chalk.green(`Build: ok (log: ${built.buildLogPath})`));
14600
+ console.log(chalk.green(`Build: sources installed to ${installedProject.destDir}`));
14601
+ console.log(chalk.cyan("Build: compiling plugin via RunUAT BuildPlugin..."));
14602
+ const built = await buildAndInstallUnrealMcpPlugin({
14603
+ engineRoot,
14604
+ flockbayHomeDir: configuration.flockbayHomeDir,
14605
+ pluginDir: installedProject.destDir
14606
+ });
14607
+ if (!built.ok) {
14608
+ failures.push({ engineRoot, phase: "build", error: built.errorMessage });
14609
+ console.log(chalk.red(`Build: failed
14610
+ ${built.errorMessage}
14611
+ `));
14612
+ } else {
14613
+ console.log(chalk.green(`Build: ok (log: ${built.buildLogPath})`));
14614
+ }
14561
14615
  }
14616
+ } else {
14617
+ const error = `Engine plugins folder is not writable:
14618
+ ${enginePluginsDir}
14619
+
14620
+ Fix:
14621
+ - Re-run with --project "<path-to-your-project>.uproject" so we can install the plugin into the project (no admin), OR
14622
+ - Run the installer with Windows admin permissions.`;
14623
+ failures.push({ engineRoot, phase: "build", error });
14624
+ console.log(chalk.red(`Build: failed
14625
+ ${error}
14626
+ `));
14627
+ if (!doRuntime) continue;
14562
14628
  }
14563
14629
  }
14564
14630
  if (doRuntime) {
@@ -15017,7 +15083,7 @@ async function authAndSetupMachineIfNeeded() {
15017
15083
  process.exit(1);
15018
15084
  }
15019
15085
  try {
15020
- const { migrateUnrealMcpToFlockbayMcp } = await import('./migratePlugin-D-oSS5d1.mjs');
15086
+ const { migrateUnrealMcpToFlockbayMcp } = await import('./migratePlugin-BenVKITz.mjs');
15021
15087
  const result = migrateUnrealMcpToFlockbayMcp({
15022
15088
  engineRoot,
15023
15089
  projectUprojectPath: project || void 0,
@@ -15156,7 +15222,7 @@ ${engineRoot}`, {
15156
15222
  } else if (subcommand === "codex") {
15157
15223
  try {
15158
15224
  await chdirToNearestUprojectRootIfPresent();
15159
- const { runCodex } = await import('./runCodex-B10NJHEL.mjs');
15225
+ const { runCodex } = await import('./runCodex-aBjsormW.mjs');
15160
15226
  let startedBy = void 0;
15161
15227
  let sessionId = void 0;
15162
15228
  for (let i = 1; i < args.length; i++) {
@@ -15258,7 +15324,7 @@ ${engineRoot}`, {
15258
15324
  }
15259
15325
  try {
15260
15326
  await chdirToNearestUprojectRootIfPresent();
15261
- const { runGemini } = await import('./runGemini-B4kutwSV.mjs');
15327
+ const { runGemini } = await import('./runGemini-D9bi1Ih3.mjs');
15262
15328
  let startedBy = void 0;
15263
15329
  let sessionId = void 0;
15264
15330
  for (let i = 1; i < args.length; i++) {
package/dist/index.cjs CHANGED
@@ -1,8 +1,8 @@
1
1
  'use strict';
2
2
 
3
3
  require('chalk');
4
- require('./index-X_0a6dpP.cjs');
5
- require('./types-2vFbaIZJ.cjs');
4
+ require('./index-Bih-iANW.cjs');
5
+ require('./types-DTy-RPNv.cjs');
6
6
  require('zod');
7
7
  require('node:child_process');
8
8
  require('node:fs');
@@ -17,7 +17,6 @@ require('ink');
17
17
  require('react');
18
18
  require('node:url');
19
19
  require('axios');
20
- require('node:events');
21
20
  require('socket.io-client');
22
21
  require('child_process');
23
22
  require('crypto');
@@ -35,6 +34,7 @@ require('fastify-type-provider-zod');
35
34
  require('@modelcontextprotocol/sdk/server/mcp.js');
36
35
  require('node:http');
37
36
  require('@modelcontextprotocol/sdk/server/streamableHttp.js');
37
+ require('node:events');
38
38
  require('tweetnacl');
39
39
  require('node:zlib');
40
40
  require('url');
package/dist/index.mjs CHANGED
@@ -1,6 +1,6 @@
1
1
  import 'chalk';
2
- import './index-4XOVLZZ1.mjs';
3
- import './types-DQ-HKKy4.mjs';
2
+ import './index-ZFx58JSw.mjs';
3
+ import './types-1s9-Oj5w.mjs';
4
4
  import 'zod';
5
5
  import 'node:child_process';
6
6
  import 'node:fs';
@@ -15,7 +15,6 @@ import 'ink';
15
15
  import 'react';
16
16
  import 'node:url';
17
17
  import 'axios';
18
- import 'node:events';
19
18
  import 'socket.io-client';
20
19
  import 'child_process';
21
20
  import 'crypto';
@@ -33,6 +32,7 @@ import 'fastify-type-provider-zod';
33
32
  import '@modelcontextprotocol/sdk/server/mcp.js';
34
33
  import 'node:http';
35
34
  import '@modelcontextprotocol/sdk/server/streamableHttp.js';
35
+ import 'node:events';
36
36
  import 'tweetnacl';
37
37
  import 'node:zlib';
38
38
  import 'url';
package/dist/lib.cjs CHANGED
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- var types = require('./types-2vFbaIZJ.cjs');
3
+ var types = require('./types-DTy-RPNv.cjs');
4
4
  require('axios');
5
5
  require('node:fs');
6
6
  require('node:os');
package/dist/lib.mjs CHANGED
@@ -1,4 +1,4 @@
1
- export { A as ApiClient, a as ApiSessionClient, R as RawJSONLinesSchema, c as configuration, l as logger } from './types-DQ-HKKy4.mjs';
1
+ export { A as ApiClient, a as ApiSessionClient, R as RawJSONLinesSchema, c as configuration, l as logger } from './types-1s9-Oj5w.mjs';
2
2
  import 'axios';
3
3
  import 'node:fs';
4
4
  import 'node:os';
@@ -1,6 +1,6 @@
1
1
  import fs__default from 'node:fs';
2
2
  import path__default from 'node:path';
3
- import { i as installUnrealMcpPluginToEngine } from './types-DQ-HKKy4.mjs';
3
+ import { i as installUnrealMcpPluginToEngine } from './types-1s9-Oj5w.mjs';
4
4
  import 'axios';
5
5
  import 'node:os';
6
6
  import 'node:events';