flockbay 0.10.15 → 0.10.16
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/codex/flockbayMcpStdioBridge.cjs +339 -0
- package/dist/codex/flockbayMcpStdioBridge.mjs +339 -0
- package/dist/{index--o4BPz5o.cjs → index-Cau-_Qvn.cjs} +2683 -609
- package/dist/{index-CUp3juDS.mjs → index-DtmFQzXY.mjs} +2684 -611
- package/dist/index.cjs +3 -5
- package/dist/index.mjs +3 -5
- package/dist/lib.cjs +7 -9
- package/dist/lib.d.cts +219 -531
- package/dist/lib.d.mts +219 -531
- package/dist/lib.mjs +7 -9
- package/dist/{runCodex-o6PCbHQ7.mjs → runCodex-Di9eHddq.mjs} +263 -42
- package/dist/{runCodex-D3eT-TvB.cjs → runCodex-DzP3VUa-.cjs} +264 -43
- package/dist/{runGemini-Bt0oEj_g.mjs → runGemini-BS6sBU_V.mjs} +63 -28
- package/dist/{runGemini-CBxZp6I7.cjs → runGemini-CpmehDQ2.cjs} +64 -29
- package/dist/{types-DGd6ea2Z.mjs → types-CwzNqYEx.mjs} +465 -1142
- package/dist/{types-C-jnUdn_.cjs → types-SUAKq-K0.cjs} +466 -1146
- package/package.json +1 -1
- package/tools/unreal-mcp/upstream/MCPGameProject/Plugins/UnrealMCP/Source/UnrealMCP/Private/Commands/UnrealMCPBlueprintCommands.cpp +195 -6
- package/tools/unreal-mcp/upstream/MCPGameProject/Plugins/UnrealMCP/Source/UnrealMCP/Private/Commands/UnrealMCPBlueprintNodeCommands.cpp +376 -5
- package/tools/unreal-mcp/upstream/MCPGameProject/Plugins/UnrealMCP/Source/UnrealMCP/Private/Commands/UnrealMCPCommandSchema.cpp +731 -0
- package/tools/unreal-mcp/upstream/MCPGameProject/Plugins/UnrealMCP/Source/UnrealMCP/Private/Commands/UnrealMCPCommonUtils.cpp +476 -8
- package/tools/unreal-mcp/upstream/MCPGameProject/Plugins/UnrealMCP/Source/UnrealMCP/Private/Commands/UnrealMCPEditorCommands.cpp +1518 -94
- package/tools/unreal-mcp/upstream/MCPGameProject/Plugins/UnrealMCP/Source/UnrealMCP/Private/MCPServerRunnable.cpp +7 -4
- package/tools/unreal-mcp/upstream/MCPGameProject/Plugins/UnrealMCP/Source/UnrealMCP/Private/UnrealMCPBridge.cpp +150 -112
- package/tools/unreal-mcp/upstream/MCPGameProject/Plugins/UnrealMCP/Source/UnrealMCP/Public/Commands/UnrealMCPBlueprintCommands.h +2 -1
- package/tools/unreal-mcp/upstream/MCPGameProject/Plugins/UnrealMCP/Source/UnrealMCP/Public/Commands/UnrealMCPBlueprintNodeCommands.h +4 -1
- package/tools/unreal-mcp/upstream/MCPGameProject/Plugins/UnrealMCP/Source/UnrealMCP/Public/Commands/UnrealMCPCommandSchema.h +42 -0
- package/tools/unreal-mcp/upstream/MCPGameProject/Plugins/UnrealMCP/Source/UnrealMCP/Public/Commands/UnrealMCPEditorCommands.h +21 -0
- package/tools/unreal-mcp/upstream/MCPGameProject/Plugins/UnrealMCP/Source/UnrealMCP/UnrealMCP.Build.cs +4 -1
- package/dist/flockbayScreenshotGate-DJX3Is5d.mjs +0 -136
- package/dist/flockbayScreenshotGate-DkxU24cR.cjs +0 -138
|
@@ -4,8 +4,8 @@ import { randomUUID, createHash } from 'node:crypto';
|
|
|
4
4
|
import os from 'node:os';
|
|
5
5
|
import path, { resolve, join as join$1, basename } from 'node:path';
|
|
6
6
|
import { mkdir, writeFile, readFile } from 'node:fs/promises';
|
|
7
|
-
import { l as logger, b as packageJson, A as ApiClient, r as readSettings, p as projectPath, c as configuration } from './types-
|
|
8
|
-
import { s as shouldCountToolCall, c as consumeToolQuota, f as formatQuotaDeniedReason, h as hashObject, i as initialMachineMetadata, n as notifyDaemonSessionStarted, M as MessageQueue2, g as buildProjectCapsule, a as setLatestUserImages, b as MessageBuffer, w as withUserImagesMarker, P as PLATFORM_SYSTEM_PROMPT, r as registerKillSessionHandler, d as startFlockbayServer,
|
|
7
|
+
import { l as logger, b as packageJson, A as ApiClient, r as readSettings, p as projectPath, c as configuration } from './types-CwzNqYEx.mjs';
|
|
8
|
+
import { s as shouldCountToolCall, c as consumeToolQuota, f as formatQuotaDeniedReason, h as hashObject, i as initialMachineMetadata, n as notifyDaemonSessionStarted, M as MessageQueue2, g as buildProjectCapsule, a as setLatestUserImages, b as MessageBuffer, w as withUserImagesMarker, P as PLATFORM_SYSTEM_PROMPT, r as registerKillSessionHandler, d as startFlockbayServer, o as extractUserImagesMarker, p as getLatestUserImages, j as autoFinalizeCoordinationWorkItem, E as ElicitationHub, k as detectScreenshotsForGate, m as stopCaffeinate } from './index-DtmFQzXY.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';
|
|
@@ -13,31 +13,28 @@ import { join } from 'path';
|
|
|
13
13
|
import { homedir } from 'os';
|
|
14
14
|
import { execSync } from 'child_process';
|
|
15
15
|
import fs__default from 'node:fs';
|
|
16
|
-
import { d as detectScreenshotsForGate } from './flockbayScreenshotGate-DJX3Is5d.mjs';
|
|
17
16
|
import 'axios';
|
|
18
|
-
import 'chalk';
|
|
19
|
-
import 'zod';
|
|
20
|
-
import 'tweetnacl';
|
|
21
17
|
import 'node:events';
|
|
22
18
|
import 'socket.io-client';
|
|
19
|
+
import 'chalk';
|
|
20
|
+
import 'zod';
|
|
23
21
|
import 'fs/promises';
|
|
24
22
|
import 'crypto';
|
|
25
23
|
import 'url';
|
|
26
24
|
import 'node:process';
|
|
27
25
|
import 'node:net';
|
|
28
|
-
import 'expo-server-sdk';
|
|
29
26
|
import 'node:readline';
|
|
30
27
|
import 'node:url';
|
|
31
28
|
import 'ps-list';
|
|
32
29
|
import 'cross-spawn';
|
|
33
30
|
import 'tmp';
|
|
34
|
-
import 'qrcode-terminal';
|
|
35
31
|
import 'open';
|
|
36
32
|
import 'fastify';
|
|
37
33
|
import 'fastify-type-provider-zod';
|
|
38
34
|
import '@modelcontextprotocol/sdk/server/mcp.js';
|
|
39
35
|
import 'node:http';
|
|
40
36
|
import '@modelcontextprotocol/sdk/server/streamableHttp.js';
|
|
37
|
+
import 'tweetnacl';
|
|
41
38
|
import 'http';
|
|
42
39
|
import 'util';
|
|
43
40
|
|
|
@@ -934,15 +931,6 @@ ${excerpt}` : base;
|
|
|
934
931
|
}
|
|
935
932
|
}
|
|
936
933
|
}
|
|
937
|
-
if (update.messageChunk) {
|
|
938
|
-
const chunk = update.messageChunk;
|
|
939
|
-
if (chunk.textDelta) {
|
|
940
|
-
this.emit({
|
|
941
|
-
type: "model-output",
|
|
942
|
-
textDelta: chunk.textDelta
|
|
943
|
-
});
|
|
944
|
-
}
|
|
945
|
-
}
|
|
946
934
|
if (update.plan) {
|
|
947
935
|
this.emit({
|
|
948
936
|
type: "event",
|
|
@@ -1878,11 +1866,14 @@ class GeminiPermissionHandler {
|
|
|
1878
1866
|
}
|
|
1879
1867
|
this.pendingRequests.clear();
|
|
1880
1868
|
this.session.updateAgentState((currentState) => {
|
|
1881
|
-
const
|
|
1882
|
-
const
|
|
1869
|
+
const pendingRaw = currentState?.requests;
|
|
1870
|
+
const pendingRequests = pendingRaw && typeof pendingRaw === "object" ? pendingRaw : {};
|
|
1871
|
+
const completedRaw = currentState?.completedRequests;
|
|
1872
|
+
const completedRequests = completedRaw && typeof completedRaw === "object" ? { ...completedRaw } : {};
|
|
1883
1873
|
for (const [id, request] of Object.entries(pendingRequests)) {
|
|
1874
|
+
const reqObj = request && typeof request === "object" ? request : { value: request };
|
|
1884
1875
|
completedRequests[id] = {
|
|
1885
|
-
...
|
|
1876
|
+
...reqObj,
|
|
1886
1877
|
completedAt: Date.now(),
|
|
1887
1878
|
status: "canceled",
|
|
1888
1879
|
reason: "Session reset"
|
|
@@ -2348,8 +2339,19 @@ async function runGemini(opts) {
|
|
|
2348
2339
|
lifecycleStateSince: Date.now(),
|
|
2349
2340
|
flavor: "gemini"
|
|
2350
2341
|
};
|
|
2351
|
-
const response = await api.getOrCreateSession({ tag: sessionTag, metadata, state });
|
|
2342
|
+
const response = opts.sessionId ? await api.getSessionById(opts.sessionId) : await api.getOrCreateSession({ tag: sessionTag, metadata, state });
|
|
2352
2343
|
const session = api.sessionSyncClient(response);
|
|
2344
|
+
if (opts.sessionId) {
|
|
2345
|
+
session.updateMetadata((currentMetadata) => ({
|
|
2346
|
+
...currentMetadata,
|
|
2347
|
+
...metadata,
|
|
2348
|
+
// Preserve user-facing fields set by other clients.
|
|
2349
|
+
name: currentMetadata?.name,
|
|
2350
|
+
summary: currentMetadata?.summary
|
|
2351
|
+
}));
|
|
2352
|
+
}
|
|
2353
|
+
await session.connectAndWait(15e3);
|
|
2354
|
+
session.keepAlive(false, "remote");
|
|
2353
2355
|
try {
|
|
2354
2356
|
logger.debug(`[START] Reporting session ${response.id} to daemon`);
|
|
2355
2357
|
const result = await notifyDaemonSessionStarted(response.id, metadata);
|
|
@@ -2396,9 +2398,13 @@ async function runGemini(opts) {
|
|
|
2396
2398
|
text: [
|
|
2397
2399
|
`You just generated ${unique.length} screenshot${unique.length === 1 ? "" : "s"}.`,
|
|
2398
2400
|
"",
|
|
2399
|
-
"Visually inspect EVERY screenshot and report:",
|
|
2400
|
-
"
|
|
2401
|
-
"
|
|
2401
|
+
"Visually inspect EVERY screenshot and report (this is for YOUR validation, not ceremony):",
|
|
2402
|
+
"1) List 2\u20135 concrete acceptance criteria for the user\u2019s request.",
|
|
2403
|
+
"2) One short bullet per image describing what you see.",
|
|
2404
|
+
"3) For each acceptance criterion: mark it as Verified / Not visible / Failed based ONLY on the screenshots.",
|
|
2405
|
+
' - If "Not visible", say what evidence is missing.',
|
|
2406
|
+
' - If "Failed", say what is wrong.',
|
|
2407
|
+
"4) If anything is not Verified: state the next tool/action you will take to fix or validate it (do not claim completion yet).",
|
|
2402
2408
|
"",
|
|
2403
2409
|
"Do not run any tools in this step."
|
|
2404
2410
|
].join("\n")
|
|
@@ -2534,8 +2540,14 @@ async function runGemini(opts) {
|
|
|
2534
2540
|
let geminiBackend = null;
|
|
2535
2541
|
let acpSessionId = null;
|
|
2536
2542
|
let wasSessionCreated = false;
|
|
2537
|
-
|
|
2543
|
+
let abortNote = null;
|
|
2544
|
+
let abortNoteSentToSession = false;
|
|
2545
|
+
async function handleAbort(note, options) {
|
|
2538
2546
|
logger.debug("[Gemini] Abort requested - stopping current task");
|
|
2547
|
+
if (typeof note === "string" && note.trim()) {
|
|
2548
|
+
abortNote = note.trim();
|
|
2549
|
+
abortNoteSentToSession = Boolean(options?.alreadySentToSession);
|
|
2550
|
+
}
|
|
2539
2551
|
session.sendCodexMessage({
|
|
2540
2552
|
type: "turn_aborted",
|
|
2541
2553
|
id: randomUUID()
|
|
@@ -2590,7 +2602,7 @@ async function runGemini(opts) {
|
|
|
2590
2602
|
process.exit(1);
|
|
2591
2603
|
}
|
|
2592
2604
|
};
|
|
2593
|
-
session.rpcHandlerManager.registerHandler("
|
|
2605
|
+
session.rpcHandlerManager.registerHandler("cancel-generation", handleAbort);
|
|
2594
2606
|
registerKillSessionHandler(session.rpcHandlerManager, handleKillSession);
|
|
2595
2607
|
const messageBuffer = new MessageBuffer();
|
|
2596
2608
|
const hasTTY = process.stdout.isTTY && process.stdin.isTTY;
|
|
@@ -2648,6 +2660,21 @@ async function runGemini(opts) {
|
|
|
2648
2660
|
}
|
|
2649
2661
|
const elicitationHub = new ElicitationHub();
|
|
2650
2662
|
const flockbayServer = await startFlockbayServer(session, { elicitationHub });
|
|
2663
|
+
const unsubscribeUnrealIssue = (() => {
|
|
2664
|
+
const onIssue = flockbayServer?.unreal?.onIssue;
|
|
2665
|
+
if (typeof onIssue !== "function") return null;
|
|
2666
|
+
return onIssue((event) => {
|
|
2667
|
+
try {
|
|
2668
|
+
const kind = typeof event?.kind === "string" ? event.kind : "unreachable";
|
|
2669
|
+
const base = typeof event?.message === "string" && event.message.trim() ? event.message.trim() : "Unreal Editor issue detected.";
|
|
2670
|
+
const msg = kind === "process_exit" ? `Unreal Editor crashed. ${base}` : `Unreal Editor is not reachable. ${base}`;
|
|
2671
|
+
session.sendSessionEvent({ type: "message", message: msg });
|
|
2672
|
+
void handleAbort(msg, { alreadySentToSession: true });
|
|
2673
|
+
} catch (err) {
|
|
2674
|
+
logger.debug("[Gemini] Failed to handle Unreal issue event", err);
|
|
2675
|
+
}
|
|
2676
|
+
});
|
|
2677
|
+
})();
|
|
2651
2678
|
const bridgeCommand = join$1(projectPath(), "bin", "flockbay-mcp.mjs");
|
|
2652
2679
|
const mcpServers = {
|
|
2653
2680
|
flockbay: {
|
|
@@ -3055,8 +3082,12 @@ async function runGemini(opts) {
|
|
|
3055
3082
|
const isAbortError = error instanceof Error && error.name === "AbortError";
|
|
3056
3083
|
if (isAbortError) {
|
|
3057
3084
|
skipAutoFinalize = true;
|
|
3058
|
-
|
|
3059
|
-
|
|
3085
|
+
const note = abortNote || "Aborted by user";
|
|
3086
|
+
abortNote = null;
|
|
3087
|
+
const alreadySent = abortNoteSentToSession;
|
|
3088
|
+
abortNoteSentToSession = false;
|
|
3089
|
+
messageBuffer.addMessage(note, "status");
|
|
3090
|
+
if (!alreadySent) session.sendSessionEvent({ type: "message", message: note });
|
|
3060
3091
|
} else {
|
|
3061
3092
|
const rawErrorString = error instanceof Error ? error.message : String(error);
|
|
3062
3093
|
const looksLikeAuthOrQuotaError = /unauthenticated|unauthorized|invalid (api )?key|api key not valid|permission denied|forbidden|expired|quota|usage limit|rate limit|resource exhausted|resource_exhausted|status 401|status 403|status 429|\b401\b|\b403\b|\b429\b/i.test(rawErrorString);
|
|
@@ -3148,6 +3179,10 @@ async function runGemini(opts) {
|
|
|
3148
3179
|
}
|
|
3149
3180
|
} finally {
|
|
3150
3181
|
logger.debug("[gemini]: Final cleanup start");
|
|
3182
|
+
try {
|
|
3183
|
+
if (typeof unsubscribeUnrealIssue === "function") unsubscribeUnrealIssue();
|
|
3184
|
+
} catch {
|
|
3185
|
+
}
|
|
3151
3186
|
try {
|
|
3152
3187
|
session.sendSessionDeath();
|
|
3153
3188
|
await session.flush();
|
|
@@ -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-
|
|
10
|
-
var index = require('./index
|
|
9
|
+
var types = require('./types-SUAKq-K0.cjs');
|
|
10
|
+
var index = require('./index-Cau-_Qvn.cjs');
|
|
11
11
|
var node_child_process = require('node:child_process');
|
|
12
12
|
var sdk = require('@agentclientprotocol/sdk');
|
|
13
13
|
var fs = require('fs');
|
|
@@ -15,31 +15,28 @@ var path$1 = require('path');
|
|
|
15
15
|
var os$1 = require('os');
|
|
16
16
|
var child_process = require('child_process');
|
|
17
17
|
var fs$1 = require('node:fs');
|
|
18
|
-
var flockbayScreenshotGate = require('./flockbayScreenshotGate-DkxU24cR.cjs');
|
|
19
18
|
require('axios');
|
|
20
|
-
require('chalk');
|
|
21
|
-
require('zod');
|
|
22
|
-
require('tweetnacl');
|
|
23
19
|
require('node:events');
|
|
24
20
|
require('socket.io-client');
|
|
21
|
+
require('chalk');
|
|
22
|
+
require('zod');
|
|
25
23
|
require('fs/promises');
|
|
26
24
|
require('crypto');
|
|
27
25
|
require('url');
|
|
28
26
|
require('node:process');
|
|
29
27
|
require('node:net');
|
|
30
|
-
require('expo-server-sdk');
|
|
31
28
|
require('node:readline');
|
|
32
29
|
require('node:url');
|
|
33
30
|
require('ps-list');
|
|
34
31
|
require('cross-spawn');
|
|
35
32
|
require('tmp');
|
|
36
|
-
require('qrcode-terminal');
|
|
37
33
|
require('open');
|
|
38
34
|
require('fastify');
|
|
39
35
|
require('fastify-type-provider-zod');
|
|
40
36
|
require('@modelcontextprotocol/sdk/server/mcp.js');
|
|
41
37
|
require('node:http');
|
|
42
38
|
require('@modelcontextprotocol/sdk/server/streamableHttp.js');
|
|
39
|
+
require('tweetnacl');
|
|
43
40
|
require('http');
|
|
44
41
|
require('util');
|
|
45
42
|
|
|
@@ -936,15 +933,6 @@ ${excerpt}` : base;
|
|
|
936
933
|
}
|
|
937
934
|
}
|
|
938
935
|
}
|
|
939
|
-
if (update.messageChunk) {
|
|
940
|
-
const chunk = update.messageChunk;
|
|
941
|
-
if (chunk.textDelta) {
|
|
942
|
-
this.emit({
|
|
943
|
-
type: "model-output",
|
|
944
|
-
textDelta: chunk.textDelta
|
|
945
|
-
});
|
|
946
|
-
}
|
|
947
|
-
}
|
|
948
936
|
if (update.plan) {
|
|
949
937
|
this.emit({
|
|
950
938
|
type: "event",
|
|
@@ -1880,11 +1868,14 @@ class GeminiPermissionHandler {
|
|
|
1880
1868
|
}
|
|
1881
1869
|
this.pendingRequests.clear();
|
|
1882
1870
|
this.session.updateAgentState((currentState) => {
|
|
1883
|
-
const
|
|
1884
|
-
const
|
|
1871
|
+
const pendingRaw = currentState?.requests;
|
|
1872
|
+
const pendingRequests = pendingRaw && typeof pendingRaw === "object" ? pendingRaw : {};
|
|
1873
|
+
const completedRaw = currentState?.completedRequests;
|
|
1874
|
+
const completedRequests = completedRaw && typeof completedRaw === "object" ? { ...completedRaw } : {};
|
|
1885
1875
|
for (const [id, request] of Object.entries(pendingRequests)) {
|
|
1876
|
+
const reqObj = request && typeof request === "object" ? request : { value: request };
|
|
1886
1877
|
completedRequests[id] = {
|
|
1887
|
-
...
|
|
1878
|
+
...reqObj,
|
|
1888
1879
|
completedAt: Date.now(),
|
|
1889
1880
|
status: "canceled",
|
|
1890
1881
|
reason: "Session reset"
|
|
@@ -2350,8 +2341,19 @@ async function runGemini(opts) {
|
|
|
2350
2341
|
lifecycleStateSince: Date.now(),
|
|
2351
2342
|
flavor: "gemini"
|
|
2352
2343
|
};
|
|
2353
|
-
const response = await api.getOrCreateSession({ tag: sessionTag, metadata, state });
|
|
2344
|
+
const response = opts.sessionId ? await api.getSessionById(opts.sessionId) : await api.getOrCreateSession({ tag: sessionTag, metadata, state });
|
|
2354
2345
|
const session = api.sessionSyncClient(response);
|
|
2346
|
+
if (opts.sessionId) {
|
|
2347
|
+
session.updateMetadata((currentMetadata) => ({
|
|
2348
|
+
...currentMetadata,
|
|
2349
|
+
...metadata,
|
|
2350
|
+
// Preserve user-facing fields set by other clients.
|
|
2351
|
+
name: currentMetadata?.name,
|
|
2352
|
+
summary: currentMetadata?.summary
|
|
2353
|
+
}));
|
|
2354
|
+
}
|
|
2355
|
+
await session.connectAndWait(15e3);
|
|
2356
|
+
session.keepAlive(false, "remote");
|
|
2355
2357
|
try {
|
|
2356
2358
|
types.logger.debug(`[START] Reporting session ${response.id} to daemon`);
|
|
2357
2359
|
const result = await index.notifyDaemonSessionStarted(response.id, metadata);
|
|
@@ -2380,7 +2382,7 @@ async function runGemini(opts) {
|
|
|
2380
2382
|
if (!output) return;
|
|
2381
2383
|
const cwdHint = output?.cwd;
|
|
2382
2384
|
const cwd = typeof cwdHint === "string" && cwdHint.trim().length > 0 ? cwdHint.trim() : process.cwd();
|
|
2383
|
-
const detected =
|
|
2385
|
+
const detected = index.detectScreenshotsForGate({ output, cwd });
|
|
2384
2386
|
if (detected.paths.length === 0) return;
|
|
2385
2387
|
for (const p of detected.paths) {
|
|
2386
2388
|
const trimmed = String(p || "").trim();
|
|
@@ -2398,9 +2400,13 @@ async function runGemini(opts) {
|
|
|
2398
2400
|
text: [
|
|
2399
2401
|
`You just generated ${unique.length} screenshot${unique.length === 1 ? "" : "s"}.`,
|
|
2400
2402
|
"",
|
|
2401
|
-
"Visually inspect EVERY screenshot and report:",
|
|
2402
|
-
"
|
|
2403
|
-
"
|
|
2403
|
+
"Visually inspect EVERY screenshot and report (this is for YOUR validation, not ceremony):",
|
|
2404
|
+
"1) List 2\u20135 concrete acceptance criteria for the user\u2019s request.",
|
|
2405
|
+
"2) One short bullet per image describing what you see.",
|
|
2406
|
+
"3) For each acceptance criterion: mark it as Verified / Not visible / Failed based ONLY on the screenshots.",
|
|
2407
|
+
' - If "Not visible", say what evidence is missing.',
|
|
2408
|
+
' - If "Failed", say what is wrong.',
|
|
2409
|
+
"4) If anything is not Verified: state the next tool/action you will take to fix or validate it (do not claim completion yet).",
|
|
2404
2410
|
"",
|
|
2405
2411
|
"Do not run any tools in this step."
|
|
2406
2412
|
].join("\n")
|
|
@@ -2536,8 +2542,14 @@ async function runGemini(opts) {
|
|
|
2536
2542
|
let geminiBackend = null;
|
|
2537
2543
|
let acpSessionId = null;
|
|
2538
2544
|
let wasSessionCreated = false;
|
|
2539
|
-
|
|
2545
|
+
let abortNote = null;
|
|
2546
|
+
let abortNoteSentToSession = false;
|
|
2547
|
+
async function handleAbort(note, options) {
|
|
2540
2548
|
types.logger.debug("[Gemini] Abort requested - stopping current task");
|
|
2549
|
+
if (typeof note === "string" && note.trim()) {
|
|
2550
|
+
abortNote = note.trim();
|
|
2551
|
+
abortNoteSentToSession = Boolean(options?.alreadySentToSession);
|
|
2552
|
+
}
|
|
2541
2553
|
session.sendCodexMessage({
|
|
2542
2554
|
type: "turn_aborted",
|
|
2543
2555
|
id: node_crypto.randomUUID()
|
|
@@ -2592,7 +2604,7 @@ async function runGemini(opts) {
|
|
|
2592
2604
|
process.exit(1);
|
|
2593
2605
|
}
|
|
2594
2606
|
};
|
|
2595
|
-
session.rpcHandlerManager.registerHandler("
|
|
2607
|
+
session.rpcHandlerManager.registerHandler("cancel-generation", handleAbort);
|
|
2596
2608
|
index.registerKillSessionHandler(session.rpcHandlerManager, handleKillSession);
|
|
2597
2609
|
const messageBuffer = new index.MessageBuffer();
|
|
2598
2610
|
const hasTTY = process.stdout.isTTY && process.stdin.isTTY;
|
|
@@ -2650,6 +2662,21 @@ async function runGemini(opts) {
|
|
|
2650
2662
|
}
|
|
2651
2663
|
const elicitationHub = new index.ElicitationHub();
|
|
2652
2664
|
const flockbayServer = await index.startFlockbayServer(session, { elicitationHub });
|
|
2665
|
+
const unsubscribeUnrealIssue = (() => {
|
|
2666
|
+
const onIssue = flockbayServer?.unreal?.onIssue;
|
|
2667
|
+
if (typeof onIssue !== "function") return null;
|
|
2668
|
+
return onIssue((event) => {
|
|
2669
|
+
try {
|
|
2670
|
+
const kind = typeof event?.kind === "string" ? event.kind : "unreachable";
|
|
2671
|
+
const base = typeof event?.message === "string" && event.message.trim() ? event.message.trim() : "Unreal Editor issue detected.";
|
|
2672
|
+
const msg = kind === "process_exit" ? `Unreal Editor crashed. ${base}` : `Unreal Editor is not reachable. ${base}`;
|
|
2673
|
+
session.sendSessionEvent({ type: "message", message: msg });
|
|
2674
|
+
void handleAbort(msg, { alreadySentToSession: true });
|
|
2675
|
+
} catch (err) {
|
|
2676
|
+
types.logger.debug("[Gemini] Failed to handle Unreal issue event", err);
|
|
2677
|
+
}
|
|
2678
|
+
});
|
|
2679
|
+
})();
|
|
2653
2680
|
const bridgeCommand = path.join(types.projectPath(), "bin", "flockbay-mcp.mjs");
|
|
2654
2681
|
const mcpServers = {
|
|
2655
2682
|
flockbay: {
|
|
@@ -3057,8 +3084,12 @@ async function runGemini(opts) {
|
|
|
3057
3084
|
const isAbortError = error instanceof Error && error.name === "AbortError";
|
|
3058
3085
|
if (isAbortError) {
|
|
3059
3086
|
skipAutoFinalize = true;
|
|
3060
|
-
|
|
3061
|
-
|
|
3087
|
+
const note = abortNote || "Aborted by user";
|
|
3088
|
+
abortNote = null;
|
|
3089
|
+
const alreadySent = abortNoteSentToSession;
|
|
3090
|
+
abortNoteSentToSession = false;
|
|
3091
|
+
messageBuffer.addMessage(note, "status");
|
|
3092
|
+
if (!alreadySent) session.sendSessionEvent({ type: "message", message: note });
|
|
3062
3093
|
} else {
|
|
3063
3094
|
const rawErrorString = error instanceof Error ? error.message : String(error);
|
|
3064
3095
|
const looksLikeAuthOrQuotaError = /unauthenticated|unauthorized|invalid (api )?key|api key not valid|permission denied|forbidden|expired|quota|usage limit|rate limit|resource exhausted|resource_exhausted|status 401|status 403|status 429|\b401\b|\b403\b|\b429\b/i.test(rawErrorString);
|
|
@@ -3150,6 +3181,10 @@ async function runGemini(opts) {
|
|
|
3150
3181
|
}
|
|
3151
3182
|
} finally {
|
|
3152
3183
|
types.logger.debug("[gemini]: Final cleanup start");
|
|
3184
|
+
try {
|
|
3185
|
+
if (typeof unsubscribeUnrealIssue === "function") unsubscribeUnrealIssue();
|
|
3186
|
+
} catch {
|
|
3187
|
+
}
|
|
3153
3188
|
try {
|
|
3154
3189
|
session.sendSessionDeath();
|
|
3155
3190
|
await session.flush();
|