flockbay 0.10.51 → 0.10.53

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-CN-EDgzo.cjs');
6
+ var types = require('./types-DQ4IqofE.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');
@@ -982,7 +982,11 @@ async function claudeLocalLauncher(session) {
982
982
  } catch (e) {
983
983
  types.logger.debug("[local]: launch error", e);
984
984
  if (!exitReason) {
985
- session.client.sendSessionEvent({ type: "message", message: "Process exited unexpectedly" });
985
+ const details = e instanceof Error ? e.message : String(e);
986
+ session.client.sendSessionEvent({
987
+ type: "message",
988
+ message: `Process exited unexpectedly${details ? `: ${details}` : ""}`
989
+ });
986
990
  continue;
987
991
  } else {
988
992
  break;
@@ -1319,7 +1323,7 @@ function buildDaemonSafeEnv(baseEnv, binPath) {
1319
1323
  env[pathKey] = [...prepend, ...existingParts].join(pathSep);
1320
1324
  return env;
1321
1325
  }
1322
- 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-wU3LFfZh.cjs', document.baseURI).href)));
1326
+ 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-CG7Ouk31.cjs', document.baseURI).href)));
1323
1327
  const __dirname$1 = path.join(__filename$1, "..");
1324
1328
  function getGlobalClaudeVersion(claudeExecutable) {
1325
1329
  try {
@@ -1522,6 +1526,40 @@ async function streamToStdin(stream, stdin, abort) {
1522
1526
  stdin.end();
1523
1527
  }
1524
1528
 
1529
+ function trimProcessDiagnostic(text) {
1530
+ const lines = String(text || "").split(/\r?\n/).map((line) => line.trim()).filter(Boolean);
1531
+ if (lines.length === 0) return "";
1532
+ return lines.slice(-8).join("\n");
1533
+ }
1534
+ function buildClaudeProcessExitMessage(args) {
1535
+ const stderrText = String(args.stderrText || "");
1536
+ const stderr = trimProcessDiagnostic(stderrText);
1537
+ const combined = [stderrText, args.spawnError?.message || ""].filter(Boolean).join("\n");
1538
+ if (/claude code is not installed/i.test(combined)) {
1539
+ return [
1540
+ "Claude Code is not installed on this machine.",
1541
+ "Install it, then restart Flockbay:",
1542
+ process$1.platform === "win32" ? " npm install -g @anthropic-ai/claude-code" : " npm install -g @anthropic-ai/claude-code"
1543
+ ].join("\n");
1544
+ }
1545
+ if (/not recognized as an internal or external command|command not found|spawn .*enoent|enoent/i.test(combined)) {
1546
+ return [
1547
+ "Claude Code could not be found on PATH.",
1548
+ "Install it, then restart Flockbay:",
1549
+ " npm install -g @anthropic-ai/claude-code"
1550
+ ].join("\n");
1551
+ }
1552
+ if (/git bash|bash\.exe|claude_code_git_bash_path/i.test(combined)) {
1553
+ return [
1554
+ "Claude Code could not start because Git Bash is missing or not configured.",
1555
+ "Install Git for Windows, then set CLAUDE_CODE_GIT_BASH_PATH to your bash.exe path and restart Flockbay."
1556
+ ].join("\n");
1557
+ }
1558
+ if (stderr) {
1559
+ return `Claude Code process exited with code ${args.code}. Details: ${stderr}`;
1560
+ }
1561
+ return `Claude Code process exited with code ${args.code}`;
1562
+ }
1525
1563
  class Query {
1526
1564
  constructor(childStdin, childStdout, processExitPromise, canCallTool) {
1527
1565
  this.childStdin = childStdin;
@@ -1791,11 +1829,17 @@ function query(config) {
1791
1829
  streamToStdin(prompt, child.stdin, config.options?.abort);
1792
1830
  childStdin = child.stdin;
1793
1831
  }
1794
- if (process$1.env.DEBUG) {
1795
- child.stderr.on("data", (data) => {
1832
+ let stderrTail = "";
1833
+ const appendStderr = (chunk) => {
1834
+ stderrTail += chunk.toString();
1835
+ if (stderrTail.length > 32e3) stderrTail = stderrTail.slice(-16e3);
1836
+ };
1837
+ child.stderr.on("data", (data) => {
1838
+ appendStderr(data);
1839
+ if (process$1.env.DEBUG) {
1796
1840
  console.error("Claude Code stderr:", data.toString());
1797
- });
1798
- }
1841
+ }
1842
+ });
1799
1843
  const cleanup = () => {
1800
1844
  if (!child.killed) {
1801
1845
  child.kill("SIGTERM");
@@ -1809,7 +1853,7 @@ function query(config) {
1809
1853
  query2.setError(new AbortError("Claude Code process aborted by user"));
1810
1854
  }
1811
1855
  if (code !== 0) {
1812
- query2.setError(new Error(`Claude Code process exited with code ${code}`));
1856
+ query2.setError(new Error(buildClaudeProcessExitMessage({ code, stderrText: stderrTail })));
1813
1857
  } else {
1814
1858
  resolve();
1815
1859
  }
@@ -1820,7 +1864,7 @@ function query(config) {
1820
1864
  if (config.options?.abort?.aborted) {
1821
1865
  query2.setError(new AbortError("Claude Code process aborted by user"));
1822
1866
  } else {
1823
- query2.setError(new Error(`Failed to spawn Claude Code process: ${error.message}`));
1867
+ query2.setError(new Error(buildClaudeProcessExitMessage({ code: null, stderrText: stderrTail, spawnError: error })));
1824
1868
  }
1825
1869
  });
1826
1870
  processExitPromise.finally(() => {
@@ -15225,7 +15269,7 @@ async function authAndSetupMachineIfNeeded() {
15225
15269
  process.exit(1);
15226
15270
  }
15227
15271
  try {
15228
- const { migrateUnrealMcpToFlockbayMcp } = await Promise.resolve().then(function () { return require('./migratePlugin-CyXgJ-se.cjs'); });
15272
+ const { migrateUnrealMcpToFlockbayMcp } = await Promise.resolve().then(function () { return require('./migratePlugin-CZ3rEkKy.cjs'); });
15229
15273
  const result = migrateUnrealMcpToFlockbayMcp({
15230
15274
  engineRoot,
15231
15275
  projectUprojectPath: project || void 0,
@@ -15381,7 +15425,7 @@ ${engineRoot}`;
15381
15425
  } else if (subcommand === "codex") {
15382
15426
  try {
15383
15427
  await chdirToNearestUprojectRootIfPresent();
15384
- const { runCodex } = await Promise.resolve().then(function () { return require('./runCodex-jDfLDJJW.cjs'); });
15428
+ const { runCodex } = await Promise.resolve().then(function () { return require('./runCodex-DFG80IBU.cjs'); });
15385
15429
  let startedBy = void 0;
15386
15430
  let sessionId = void 0;
15387
15431
  for (let i = 1; i < args.length; i++) {
@@ -15483,7 +15527,7 @@ ${engineRoot}`;
15483
15527
  }
15484
15528
  try {
15485
15529
  await chdirToNearestUprojectRootIfPresent();
15486
- const { runGemini } = await Promise.resolve().then(function () { return require('./runGemini-DN189-WI.cjs'); });
15530
+ const { runGemini } = await Promise.resolve().then(function () { return require('./runGemini-B6k0JjNw.cjs'); });
15487
15531
  let startedBy = void 0;
15488
15532
  let sessionId = void 0;
15489
15533
  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, e as projectPath, f as backoff, g as delay, R as RawJSONLinesSchema, c as configuration, h as readDaemonState, j as clearDaemonState, p as packageJson, r as readSettings, k as readCredentials, u as updateSettings, o as openBrowser, w as writeCredentials, m as unrealMcpPythonDir, n as acquireDaemonLock, s as writeDaemonState, t as ApiMachineClient, v as releaseDaemonLock, x as sendUnrealMcpTcpCommand, A as ApiClient, y as validatePath, z as run, B as run$1, C as buildShellInvocation, D as clearCredentials, E as clearMachineId, F as authenticateCodex, G as syncCodexCliAuth, H as authenticateClaude, I as authenticateGemini, d as installUnrealMcpPluginToEngine, J as buildAndInstallUnrealMcpPlugin, i as installUnrealMcpPluginToProject, b as isInstalledEngineRoot, K as getLatestDaemonLog, L as normalizeServerUrlForNode } from './types-DRXvc8Nt.mjs';
5
+ import { l as logger, e as projectPath, f as backoff, g as delay, R as RawJSONLinesSchema, c as configuration, h as readDaemonState, j as clearDaemonState, p as packageJson, r as readSettings, k as readCredentials, u as updateSettings, o as openBrowser, w as writeCredentials, m as unrealMcpPythonDir, n as acquireDaemonLock, s as writeDaemonState, t as ApiMachineClient, v as releaseDaemonLock, x as sendUnrealMcpTcpCommand, A as ApiClient, y as validatePath, z as run, B as run$1, C as buildShellInvocation, D as clearCredentials, E as clearMachineId, F as authenticateCodex, G as syncCodexCliAuth, H as authenticateClaude, I as authenticateGemini, d as installUnrealMcpPluginToEngine, J as buildAndInstallUnrealMcpPlugin, i as installUnrealMcpPluginToProject, b as isInstalledEngineRoot, K as getLatestDaemonLog, L as normalizeServerUrlForNode } from './types-Dsn3eNAB.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';
@@ -960,7 +960,11 @@ async function claudeLocalLauncher(session) {
960
960
  } catch (e) {
961
961
  logger.debug("[local]: launch error", e);
962
962
  if (!exitReason) {
963
- session.client.sendSessionEvent({ type: "message", message: "Process exited unexpectedly" });
963
+ const details = e instanceof Error ? e.message : String(e);
964
+ session.client.sendSessionEvent({
965
+ type: "message",
966
+ message: `Process exited unexpectedly${details ? `: ${details}` : ""}`
967
+ });
964
968
  continue;
965
969
  } else {
966
970
  break;
@@ -1500,6 +1504,40 @@ async function streamToStdin(stream, stdin, abort) {
1500
1504
  stdin.end();
1501
1505
  }
1502
1506
 
1507
+ function trimProcessDiagnostic(text) {
1508
+ const lines = String(text || "").split(/\r?\n/).map((line) => line.trim()).filter(Boolean);
1509
+ if (lines.length === 0) return "";
1510
+ return lines.slice(-8).join("\n");
1511
+ }
1512
+ function buildClaudeProcessExitMessage(args) {
1513
+ const stderrText = String(args.stderrText || "");
1514
+ const stderr = trimProcessDiagnostic(stderrText);
1515
+ const combined = [stderrText, args.spawnError?.message || ""].filter(Boolean).join("\n");
1516
+ if (/claude code is not installed/i.test(combined)) {
1517
+ return [
1518
+ "Claude Code is not installed on this machine.",
1519
+ "Install it, then restart Flockbay:",
1520
+ process$1.platform === "win32" ? " npm install -g @anthropic-ai/claude-code" : " npm install -g @anthropic-ai/claude-code"
1521
+ ].join("\n");
1522
+ }
1523
+ if (/not recognized as an internal or external command|command not found|spawn .*enoent|enoent/i.test(combined)) {
1524
+ return [
1525
+ "Claude Code could not be found on PATH.",
1526
+ "Install it, then restart Flockbay:",
1527
+ " npm install -g @anthropic-ai/claude-code"
1528
+ ].join("\n");
1529
+ }
1530
+ if (/git bash|bash\.exe|claude_code_git_bash_path/i.test(combined)) {
1531
+ return [
1532
+ "Claude Code could not start because Git Bash is missing or not configured.",
1533
+ "Install Git for Windows, then set CLAUDE_CODE_GIT_BASH_PATH to your bash.exe path and restart Flockbay."
1534
+ ].join("\n");
1535
+ }
1536
+ if (stderr) {
1537
+ return `Claude Code process exited with code ${args.code}. Details: ${stderr}`;
1538
+ }
1539
+ return `Claude Code process exited with code ${args.code}`;
1540
+ }
1503
1541
  class Query {
1504
1542
  constructor(childStdin, childStdout, processExitPromise, canCallTool) {
1505
1543
  this.childStdin = childStdin;
@@ -1769,11 +1807,17 @@ function query(config) {
1769
1807
  streamToStdin(prompt, child.stdin, config.options?.abort);
1770
1808
  childStdin = child.stdin;
1771
1809
  }
1772
- if (process$1.env.DEBUG) {
1773
- child.stderr.on("data", (data) => {
1810
+ let stderrTail = "";
1811
+ const appendStderr = (chunk) => {
1812
+ stderrTail += chunk.toString();
1813
+ if (stderrTail.length > 32e3) stderrTail = stderrTail.slice(-16e3);
1814
+ };
1815
+ child.stderr.on("data", (data) => {
1816
+ appendStderr(data);
1817
+ if (process$1.env.DEBUG) {
1774
1818
  console.error("Claude Code stderr:", data.toString());
1775
- });
1776
- }
1819
+ }
1820
+ });
1777
1821
  const cleanup = () => {
1778
1822
  if (!child.killed) {
1779
1823
  child.kill("SIGTERM");
@@ -1787,7 +1831,7 @@ function query(config) {
1787
1831
  query2.setError(new AbortError("Claude Code process aborted by user"));
1788
1832
  }
1789
1833
  if (code !== 0) {
1790
- query2.setError(new Error(`Claude Code process exited with code ${code}`));
1834
+ query2.setError(new Error(buildClaudeProcessExitMessage({ code, stderrText: stderrTail })));
1791
1835
  } else {
1792
1836
  resolve();
1793
1837
  }
@@ -1798,7 +1842,7 @@ function query(config) {
1798
1842
  if (config.options?.abort?.aborted) {
1799
1843
  query2.setError(new AbortError("Claude Code process aborted by user"));
1800
1844
  } else {
1801
- query2.setError(new Error(`Failed to spawn Claude Code process: ${error.message}`));
1845
+ query2.setError(new Error(buildClaudeProcessExitMessage({ code: null, stderrText: stderrTail, spawnError: error })));
1802
1846
  }
1803
1847
  });
1804
1848
  processExitPromise.finally(() => {
@@ -15203,7 +15247,7 @@ async function authAndSetupMachineIfNeeded() {
15203
15247
  process.exit(1);
15204
15248
  }
15205
15249
  try {
15206
- const { migrateUnrealMcpToFlockbayMcp } = await import('./migratePlugin-CnpWYW1E.mjs');
15250
+ const { migrateUnrealMcpToFlockbayMcp } = await import('./migratePlugin-_Voh9wUv.mjs');
15207
15251
  const result = migrateUnrealMcpToFlockbayMcp({
15208
15252
  engineRoot,
15209
15253
  projectUprojectPath: project || void 0,
@@ -15359,7 +15403,7 @@ ${engineRoot}`;
15359
15403
  } else if (subcommand === "codex") {
15360
15404
  try {
15361
15405
  await chdirToNearestUprojectRootIfPresent();
15362
- const { runCodex } = await import('./runCodex-Dhkynhhh.mjs');
15406
+ const { runCodex } = await import('./runCodex-CBPYccVV.mjs');
15363
15407
  let startedBy = void 0;
15364
15408
  let sessionId = void 0;
15365
15409
  for (let i = 1; i < args.length; i++) {
@@ -15461,7 +15505,7 @@ ${engineRoot}`;
15461
15505
  }
15462
15506
  try {
15463
15507
  await chdirToNearestUprojectRootIfPresent();
15464
- const { runGemini } = await import('./runGemini-Dq5_59Us.mjs');
15508
+ const { runGemini } = await import('./runGemini-ibnNbOeF.mjs');
15465
15509
  let startedBy = void 0;
15466
15510
  let sessionId = void 0;
15467
15511
  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-wU3LFfZh.cjs');
5
- require('./types-CN-EDgzo.cjs');
4
+ require('./index-CG7Ouk31.cjs');
5
+ require('./types-DQ4IqofE.cjs');
6
6
  require('zod');
7
7
  require('node:child_process');
8
8
  require('node:fs');
package/dist/index.mjs CHANGED
@@ -1,6 +1,6 @@
1
1
  import 'chalk';
2
- import './index-DZjyS6UX.mjs';
3
- import './types-DRXvc8Nt.mjs';
2
+ import './index-ZZAd2VNk.mjs';
3
+ import './types-Dsn3eNAB.mjs';
4
4
  import 'zod';
5
5
  import 'node:child_process';
6
6
  import 'node:fs';
package/dist/lib.cjs CHANGED
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- var types = require('./types-CN-EDgzo.cjs');
3
+ var types = require('./types-DQ4IqofE.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-DRXvc8Nt.mjs';
1
+ export { A as ApiClient, a as ApiSessionClient, R as RawJSONLinesSchema, c as configuration, l as logger } from './types-Dsn3eNAB.mjs';
2
2
  import 'axios';
3
3
  import 'node:fs';
4
4
  import 'node:os';
@@ -2,7 +2,7 @@
2
2
 
3
3
  var fs = require('node:fs');
4
4
  var path = require('node:path');
5
- var types = require('./types-CN-EDgzo.cjs');
5
+ var types = require('./types-DQ4IqofE.cjs');
6
6
  require('axios');
7
7
  require('node:os');
8
8
  require('node:events');
@@ -1,6 +1,6 @@
1
1
  import fs__default from 'node:fs';
2
2
  import path__default from 'node:path';
3
- import { i as installUnrealMcpPluginToProject, b as isInstalledEngineRoot, q as quarantineLegacyEnginePlugins, d as installUnrealMcpPluginToEngine } from './types-DRXvc8Nt.mjs';
3
+ import { i as installUnrealMcpPluginToProject, b as isInstalledEngineRoot, q as quarantineLegacyEnginePlugins, d as installUnrealMcpPluginToEngine } from './types-Dsn3eNAB.mjs';
4
4
  import 'axios';
5
5
  import 'node:os';
6
6
  import 'node:events';
@@ -1,6 +1,6 @@
1
1
  import { useStdout, useInput, Box, Text, render } from 'ink';
2
2
  import React, { useState, useRef, useEffect, useCallback } from 'react';
3
- import { l as logger, A as ApiClient, p as packageJson, c as configuration, r as readSettings, e as projectPath } from './types-DRXvc8Nt.mjs';
3
+ import { l as logger, A as ApiClient, p as packageJson, c as configuration, r as readSettings, e as projectPath } from './types-Dsn3eNAB.mjs';
4
4
  import { Client } from '@modelcontextprotocol/sdk/client/index.js';
5
5
  import { z } from 'zod';
6
6
  import { ElicitRequestSchema } from '@modelcontextprotocol/sdk/types.js';
@@ -14,7 +14,7 @@ import process$1 from 'node:process';
14
14
  import { PassThrough } from 'node:stream';
15
15
  import { getDefaultEnvironment } from '@modelcontextprotocol/sdk/client/stdio.js';
16
16
  import { ReadBuffer, serializeMessage } from '@modelcontextprotocol/sdk/shared/stdio.js';
17
- import { s as shouldCountToolCall, c as consumeToolQuota, f as formatQuotaDeniedReason, h as hashObject, e as enforceCliVersionPolicy, i as initialMachineMetadata, E as ElicitationHub, n as notifyDaemonSessionStarted, M as MessageQueue2, P as PLATFORM_SYSTEM_PROMPT, a as setLatestUserImages, w as withUserImagesMarker, r as registerKillSessionHandler, b as MessageBuffer, d as startFlockbayServer, g as buildProjectCapsule, t as trimIdent, j as autoFinalizeCoordinationWorkItem, k as detectScreenshotsForGate, l as applyCoordinationSideEffectsFromMcpToolResult, m as stopCaffeinate } from './index-DZjyS6UX.mjs';
17
+ import { s as shouldCountToolCall, c as consumeToolQuota, f as formatQuotaDeniedReason, h as hashObject, e as enforceCliVersionPolicy, i as initialMachineMetadata, E as ElicitationHub, n as notifyDaemonSessionStarted, M as MessageQueue2, P as PLATFORM_SYSTEM_PROMPT, a as setLatestUserImages, w as withUserImagesMarker, r as registerKillSessionHandler, b as MessageBuffer, d as startFlockbayServer, g as buildProjectCapsule, t as trimIdent, j as autoFinalizeCoordinationWorkItem, k as detectScreenshotsForGate, l as applyCoordinationSideEffectsFromMcpToolResult, m as stopCaffeinate } from './index-ZZAd2VNk.mjs';
18
18
  import 'axios';
19
19
  import 'node:events';
20
20
  import 'socket.io-client';
@@ -2348,38 +2348,50 @@ function hashCodexSessionModeFromEnhancedMode(mode) {
2348
2348
  }
2349
2349
 
2350
2350
  const MIN_CODEX_CLI_FOR_GPT_53_CODEX = { major: 0, minor: 104, patch: 0 };
2351
- function readCodexAuthIsChatGptAccount() {
2352
- try {
2353
- const authPath = path__default.join(os__default.homedir(), ".codex", "auth.json");
2354
- const raw = fs__default.readFileSync(authPath, "utf8");
2355
- const parsed = JSON.parse(raw);
2356
- const accessToken = parsed?.tokens?.access_token;
2357
- if (typeof accessToken !== "string" || !accessToken) return false;
2358
- return Boolean(parsed?.tokens?.account_id) && parsed?.OPENAI_API_KEY === null;
2359
- } catch {
2360
- return false;
2351
+ function normalizeLegacyModelAlias(model) {
2352
+ const trimmed = String(model || "").trim();
2353
+ if (!trimmed) return "";
2354
+ switch (trimmed) {
2355
+ case "gpt-5":
2356
+ case "gpt-5-minimal":
2357
+ case "gpt-5-low":
2358
+ return "gpt-5.4-low";
2359
+ case "gpt-5-medium":
2360
+ return "gpt-5.4-medium";
2361
+ case "gpt-5-high":
2362
+ return "gpt-5.4-high";
2363
+ case "gpt-5-codex":
2364
+ case "gpt-5-codex-low":
2365
+ return "gpt-5.3-codex-low";
2366
+ case "gpt-5-codex-medium":
2367
+ return "gpt-5.3-codex-medium";
2368
+ case "gpt-5-codex-high":
2369
+ return "gpt-5.3-codex-high";
2370
+ default:
2371
+ return trimmed;
2361
2372
  }
2362
2373
  }
2363
2374
  function parseEffortSuffix(model) {
2364
2375
  const m = String(model || "").trim();
2365
2376
  if (!m) return null;
2377
+ if (m.endsWith("-xhigh")) return "xhigh";
2366
2378
  if (m.endsWith("-low")) return "low";
2367
2379
  if (m.endsWith("-medium")) return "medium";
2368
2380
  if (m.endsWith("-high")) return "high";
2369
2381
  return null;
2370
2382
  }
2371
2383
  function parseCodexModelTarget(model) {
2372
- const trimmed = String(model || "").trim();
2384
+ const trimmed = normalizeLegacyModelAlias(model);
2373
2385
  if (!trimmed) return null;
2374
- if (trimmed === "gpt-5-minimal" || trimmed === "gpt-5-low" || trimmed === "gpt-5-medium" || trimmed === "gpt-5-high" || trimmed === "gpt-5-codex" || trimmed.startsWith("gpt-5-codex-") || trimmed === "gpt-5.3-codex" || trimmed.startsWith("gpt-5.3-codex-")) {
2375
- if (trimmed === "gpt-5-codex" || trimmed.startsWith("gpt-5-codex-")) return "gpt-5.2-codex";
2386
+ const isGpt54ReasoningToken = trimmed === "gpt-5.4" || trimmed === "gpt-5.4-low" || trimmed === "gpt-5.4-medium" || trimmed === "gpt-5.4-high" || trimmed === "gpt-5.4-xhigh";
2387
+ if (isGpt54ReasoningToken || trimmed === "gpt-5.3-codex" || trimmed.startsWith("gpt-5.3-codex-")) {
2376
2388
  if (trimmed === "gpt-5.3-codex" || trimmed.startsWith("gpt-5.3-codex-")) return "gpt-5.3-codex";
2377
- return "gpt-5.2";
2389
+ return "gpt-5.4";
2378
2390
  }
2379
2391
  return null;
2380
2392
  }
2381
2393
  function resolveCodexModelOverride(rawModel) {
2382
- const model = typeof rawModel === "string" ? rawModel.trim() : "";
2394
+ const model = normalizeLegacyModelAlias(typeof rawModel === "string" ? rawModel.trim() : "");
2383
2395
  if (!model) return {};
2384
2396
  const effort = parseEffortSuffix(model);
2385
2397
  const codexModelTarget = parseCodexModelTarget(model);
@@ -2399,12 +2411,6 @@ function resolveCodexModelOverride(rawModel) {
2399
2411
  }
2400
2412
  };
2401
2413
  }
2402
- const isChatGptAuth = readCodexAuthIsChatGptAccount();
2403
- if (!isChatGptAuth) return { config: { model } };
2404
- if (model.startsWith("gpt-5-")) {
2405
- const nextEffort = effort ?? "medium";
2406
- return { config: { model: "gpt-5.2", model_reasoning_effort: nextEffort } };
2407
- }
2408
2414
  return { config: { model } };
2409
2415
  }
2410
2416
 
@@ -2,7 +2,7 @@
2
2
 
3
3
  var ink = require('ink');
4
4
  var React = require('react');
5
- var types = require('./types-CN-EDgzo.cjs');
5
+ var types = require('./types-DQ4IqofE.cjs');
6
6
  var index_js = require('@modelcontextprotocol/sdk/client/index.js');
7
7
  var z = require('zod');
8
8
  var types_js = require('@modelcontextprotocol/sdk/types.js');
@@ -16,7 +16,7 @@ var process$1 = require('node:process');
16
16
  var node_stream = require('node:stream');
17
17
  var stdio_js$1 = require('@modelcontextprotocol/sdk/client/stdio.js');
18
18
  var stdio_js = require('@modelcontextprotocol/sdk/shared/stdio.js');
19
- var index = require('./index-wU3LFfZh.cjs');
19
+ var index = require('./index-CG7Ouk31.cjs');
20
20
  require('axios');
21
21
  require('node:events');
22
22
  require('socket.io-client');
@@ -2350,38 +2350,50 @@ function hashCodexSessionModeFromEnhancedMode(mode) {
2350
2350
  }
2351
2351
 
2352
2352
  const MIN_CODEX_CLI_FOR_GPT_53_CODEX = { major: 0, minor: 104, patch: 0 };
2353
- function readCodexAuthIsChatGptAccount() {
2354
- try {
2355
- const authPath = path.join(os.homedir(), ".codex", "auth.json");
2356
- const raw = fs.readFileSync(authPath, "utf8");
2357
- const parsed = JSON.parse(raw);
2358
- const accessToken = parsed?.tokens?.access_token;
2359
- if (typeof accessToken !== "string" || !accessToken) return false;
2360
- return Boolean(parsed?.tokens?.account_id) && parsed?.OPENAI_API_KEY === null;
2361
- } catch {
2362
- return false;
2353
+ function normalizeLegacyModelAlias(model) {
2354
+ const trimmed = String(model || "").trim();
2355
+ if (!trimmed) return "";
2356
+ switch (trimmed) {
2357
+ case "gpt-5":
2358
+ case "gpt-5-minimal":
2359
+ case "gpt-5-low":
2360
+ return "gpt-5.4-low";
2361
+ case "gpt-5-medium":
2362
+ return "gpt-5.4-medium";
2363
+ case "gpt-5-high":
2364
+ return "gpt-5.4-high";
2365
+ case "gpt-5-codex":
2366
+ case "gpt-5-codex-low":
2367
+ return "gpt-5.3-codex-low";
2368
+ case "gpt-5-codex-medium":
2369
+ return "gpt-5.3-codex-medium";
2370
+ case "gpt-5-codex-high":
2371
+ return "gpt-5.3-codex-high";
2372
+ default:
2373
+ return trimmed;
2363
2374
  }
2364
2375
  }
2365
2376
  function parseEffortSuffix(model) {
2366
2377
  const m = String(model || "").trim();
2367
2378
  if (!m) return null;
2379
+ if (m.endsWith("-xhigh")) return "xhigh";
2368
2380
  if (m.endsWith("-low")) return "low";
2369
2381
  if (m.endsWith("-medium")) return "medium";
2370
2382
  if (m.endsWith("-high")) return "high";
2371
2383
  return null;
2372
2384
  }
2373
2385
  function parseCodexModelTarget(model) {
2374
- const trimmed = String(model || "").trim();
2386
+ const trimmed = normalizeLegacyModelAlias(model);
2375
2387
  if (!trimmed) return null;
2376
- if (trimmed === "gpt-5-minimal" || trimmed === "gpt-5-low" || trimmed === "gpt-5-medium" || trimmed === "gpt-5-high" || trimmed === "gpt-5-codex" || trimmed.startsWith("gpt-5-codex-") || trimmed === "gpt-5.3-codex" || trimmed.startsWith("gpt-5.3-codex-")) {
2377
- if (trimmed === "gpt-5-codex" || trimmed.startsWith("gpt-5-codex-")) return "gpt-5.2-codex";
2388
+ const isGpt54ReasoningToken = trimmed === "gpt-5.4" || trimmed === "gpt-5.4-low" || trimmed === "gpt-5.4-medium" || trimmed === "gpt-5.4-high" || trimmed === "gpt-5.4-xhigh";
2389
+ if (isGpt54ReasoningToken || trimmed === "gpt-5.3-codex" || trimmed.startsWith("gpt-5.3-codex-")) {
2378
2390
  if (trimmed === "gpt-5.3-codex" || trimmed.startsWith("gpt-5.3-codex-")) return "gpt-5.3-codex";
2379
- return "gpt-5.2";
2391
+ return "gpt-5.4";
2380
2392
  }
2381
2393
  return null;
2382
2394
  }
2383
2395
  function resolveCodexModelOverride(rawModel) {
2384
- const model = typeof rawModel === "string" ? rawModel.trim() : "";
2396
+ const model = normalizeLegacyModelAlias(typeof rawModel === "string" ? rawModel.trim() : "");
2385
2397
  if (!model) return {};
2386
2398
  const effort = parseEffortSuffix(model);
2387
2399
  const codexModelTarget = parseCodexModelTarget(model);
@@ -2401,12 +2413,6 @@ function resolveCodexModelOverride(rawModel) {
2401
2413
  }
2402
2414
  };
2403
2415
  }
2404
- const isChatGptAuth = readCodexAuthIsChatGptAccount();
2405
- if (!isChatGptAuth) return { config: { model } };
2406
- if (model.startsWith("gpt-5-")) {
2407
- const nextEffort = effort ?? "medium";
2408
- return { config: { model: "gpt-5.2", model_reasoning_effort: nextEffort } };
2409
- }
2410
2416
  return { config: { model } };
2411
2417
  }
2412
2418
 
@@ -6,8 +6,8 @@ var node_crypto = require('node:crypto');
6
6
  var os = require('node:os');
7
7
  var path = require('node:path');
8
8
  var fs$2 = require('node:fs/promises');
9
- var types = require('./types-CN-EDgzo.cjs');
10
- var index = require('./index-wU3LFfZh.cjs');
9
+ var types = require('./types-DQ4IqofE.cjs');
10
+ var index = require('./index-CG7Ouk31.cjs');
11
11
  var node_child_process = require('node:child_process');
12
12
  var sdk = require('@agentclientprotocol/sdk');
13
13
  var fs = require('fs');
@@ -4,8 +4,8 @@ import { randomUUID, createHash } from 'node:crypto';
4
4
  import os__default from 'node:os';
5
5
  import path__default, { resolve, join as join$1, basename } from 'node:path';
6
6
  import { mkdir, writeFile, readFile } from 'node:fs/promises';
7
- import { l as logger, p as packageJson, A as ApiClient, c as configuration, r as readSettings, e as projectPath } from './types-DRXvc8Nt.mjs';
8
- import { s as shouldCountToolCall, c as consumeToolQuota, f as formatQuotaDeniedReason, h as hashObject, e as enforceCliVersionPolicy, i as initialMachineMetadata, n as notifyDaemonSessionStarted, M as MessageQueue2, g as buildProjectCapsule, a as setLatestUserImages, b as MessageBuffer, w as withUserImagesMarker, r as registerKillSessionHandler, d as startFlockbayServer, o as extractUserImagesMarker, p as getLatestUserImages, P as PLATFORM_SYSTEM_PROMPT, j as autoFinalizeCoordinationWorkItem, E as ElicitationHub, k as detectScreenshotsForGate, m as stopCaffeinate } from './index-DZjyS6UX.mjs';
7
+ import { l as logger, p as packageJson, A as ApiClient, c as configuration, r as readSettings, e as projectPath } from './types-Dsn3eNAB.mjs';
8
+ import { s as shouldCountToolCall, c as consumeToolQuota, f as formatQuotaDeniedReason, h as hashObject, e as enforceCliVersionPolicy, i as initialMachineMetadata, n as notifyDaemonSessionStarted, M as MessageQueue2, g as buildProjectCapsule, a as setLatestUserImages, b as MessageBuffer, w as withUserImagesMarker, r as registerKillSessionHandler, d as startFlockbayServer, o as extractUserImagesMarker, p as getLatestUserImages, P as PLATFORM_SYSTEM_PROMPT, j as autoFinalizeCoordinationWorkItem, E as ElicitationHub, k as detectScreenshotsForGate, m as stopCaffeinate } from './index-ZZAd2VNk.mjs';
9
9
  import { spawn, spawnSync } from 'node:child_process';
10
10
  import { ndJsonStream, ClientSideConnection } from '@agentclientprotocol/sdk';
11
11
  import { existsSync, readFileSync, mkdirSync, writeFileSync } from 'fs';
@@ -44,7 +44,7 @@ function _interopNamespaceDefault(e) {
44
44
  var z__namespace = /*#__PURE__*/_interopNamespaceDefault(z);
45
45
 
46
46
  var name = "flockbay";
47
- var version = "0.10.51";
47
+ var version = "0.10.53";
48
48
  var description = "Flockbay CLI (local agent + daemon)";
49
49
  var author = "Eduardo Orellana";
50
50
  var license = "UNLICENSED";
@@ -832,7 +832,7 @@ class RpcHandlerManager {
832
832
  }
833
833
  }
834
834
 
835
- const __dirname$1 = path$1.dirname(url.fileURLToPath((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('types-CN-EDgzo.cjs', document.baseURI).href))));
835
+ const __dirname$1 = path$1.dirname(url.fileURLToPath((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('types-DQ4IqofE.cjs', document.baseURI).href))));
836
836
  function projectPath() {
837
837
  const path = path$1.resolve(__dirname$1, "..");
838
838
  return path;
@@ -1053,6 +1053,185 @@ ${hints.join("\n\n")}` : "";
1053
1053
  return response;
1054
1054
  }
1055
1055
 
1056
+ function normalizeWindowsPath(value) {
1057
+ return path.win32.normalize(String(value || "").trim()).replace(/[\\/]+$/, "");
1058
+ }
1059
+ function equalsIgnoreCaseWindows(a, b) {
1060
+ return normalizeWindowsPath(a || "").toLowerCase() === normalizeWindowsPath(b || "").toLowerCase();
1061
+ }
1062
+ function extractUprojectPathFromCommandLine(commandLine) {
1063
+ const raw = String(commandLine || "").trim();
1064
+ if (!raw) return null;
1065
+ const matches = Array.from(raw.matchAll(/"([^"\r\n]+?\.uproject)"|([^\s"]+?\.uproject)/gi));
1066
+ for (const match of matches) {
1067
+ const candidate = String(match[1] || match[2] || "").trim();
1068
+ if (!candidate) continue;
1069
+ return normalizeWindowsPath(candidate);
1070
+ }
1071
+ return null;
1072
+ }
1073
+ function inferEngineRootFromExecutablePath(executablePath) {
1074
+ const normalized = normalizeWindowsPath(executablePath);
1075
+ if (!normalized) return null;
1076
+ const marker = `${path.win32.sep}Engine${path.win32.sep}Binaries${path.win32.sep}`;
1077
+ const idx = normalized.toLowerCase().indexOf(marker.toLowerCase());
1078
+ if (idx === -1) return null;
1079
+ return normalized.slice(0, idx);
1080
+ }
1081
+ function compareCreationDateDesc(a, b) {
1082
+ const aa = String(a || "").trim();
1083
+ const bb = String(b || "").trim();
1084
+ return bb.localeCompare(aa);
1085
+ }
1086
+ function parseRunningUnrealEditorProcessesFromWindowsJson(input) {
1087
+ const engineRoot = String(input.engineRoot || "").trim();
1088
+ const wantedEngineRoot = engineRoot ? normalizeWindowsPath(engineRoot) : "";
1089
+ const raw = String(input.raw || "").trim();
1090
+ if (!raw) return [];
1091
+ let parsed;
1092
+ try {
1093
+ parsed = JSON.parse(raw);
1094
+ } catch {
1095
+ return [];
1096
+ }
1097
+ const records = (Array.isArray(parsed) ? parsed : [parsed]).filter(Boolean);
1098
+ const out = [];
1099
+ for (const record of records) {
1100
+ const uprojectPath = extractUprojectPathFromCommandLine(String(record?.CommandLine || ""));
1101
+ const executablePath = record?.ExecutablePath ? normalizeWindowsPath(record.ExecutablePath) : null;
1102
+ const inferredEngineRoot = executablePath ? inferEngineRootFromExecutablePath(executablePath) : null;
1103
+ if (wantedEngineRoot && !equalsIgnoreCaseWindows(inferredEngineRoot, wantedEngineRoot)) continue;
1104
+ const processIdNumber = Number(record?.ProcessId);
1105
+ out.push({
1106
+ processId: Number.isFinite(processIdNumber) && processIdNumber > 0 ? processIdNumber : null,
1107
+ executablePath,
1108
+ engineRoot: inferredEngineRoot,
1109
+ uprojectPath,
1110
+ commandLine: record?.CommandLine ? String(record.CommandLine) : null,
1111
+ creationDate: record?.CreationDate ? String(record.CreationDate) : null
1112
+ });
1113
+ }
1114
+ out.sort((a, b) => compareCreationDateDesc(a.creationDate, b.creationDate));
1115
+ return out;
1116
+ }
1117
+ function parseRunningUnrealEditorProcessesFromGetProcessJson(input) {
1118
+ const engineRoot = String(input.engineRoot || "").trim();
1119
+ const wantedEngineRoot = engineRoot ? normalizeWindowsPath(engineRoot) : "";
1120
+ const raw = String(input.raw || "").trim();
1121
+ if (!raw) return [];
1122
+ let parsed;
1123
+ try {
1124
+ parsed = JSON.parse(raw);
1125
+ } catch {
1126
+ return [];
1127
+ }
1128
+ const records = (Array.isArray(parsed) ? parsed : [parsed]).filter(Boolean);
1129
+ const out = [];
1130
+ for (const record of records) {
1131
+ const executablePath = record?.Path ? normalizeWindowsPath(record.Path) : null;
1132
+ const inferredEngineRoot = executablePath ? inferEngineRootFromExecutablePath(executablePath) : null;
1133
+ if (wantedEngineRoot && !equalsIgnoreCaseWindows(inferredEngineRoot, wantedEngineRoot)) continue;
1134
+ const processIdNumber = Number(record?.Id);
1135
+ out.push({
1136
+ processId: Number.isFinite(processIdNumber) && processIdNumber > 0 ? processIdNumber : null,
1137
+ executablePath,
1138
+ engineRoot: inferredEngineRoot,
1139
+ uprojectPath: null,
1140
+ commandLine: null,
1141
+ creationDate: record?.StartTime ? String(record.StartTime) : null
1142
+ });
1143
+ }
1144
+ out.sort((a, b) => compareCreationDateDesc(a.creationDate, b.creationDate));
1145
+ return out;
1146
+ }
1147
+ function parseRunningUnrealEditorProcessesFromGetProcessMinimalJson(input) {
1148
+ const raw = String(input.raw || "").trim();
1149
+ if (!raw) return [];
1150
+ let parsed;
1151
+ try {
1152
+ parsed = JSON.parse(raw);
1153
+ } catch {
1154
+ return [];
1155
+ }
1156
+ const records = (Array.isArray(parsed) ? parsed : [parsed]).filter(Boolean);
1157
+ const out = [];
1158
+ for (const record of records) {
1159
+ const processIdNumber = Number(record?.Id);
1160
+ out.push({
1161
+ processId: Number.isFinite(processIdNumber) && processIdNumber > 0 ? processIdNumber : null,
1162
+ executablePath: null,
1163
+ engineRoot: null,
1164
+ uprojectPath: null,
1165
+ commandLine: null,
1166
+ creationDate: record?.StartTime ? String(record.StartTime) : null
1167
+ });
1168
+ }
1169
+ out.sort((a, b) => compareCreationDateDesc(a.creationDate, b.creationDate));
1170
+ return out;
1171
+ }
1172
+ function detectRunningUnrealEditorProcess(options) {
1173
+ if (process.platform !== "win32") return null;
1174
+ const execFileSyncImpl = options?.execFileSyncImpl || node_child_process.execFileSync;
1175
+ const win32Script = [
1176
+ '$ErrorActionPreference = "Stop"',
1177
+ `$procs = Get-CimInstance Win32_Process -Filter "Name = 'UnrealEditor.exe'" | Select-Object ProcessId, ExecutablePath, CommandLine, CreationDate`,
1178
+ 'if ($null -eq $procs) { "[]" } else { $procs | ConvertTo-Json -Compress -Depth 3 }'
1179
+ ].join("; ");
1180
+ try {
1181
+ const raw = execFileSyncImpl("powershell.exe", ["-NoProfile", "-Command", win32Script], {
1182
+ encoding: "utf8",
1183
+ windowsHide: true,
1184
+ timeout: 1500
1185
+ });
1186
+ const matches = parseRunningUnrealEditorProcessesFromWindowsJson({
1187
+ raw: typeof raw === "string" ? raw : String(raw || ""),
1188
+ engineRoot: options?.engineRoot
1189
+ });
1190
+ return matches[0] || null;
1191
+ } catch {
1192
+ const getProcessScript = [
1193
+ '$ErrorActionPreference = "Stop"',
1194
+ "$procs = Get-Process UnrealEditor -ErrorAction SilentlyContinue | Select-Object Id, Path, StartTime",
1195
+ 'if ($null -eq $procs) { "[]" } else { $procs | ConvertTo-Json -Compress -Depth 3 }'
1196
+ ].join("; ");
1197
+ try {
1198
+ const raw = execFileSyncImpl("powershell.exe", ["-NoProfile", "-Command", getProcessScript], {
1199
+ encoding: "utf8",
1200
+ windowsHide: true,
1201
+ timeout: 1e3
1202
+ });
1203
+ const matches = parseRunningUnrealEditorProcessesFromGetProcessJson({
1204
+ raw: typeof raw === "string" ? raw : String(raw || ""),
1205
+ engineRoot: options?.engineRoot
1206
+ });
1207
+ return matches[0] || null;
1208
+ } catch {
1209
+ const getProcessMinimalScript = [
1210
+ '$ErrorActionPreference = "Stop"',
1211
+ "$procs = Get-Process UnrealEditor -ErrorAction SilentlyContinue | Select-Object Id, StartTime",
1212
+ 'if ($null -eq $procs) { "[]" } else { $procs | ConvertTo-Json -Compress -Depth 3 }'
1213
+ ].join("; ");
1214
+ try {
1215
+ const raw = execFileSyncImpl("powershell.exe", ["-NoProfile", "-Command", getProcessMinimalScript], {
1216
+ encoding: "utf8",
1217
+ windowsHide: true,
1218
+ timeout: 1e3
1219
+ });
1220
+ const matches = parseRunningUnrealEditorProcessesFromGetProcessMinimalJson({
1221
+ raw: typeof raw === "string" ? raw : String(raw || "")
1222
+ });
1223
+ return matches[0] || null;
1224
+ } catch {
1225
+ return null;
1226
+ }
1227
+ }
1228
+ }
1229
+ }
1230
+ function detectRunningUnrealEditorProject(options) {
1231
+ const match = detectRunningUnrealEditorProcess(options);
1232
+ return match?.uprojectPath ? match : null;
1233
+ }
1234
+
1056
1235
  function getPathApiForPlatform(platform) {
1057
1236
  return platform === "win32" ? path$1.win32 : path$1.posix;
1058
1237
  }
@@ -1935,13 +2114,20 @@ function registerCommonHandlers(rpcHandlerManager, workingDirectory, coordinatio
1935
2114
  requiredCommands
1936
2115
  }
1937
2116
  };
2117
+ const detectedEditorProcess = detectRunningUnrealEditorProcess();
2118
+ if (detectedEditorProcess?.uprojectPath) {
2119
+ baseResponse.runningProjectUprojectPath = detectedEditorProcess.uprojectPath;
2120
+ }
2121
+ if (detectedEditorProcess?.engineRoot) {
2122
+ baseResponse.inferredEngineRoot = detectedEditorProcess.engineRoot ?? null;
2123
+ }
1938
2124
  try {
1939
2125
  await sendUnrealMcpTcpCommand({ type: "ping", host, port, timeoutMs });
1940
2126
  } catch (err) {
1941
2127
  const message = err instanceof Error ? err.message : String(err);
1942
2128
  return {
1943
2129
  ...baseResponse,
1944
- status: "not_running",
2130
+ status: detectedEditorProcess ? "editor_open_unreachable" : "not_running",
1945
2131
  reachable: false,
1946
2132
  error: message
1947
2133
  };
@@ -1973,6 +2159,7 @@ function registerCommonHandlers(rpcHandlerManager, workingDirectory, coordinatio
1973
2159
  const commands = Array.isArray(running?.commands) ? running.commands.filter((c) => typeof c === "string").map((c) => c.trim()).filter(Boolean) : [];
1974
2160
  const missingCommands = requiredCommands.filter((c) => !commands.includes(c));
1975
2161
  const inferredEngineRoot = baseDir ? inferEngineRootFromPluginBaseDir(baseDir) : null;
2162
+ const runningProject = detectRunningUnrealEditorProject(inferredEngineRoot ? { engineRoot: inferredEngineRoot } : {});
1976
2163
  let play = null;
1977
2164
  if (commands.includes("get_play_in_editor_status")) {
1978
2165
  try {
@@ -1991,6 +2178,7 @@ function registerCommonHandlers(rpcHandlerManager, workingDirectory, coordinatio
1991
2178
  ...baseResponse,
1992
2179
  status,
1993
2180
  inferredEngineRoot,
2181
+ runningProjectUprojectPath: runningProject?.uprojectPath ?? null,
1994
2182
  running: {
1995
2183
  baseDir,
1996
2184
  versionName,
@@ -4092,11 +4280,14 @@ function getUnrealMcpPluginDiskStatus(params) {
4092
4280
  const checkedAtMs = Date.now();
4093
4281
  const engineRoot = String(params?.engineRoot || "").trim();
4094
4282
  const installScope = String(params?.installScope || "auto");
4095
- const projectUprojectPathRaw = typeof params?.projectUprojectPath === "string" ? params.projectUprojectPath.trim() : "";
4283
+ const requestedProjectUprojectPath = typeof params?.projectUprojectPath === "string" ? params.projectUprojectPath.trim() : "";
4096
4284
  if (!engineRoot) return { success: false, error: "Missing engineRoot." };
4097
4285
  if (!looksLikeEngineRoot(engineRoot)) {
4098
4286
  return { success: false, error: `Invalid engine root (expected an Unreal Engine install folder containing Engine/Plugins): ${engineRoot}` };
4099
4287
  }
4288
+ const installedEngine = isInstalledEngineRoot(engineRoot);
4289
+ const runningProject = detectRunningUnrealEditorProject({ engineRoot });
4290
+ const projectUprojectPathRaw = runningProject?.uprojectPath || requestedProjectUprojectPath;
4100
4291
  const enginePluginsDir = path.join(engineRoot, "Engine", "Plugins");
4101
4292
  const enginePluginDir = path.join(enginePluginsDir, "FlockbayMCP");
4102
4293
  const engineUpluginPath = path.join(enginePluginDir, "FlockbayMCP.uplugin");
@@ -4164,7 +4355,7 @@ function getUnrealMcpPluginDiskStatus(params) {
4164
4355
  }
4165
4356
  const engineInstalled = engineInfo.exists && engineInfo.descriptorOk && engineInfo.hasBinaries;
4166
4357
  const projectInstalled = Boolean(project && project.exists && project.descriptorOk && project.enabledInUproject);
4167
- const effectiveScope = installScope === "engine" ? "engine" : installScope === "project" ? "project" : engineInstalled ? "engine" : project && !engineInfo.enginePluginsWritable ? "project" : "engine";
4358
+ const effectiveScope = installScope === "engine" ? "engine" : installScope === "project" ? "project" : installedEngine && project ? "project" : engineInstalled ? "engine" : project && !engineInfo.enginePluginsWritable ? "project" : "engine";
4168
4359
  const conflict = engineInfo.conflicts.length > 0;
4169
4360
  const legacyConflict = engineInfo.legacy.length > 0;
4170
4361
  const baseInstalled = effectiveScope === "engine" ? engineInstalled : projectInstalled;
@@ -4879,12 +5070,14 @@ class ApiMachineClient {
4879
5070
  async (params) => {
4880
5071
  const engineRoot = String(params?.engineRoot || "").trim();
4881
5072
  const scope = String(params?.installScope || "auto");
4882
- const projectUprojectPath = typeof params?.projectUprojectPath === "string" ? params.projectUprojectPath.trim() : "";
5073
+ const requestedProjectUprojectPath = typeof params?.projectUprojectPath === "string" ? params.projectUprojectPath.trim() : "";
4883
5074
  const enginePluginsDir = path.join(engineRoot, "Engine", "Plugins");
4884
5075
  const enginePluginDir = path.join(enginePluginsDir, "FlockbayMCP");
4885
5076
  const enginePluginUplugin = path.join(enginePluginDir, "FlockbayMCP.uplugin");
4886
5077
  const enginePluginHasBinaries = fs.existsSync(path.join(enginePluginDir, "Binaries"));
4887
5078
  const installedEngine = isInstalledEngineRoot(engineRoot);
5079
+ const runningProject = installedEngine ? detectRunningUnrealEditorProject({ engineRoot }) : null;
5080
+ const projectUprojectPath = runningProject?.uprojectPath || requestedProjectUprojectPath;
4888
5081
  if (installedEngine) {
4889
5082
  const quarantine = quarantineLegacyEnginePlugins(engineRoot);
4890
5083
  if (!quarantine.ok) return { success: false, error: quarantine.errorMessage };
@@ -18,12 +18,12 @@ import { fileURLToPath } from 'url';
18
18
  import process$1 from 'node:process';
19
19
  import { platform } from 'os';
20
20
  import net from 'node:net';
21
- import { spawn as spawn$1 } from 'node:child_process';
21
+ import { execFileSync, spawn as spawn$1 } from 'node:child_process';
22
22
  import { createServer } from 'http';
23
23
  import open$2 from 'open';
24
24
 
25
25
  var name = "flockbay";
26
- var version = "0.10.51";
26
+ var version = "0.10.53";
27
27
  var description = "Flockbay CLI (local agent + daemon)";
28
28
  var author = "Eduardo Orellana";
29
29
  var license = "UNLICENSED";
@@ -1032,6 +1032,185 @@ ${hints.join("\n\n")}` : "";
1032
1032
  return response;
1033
1033
  }
1034
1034
 
1035
+ function normalizeWindowsPath(value) {
1036
+ return path__default.win32.normalize(String(value || "").trim()).replace(/[\\/]+$/, "");
1037
+ }
1038
+ function equalsIgnoreCaseWindows(a, b) {
1039
+ return normalizeWindowsPath(a || "").toLowerCase() === normalizeWindowsPath(b || "").toLowerCase();
1040
+ }
1041
+ function extractUprojectPathFromCommandLine(commandLine) {
1042
+ const raw = String(commandLine || "").trim();
1043
+ if (!raw) return null;
1044
+ const matches = Array.from(raw.matchAll(/"([^"\r\n]+?\.uproject)"|([^\s"]+?\.uproject)/gi));
1045
+ for (const match of matches) {
1046
+ const candidate = String(match[1] || match[2] || "").trim();
1047
+ if (!candidate) continue;
1048
+ return normalizeWindowsPath(candidate);
1049
+ }
1050
+ return null;
1051
+ }
1052
+ function inferEngineRootFromExecutablePath(executablePath) {
1053
+ const normalized = normalizeWindowsPath(executablePath);
1054
+ if (!normalized) return null;
1055
+ const marker = `${path__default.win32.sep}Engine${path__default.win32.sep}Binaries${path__default.win32.sep}`;
1056
+ const idx = normalized.toLowerCase().indexOf(marker.toLowerCase());
1057
+ if (idx === -1) return null;
1058
+ return normalized.slice(0, idx);
1059
+ }
1060
+ function compareCreationDateDesc(a, b) {
1061
+ const aa = String(a || "").trim();
1062
+ const bb = String(b || "").trim();
1063
+ return bb.localeCompare(aa);
1064
+ }
1065
+ function parseRunningUnrealEditorProcessesFromWindowsJson(input) {
1066
+ const engineRoot = String(input.engineRoot || "").trim();
1067
+ const wantedEngineRoot = engineRoot ? normalizeWindowsPath(engineRoot) : "";
1068
+ const raw = String(input.raw || "").trim();
1069
+ if (!raw) return [];
1070
+ let parsed;
1071
+ try {
1072
+ parsed = JSON.parse(raw);
1073
+ } catch {
1074
+ return [];
1075
+ }
1076
+ const records = (Array.isArray(parsed) ? parsed : [parsed]).filter(Boolean);
1077
+ const out = [];
1078
+ for (const record of records) {
1079
+ const uprojectPath = extractUprojectPathFromCommandLine(String(record?.CommandLine || ""));
1080
+ const executablePath = record?.ExecutablePath ? normalizeWindowsPath(record.ExecutablePath) : null;
1081
+ const inferredEngineRoot = executablePath ? inferEngineRootFromExecutablePath(executablePath) : null;
1082
+ if (wantedEngineRoot && !equalsIgnoreCaseWindows(inferredEngineRoot, wantedEngineRoot)) continue;
1083
+ const processIdNumber = Number(record?.ProcessId);
1084
+ out.push({
1085
+ processId: Number.isFinite(processIdNumber) && processIdNumber > 0 ? processIdNumber : null,
1086
+ executablePath,
1087
+ engineRoot: inferredEngineRoot,
1088
+ uprojectPath,
1089
+ commandLine: record?.CommandLine ? String(record.CommandLine) : null,
1090
+ creationDate: record?.CreationDate ? String(record.CreationDate) : null
1091
+ });
1092
+ }
1093
+ out.sort((a, b) => compareCreationDateDesc(a.creationDate, b.creationDate));
1094
+ return out;
1095
+ }
1096
+ function parseRunningUnrealEditorProcessesFromGetProcessJson(input) {
1097
+ const engineRoot = String(input.engineRoot || "").trim();
1098
+ const wantedEngineRoot = engineRoot ? normalizeWindowsPath(engineRoot) : "";
1099
+ const raw = String(input.raw || "").trim();
1100
+ if (!raw) return [];
1101
+ let parsed;
1102
+ try {
1103
+ parsed = JSON.parse(raw);
1104
+ } catch {
1105
+ return [];
1106
+ }
1107
+ const records = (Array.isArray(parsed) ? parsed : [parsed]).filter(Boolean);
1108
+ const out = [];
1109
+ for (const record of records) {
1110
+ const executablePath = record?.Path ? normalizeWindowsPath(record.Path) : null;
1111
+ const inferredEngineRoot = executablePath ? inferEngineRootFromExecutablePath(executablePath) : null;
1112
+ if (wantedEngineRoot && !equalsIgnoreCaseWindows(inferredEngineRoot, wantedEngineRoot)) continue;
1113
+ const processIdNumber = Number(record?.Id);
1114
+ out.push({
1115
+ processId: Number.isFinite(processIdNumber) && processIdNumber > 0 ? processIdNumber : null,
1116
+ executablePath,
1117
+ engineRoot: inferredEngineRoot,
1118
+ uprojectPath: null,
1119
+ commandLine: null,
1120
+ creationDate: record?.StartTime ? String(record.StartTime) : null
1121
+ });
1122
+ }
1123
+ out.sort((a, b) => compareCreationDateDesc(a.creationDate, b.creationDate));
1124
+ return out;
1125
+ }
1126
+ function parseRunningUnrealEditorProcessesFromGetProcessMinimalJson(input) {
1127
+ const raw = String(input.raw || "").trim();
1128
+ if (!raw) return [];
1129
+ let parsed;
1130
+ try {
1131
+ parsed = JSON.parse(raw);
1132
+ } catch {
1133
+ return [];
1134
+ }
1135
+ const records = (Array.isArray(parsed) ? parsed : [parsed]).filter(Boolean);
1136
+ const out = [];
1137
+ for (const record of records) {
1138
+ const processIdNumber = Number(record?.Id);
1139
+ out.push({
1140
+ processId: Number.isFinite(processIdNumber) && processIdNumber > 0 ? processIdNumber : null,
1141
+ executablePath: null,
1142
+ engineRoot: null,
1143
+ uprojectPath: null,
1144
+ commandLine: null,
1145
+ creationDate: record?.StartTime ? String(record.StartTime) : null
1146
+ });
1147
+ }
1148
+ out.sort((a, b) => compareCreationDateDesc(a.creationDate, b.creationDate));
1149
+ return out;
1150
+ }
1151
+ function detectRunningUnrealEditorProcess(options) {
1152
+ if (process.platform !== "win32") return null;
1153
+ const execFileSyncImpl = options?.execFileSyncImpl || execFileSync;
1154
+ const win32Script = [
1155
+ '$ErrorActionPreference = "Stop"',
1156
+ `$procs = Get-CimInstance Win32_Process -Filter "Name = 'UnrealEditor.exe'" | Select-Object ProcessId, ExecutablePath, CommandLine, CreationDate`,
1157
+ 'if ($null -eq $procs) { "[]" } else { $procs | ConvertTo-Json -Compress -Depth 3 }'
1158
+ ].join("; ");
1159
+ try {
1160
+ const raw = execFileSyncImpl("powershell.exe", ["-NoProfile", "-Command", win32Script], {
1161
+ encoding: "utf8",
1162
+ windowsHide: true,
1163
+ timeout: 1500
1164
+ });
1165
+ const matches = parseRunningUnrealEditorProcessesFromWindowsJson({
1166
+ raw: typeof raw === "string" ? raw : String(raw || ""),
1167
+ engineRoot: options?.engineRoot
1168
+ });
1169
+ return matches[0] || null;
1170
+ } catch {
1171
+ const getProcessScript = [
1172
+ '$ErrorActionPreference = "Stop"',
1173
+ "$procs = Get-Process UnrealEditor -ErrorAction SilentlyContinue | Select-Object Id, Path, StartTime",
1174
+ 'if ($null -eq $procs) { "[]" } else { $procs | ConvertTo-Json -Compress -Depth 3 }'
1175
+ ].join("; ");
1176
+ try {
1177
+ const raw = execFileSyncImpl("powershell.exe", ["-NoProfile", "-Command", getProcessScript], {
1178
+ encoding: "utf8",
1179
+ windowsHide: true,
1180
+ timeout: 1e3
1181
+ });
1182
+ const matches = parseRunningUnrealEditorProcessesFromGetProcessJson({
1183
+ raw: typeof raw === "string" ? raw : String(raw || ""),
1184
+ engineRoot: options?.engineRoot
1185
+ });
1186
+ return matches[0] || null;
1187
+ } catch {
1188
+ const getProcessMinimalScript = [
1189
+ '$ErrorActionPreference = "Stop"',
1190
+ "$procs = Get-Process UnrealEditor -ErrorAction SilentlyContinue | Select-Object Id, StartTime",
1191
+ 'if ($null -eq $procs) { "[]" } else { $procs | ConvertTo-Json -Compress -Depth 3 }'
1192
+ ].join("; ");
1193
+ try {
1194
+ const raw = execFileSyncImpl("powershell.exe", ["-NoProfile", "-Command", getProcessMinimalScript], {
1195
+ encoding: "utf8",
1196
+ windowsHide: true,
1197
+ timeout: 1e3
1198
+ });
1199
+ const matches = parseRunningUnrealEditorProcessesFromGetProcessMinimalJson({
1200
+ raw: typeof raw === "string" ? raw : String(raw || "")
1201
+ });
1202
+ return matches[0] || null;
1203
+ } catch {
1204
+ return null;
1205
+ }
1206
+ }
1207
+ }
1208
+ }
1209
+ function detectRunningUnrealEditorProject(options) {
1210
+ const match = detectRunningUnrealEditorProcess(options);
1211
+ return match?.uprojectPath ? match : null;
1212
+ }
1213
+
1035
1214
  function getPathApiForPlatform(platform) {
1036
1215
  return platform === "win32" ? path.win32 : path.posix;
1037
1216
  }
@@ -1914,13 +2093,20 @@ function registerCommonHandlers(rpcHandlerManager, workingDirectory, coordinatio
1914
2093
  requiredCommands
1915
2094
  }
1916
2095
  };
2096
+ const detectedEditorProcess = detectRunningUnrealEditorProcess();
2097
+ if (detectedEditorProcess?.uprojectPath) {
2098
+ baseResponse.runningProjectUprojectPath = detectedEditorProcess.uprojectPath;
2099
+ }
2100
+ if (detectedEditorProcess?.engineRoot) {
2101
+ baseResponse.inferredEngineRoot = detectedEditorProcess.engineRoot ?? null;
2102
+ }
1917
2103
  try {
1918
2104
  await sendUnrealMcpTcpCommand({ type: "ping", host, port, timeoutMs });
1919
2105
  } catch (err) {
1920
2106
  const message = err instanceof Error ? err.message : String(err);
1921
2107
  return {
1922
2108
  ...baseResponse,
1923
- status: "not_running",
2109
+ status: detectedEditorProcess ? "editor_open_unreachable" : "not_running",
1924
2110
  reachable: false,
1925
2111
  error: message
1926
2112
  };
@@ -1952,6 +2138,7 @@ function registerCommonHandlers(rpcHandlerManager, workingDirectory, coordinatio
1952
2138
  const commands = Array.isArray(running?.commands) ? running.commands.filter((c) => typeof c === "string").map((c) => c.trim()).filter(Boolean) : [];
1953
2139
  const missingCommands = requiredCommands.filter((c) => !commands.includes(c));
1954
2140
  const inferredEngineRoot = baseDir ? inferEngineRootFromPluginBaseDir(baseDir) : null;
2141
+ const runningProject = detectRunningUnrealEditorProject(inferredEngineRoot ? { engineRoot: inferredEngineRoot } : {});
1955
2142
  let play = null;
1956
2143
  if (commands.includes("get_play_in_editor_status")) {
1957
2144
  try {
@@ -1970,6 +2157,7 @@ function registerCommonHandlers(rpcHandlerManager, workingDirectory, coordinatio
1970
2157
  ...baseResponse,
1971
2158
  status,
1972
2159
  inferredEngineRoot,
2160
+ runningProjectUprojectPath: runningProject?.uprojectPath ?? null,
1973
2161
  running: {
1974
2162
  baseDir,
1975
2163
  versionName,
@@ -4071,11 +4259,14 @@ function getUnrealMcpPluginDiskStatus(params) {
4071
4259
  const checkedAtMs = Date.now();
4072
4260
  const engineRoot = String(params?.engineRoot || "").trim();
4073
4261
  const installScope = String(params?.installScope || "auto");
4074
- const projectUprojectPathRaw = typeof params?.projectUprojectPath === "string" ? params.projectUprojectPath.trim() : "";
4262
+ const requestedProjectUprojectPath = typeof params?.projectUprojectPath === "string" ? params.projectUprojectPath.trim() : "";
4075
4263
  if (!engineRoot) return { success: false, error: "Missing engineRoot." };
4076
4264
  if (!looksLikeEngineRoot(engineRoot)) {
4077
4265
  return { success: false, error: `Invalid engine root (expected an Unreal Engine install folder containing Engine/Plugins): ${engineRoot}` };
4078
4266
  }
4267
+ const installedEngine = isInstalledEngineRoot(engineRoot);
4268
+ const runningProject = detectRunningUnrealEditorProject({ engineRoot });
4269
+ const projectUprojectPathRaw = runningProject?.uprojectPath || requestedProjectUprojectPath;
4079
4270
  const enginePluginsDir = path__default.join(engineRoot, "Engine", "Plugins");
4080
4271
  const enginePluginDir = path__default.join(enginePluginsDir, "FlockbayMCP");
4081
4272
  const engineUpluginPath = path__default.join(enginePluginDir, "FlockbayMCP.uplugin");
@@ -4143,7 +4334,7 @@ function getUnrealMcpPluginDiskStatus(params) {
4143
4334
  }
4144
4335
  const engineInstalled = engineInfo.exists && engineInfo.descriptorOk && engineInfo.hasBinaries;
4145
4336
  const projectInstalled = Boolean(project && project.exists && project.descriptorOk && project.enabledInUproject);
4146
- const effectiveScope = installScope === "engine" ? "engine" : installScope === "project" ? "project" : engineInstalled ? "engine" : project && !engineInfo.enginePluginsWritable ? "project" : "engine";
4337
+ const effectiveScope = installScope === "engine" ? "engine" : installScope === "project" ? "project" : installedEngine && project ? "project" : engineInstalled ? "engine" : project && !engineInfo.enginePluginsWritable ? "project" : "engine";
4147
4338
  const conflict = engineInfo.conflicts.length > 0;
4148
4339
  const legacyConflict = engineInfo.legacy.length > 0;
4149
4340
  const baseInstalled = effectiveScope === "engine" ? engineInstalled : projectInstalled;
@@ -4858,12 +5049,14 @@ class ApiMachineClient {
4858
5049
  async (params) => {
4859
5050
  const engineRoot = String(params?.engineRoot || "").trim();
4860
5051
  const scope = String(params?.installScope || "auto");
4861
- const projectUprojectPath = typeof params?.projectUprojectPath === "string" ? params.projectUprojectPath.trim() : "";
5052
+ const requestedProjectUprojectPath = typeof params?.projectUprojectPath === "string" ? params.projectUprojectPath.trim() : "";
4862
5053
  const enginePluginsDir = path__default.join(engineRoot, "Engine", "Plugins");
4863
5054
  const enginePluginDir = path__default.join(enginePluginsDir, "FlockbayMCP");
4864
5055
  const enginePluginUplugin = path__default.join(enginePluginDir, "FlockbayMCP.uplugin");
4865
5056
  const enginePluginHasBinaries = fs__default.existsSync(path__default.join(enginePluginDir, "Binaries"));
4866
5057
  const installedEngine = isInstalledEngineRoot(engineRoot);
5058
+ const runningProject = installedEngine ? detectRunningUnrealEditorProject({ engineRoot }) : null;
5059
+ const projectUprojectPath = runningProject?.uprojectPath || requestedProjectUprojectPath;
4867
5060
  if (installedEngine) {
4868
5061
  const quarantine = quarantineLegacyEnginePlugins(engineRoot);
4869
5062
  if (!quarantine.ok) return { success: false, error: quarantine.errorMessage };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "flockbay",
3
- "version": "0.10.51",
3
+ "version": "0.10.53",
4
4
  "description": "Flockbay CLI (local agent + daemon)",
5
5
  "author": "Eduardo Orellana",
6
6
  "license": "UNLICENSED",