@nomad-e/bluma-cli 0.23.0 → 0.24.0
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/main.js +273 -93
- package/package.json +1 -1
package/dist/main.js
CHANGED
|
@@ -2242,25 +2242,14 @@ var init_ListMailboxMessagesTool = __esm({
|
|
|
2242
2242
|
|
|
2243
2243
|
// src/app/agent/core/context-api/token_counter.ts
|
|
2244
2244
|
import { getEncoding } from "js-tiktoken";
|
|
2245
|
-
import { createHash as createHash2 } from "crypto";
|
|
2246
2245
|
function getO200kEncoding() {
|
|
2247
2246
|
if (!cachedEncoding) {
|
|
2248
2247
|
cachedEncoding = getEncoding("o200k_base");
|
|
2249
2248
|
}
|
|
2250
2249
|
return cachedEncoding;
|
|
2251
2250
|
}
|
|
2252
|
-
function
|
|
2253
|
-
|
|
2254
|
-
hash.update(`len:${messages.length}:`);
|
|
2255
|
-
for (const msg of messages) {
|
|
2256
|
-
const m = msg;
|
|
2257
|
-
hash.update(`role:${m.role ?? ""}:`);
|
|
2258
|
-
hash.update(`content:${JSON.stringify(m.content ?? "")}:`);
|
|
2259
|
-
hash.update(`tool_calls:${JSON.stringify(m.tool_calls ?? "")}:`);
|
|
2260
|
-
hash.update(`tool_call_id:${m.tool_call_id ?? ""}:`);
|
|
2261
|
-
hash.update(`name:${m.name ?? ""}:`);
|
|
2262
|
-
}
|
|
2263
|
-
return hash.digest("hex");
|
|
2251
|
+
function invalidateTokenCache() {
|
|
2252
|
+
cacheVersion++;
|
|
2264
2253
|
}
|
|
2265
2254
|
function messageBodyForTokens(msg) {
|
|
2266
2255
|
const c = msg.content;
|
|
@@ -2290,22 +2279,8 @@ function countTokens(messages, useCache = true) {
|
|
|
2290
2279
|
if (messages.length === 0) {
|
|
2291
2280
|
return CONVERSATION_BASE_OVERHEAD;
|
|
2292
2281
|
}
|
|
2293
|
-
if (useCache) {
|
|
2294
|
-
|
|
2295
|
-
if (tokenCountCache && tokenCountCache.hash === currentHash) {
|
|
2296
|
-
return tokenCountCache.count;
|
|
2297
|
-
}
|
|
2298
|
-
const enc2 = getO200kEncoding();
|
|
2299
|
-
let total2 = CONVERSATION_BASE_OVERHEAD;
|
|
2300
|
-
for (const msg of messages) {
|
|
2301
|
-
const body = messageBodyForTokens(msg);
|
|
2302
|
-
const extra = messageExtraForTokens(msg);
|
|
2303
|
-
const nBody = body ? enc2.encode(body).length : 0;
|
|
2304
|
-
const nExtra = extra ? enc2.encode(extra).length : 0;
|
|
2305
|
-
total2 += nBody + nExtra + MESSAGE_OVERHEAD_TOKENS;
|
|
2306
|
-
}
|
|
2307
|
-
tokenCountCache = { hash: currentHash, count: total2 };
|
|
2308
|
-
return total2;
|
|
2282
|
+
if (useCache && cacheVersion === cachedVersion) {
|
|
2283
|
+
return cachedCount;
|
|
2309
2284
|
}
|
|
2310
2285
|
const enc = getO200kEncoding();
|
|
2311
2286
|
let total = CONVERSATION_BASE_OVERHEAD;
|
|
@@ -2316,11 +2291,12 @@ function countTokens(messages, useCache = true) {
|
|
|
2316
2291
|
const nExtra = extra ? enc.encode(extra).length : 0;
|
|
2317
2292
|
total += nBody + nExtra + MESSAGE_OVERHEAD_TOKENS;
|
|
2318
2293
|
}
|
|
2294
|
+
if (useCache) {
|
|
2295
|
+
cachedVersion = cacheVersion;
|
|
2296
|
+
cachedCount = total;
|
|
2297
|
+
}
|
|
2319
2298
|
return total;
|
|
2320
2299
|
}
|
|
2321
|
-
function clearTokenCountCache() {
|
|
2322
|
-
tokenCountCache = null;
|
|
2323
|
-
}
|
|
2324
2300
|
function countToolDefinitionsTokens(tools) {
|
|
2325
2301
|
if (!tools || tools.length === 0) {
|
|
2326
2302
|
return 0;
|
|
@@ -2345,14 +2321,16 @@ function computeEffectiveInputBudget(rawBudget, toolDefinitions = [], options) {
|
|
|
2345
2321
|
effectiveBudget
|
|
2346
2322
|
};
|
|
2347
2323
|
}
|
|
2348
|
-
var MESSAGE_OVERHEAD_TOKENS, CONVERSATION_BASE_OVERHEAD, cachedEncoding,
|
|
2324
|
+
var MESSAGE_OVERHEAD_TOKENS, CONVERSATION_BASE_OVERHEAD, cachedEncoding, cacheVersion, cachedVersion, cachedCount, DEFAULT_OUTPUT_TOKEN_RESERVE, DEFAULT_PROTOCOL_OVERHEAD_TOKENS;
|
|
2349
2325
|
var init_token_counter = __esm({
|
|
2350
2326
|
"src/app/agent/core/context-api/token_counter.ts"() {
|
|
2351
2327
|
"use strict";
|
|
2352
2328
|
MESSAGE_OVERHEAD_TOKENS = 4;
|
|
2353
2329
|
CONVERSATION_BASE_OVERHEAD = 3;
|
|
2354
2330
|
cachedEncoding = null;
|
|
2355
|
-
|
|
2331
|
+
cacheVersion = 0;
|
|
2332
|
+
cachedVersion = -1;
|
|
2333
|
+
cachedCount = 0;
|
|
2356
2334
|
DEFAULT_OUTPUT_TOKEN_RESERVE = 8192;
|
|
2357
2335
|
DEFAULT_PROTOCOL_OVERHEAD_TOKENS = 512;
|
|
2358
2336
|
}
|
|
@@ -14315,7 +14293,7 @@ import { v4 as uuidv412 } from "uuid";
|
|
|
14315
14293
|
import chalk3 from "chalk";
|
|
14316
14294
|
|
|
14317
14295
|
// src/app/ui/BlumaSession.tsx
|
|
14318
|
-
import
|
|
14296
|
+
import { useState as useState25, useEffect as useEffect22, useRef as useRef13, useCallback as useCallback11, memo as memo25, useMemo as useMemo8 } from "react";
|
|
14319
14297
|
|
|
14320
14298
|
// src/app/ui/layout.tsx
|
|
14321
14299
|
import { memo as memo2 } from "react";
|
|
@@ -25084,8 +25062,13 @@ var HistoryCompressor = class {
|
|
|
25084
25062
|
const tokenBudget = budgetBreakdown.effectiveBudget;
|
|
25085
25063
|
const compressThreshold = options?.compressThreshold ?? COMPRESS_THRESHOLD;
|
|
25086
25064
|
const keepRecentTurns = options?.keepRecentTurns ?? KEEP_RECENT_TURNS;
|
|
25087
|
-
|
|
25088
|
-
|
|
25065
|
+
let safeHistory;
|
|
25066
|
+
if (options?.skipSanitize) {
|
|
25067
|
+
safeHistory = fullHistory;
|
|
25068
|
+
} else {
|
|
25069
|
+
const sanitized = sanitizeConversationForProvider(fullHistory);
|
|
25070
|
+
safeHistory = sanitized.messages;
|
|
25071
|
+
}
|
|
25089
25072
|
const systemMessages = [];
|
|
25090
25073
|
let historyStartIndex = 0;
|
|
25091
25074
|
while (historyStartIndex < safeHistory.length && safeHistory[historyStartIndex].role === "system") {
|
|
@@ -25102,7 +25085,6 @@ var HistoryCompressor = class {
|
|
|
25102
25085
|
const thresholdTokens = tokenBudget * compressThreshold;
|
|
25103
25086
|
let pendingSlices = turnSlices.slice(sliceCount, recentStart);
|
|
25104
25087
|
let pendingFlat = pendingSlices.flat();
|
|
25105
|
-
clearTokenCountCache();
|
|
25106
25088
|
let messages = this.assembleMessages(systemMessages, pendingFlat, recentFlat);
|
|
25107
25089
|
let tokens = countTokens(messages, true);
|
|
25108
25090
|
contextEventBus.emit("context:compression_start", {
|
|
@@ -25149,12 +25131,12 @@ var HistoryCompressor = class {
|
|
|
25149
25131
|
reason: compressError?.message || "timeout"
|
|
25150
25132
|
});
|
|
25151
25133
|
}
|
|
25152
|
-
|
|
25134
|
+
invalidateTokenCache();
|
|
25153
25135
|
messages = this.assembleMessages(systemMessages, pendingFlat, recentFlat);
|
|
25154
25136
|
tokens = countTokens(messages, true);
|
|
25155
25137
|
}
|
|
25156
25138
|
if (tokens > tokenBudget) {
|
|
25157
|
-
|
|
25139
|
+
invalidateTokenCache();
|
|
25158
25140
|
const { capped, slices: cappedSlices } = this.enforceHardCap(
|
|
25159
25141
|
systemMessages,
|
|
25160
25142
|
recentSlices,
|
|
@@ -27246,7 +27228,9 @@ var BluMaTurnCoordinator = class {
|
|
|
27246
27228
|
this.deps.getLlmUserContext(),
|
|
27247
27229
|
{
|
|
27248
27230
|
tokenBudget,
|
|
27249
|
-
toolDefinitions: this.deps.mcpClient.getAvailableTools()
|
|
27231
|
+
toolDefinitions: this.deps.mcpClient.getAvailableTools(),
|
|
27232
|
+
skipSanitize: true
|
|
27233
|
+
// already sanitized above
|
|
27250
27234
|
}
|
|
27251
27235
|
);
|
|
27252
27236
|
this.turnLog.debug("Context window prepared", {
|
|
@@ -28137,11 +28121,15 @@ function hasMetUpdateThreshold(currentTokens) {
|
|
|
28137
28121
|
// src/app/agent/memory/session_memory_update.ts
|
|
28138
28122
|
init_logger();
|
|
28139
28123
|
var log2 = logger.child("session_memory");
|
|
28124
|
+
var MIN_COOLDOWN_MS = 6e4;
|
|
28125
|
+
var lastUpdateTime = 0;
|
|
28140
28126
|
function isSessionMemoryEnabled() {
|
|
28141
28127
|
if (process.env.BLUMA_DISABLE_SESSION_MEMORY === "1") return false;
|
|
28142
28128
|
return true;
|
|
28143
28129
|
}
|
|
28144
28130
|
function shouldUpdateSessionMemory(history) {
|
|
28131
|
+
const now2 = Date.now();
|
|
28132
|
+
if (now2 - lastUpdateTime < MIN_COOLDOWN_MS) return false;
|
|
28145
28133
|
const tokens = estimateHistoryTokens(history);
|
|
28146
28134
|
if (!isSessionMemoryInitialized()) {
|
|
28147
28135
|
if (!hasMetInitializationThreshold(tokens)) return false;
|
|
@@ -28191,6 +28179,7 @@ async function runSessionMemoryUpdate(deps) {
|
|
|
28191
28179
|
});
|
|
28192
28180
|
recordExtractionTokenCount(estimateHistoryTokens(history));
|
|
28193
28181
|
setLastCursorIndex(history.length);
|
|
28182
|
+
lastUpdateTime = Date.now();
|
|
28194
28183
|
log2.debug("finished");
|
|
28195
28184
|
} catch (err) {
|
|
28196
28185
|
log2.warn("failed", { error: err instanceof Error ? err.message : String(err) });
|
|
@@ -28205,8 +28194,10 @@ function scheduleSessionMemoryUpdate(deps) {
|
|
|
28205
28194
|
|
|
28206
28195
|
// src/app/agent/memory/background_memory.ts
|
|
28207
28196
|
function runBackgroundMemoryAfterTurn(params) {
|
|
28197
|
+
const MAX_SNAPSHOT = 80;
|
|
28198
|
+
const snapshot = params.history.length > MAX_SNAPSHOT ? params.history.slice(-MAX_SNAPSHOT) : params.history;
|
|
28208
28199
|
const deps = {
|
|
28209
|
-
history:
|
|
28200
|
+
history: snapshot,
|
|
28210
28201
|
sessionId: params.sessionId,
|
|
28211
28202
|
llm: params.llm,
|
|
28212
28203
|
mcpClient: params.mcpClient,
|
|
@@ -45377,6 +45368,167 @@ function ScrollBox({
|
|
|
45377
45368
|
}
|
|
45378
45369
|
var ScrollBox_default = ScrollBox;
|
|
45379
45370
|
|
|
45371
|
+
// src/app/ui/hooks/useVirtualScroll.ts
|
|
45372
|
+
import {
|
|
45373
|
+
useCallback as useCallback10,
|
|
45374
|
+
useLayoutEffect as useLayoutEffect3,
|
|
45375
|
+
useMemo as useMemo7,
|
|
45376
|
+
useRef as useRef12,
|
|
45377
|
+
useState as useState24
|
|
45378
|
+
} from "react";
|
|
45379
|
+
var DEFAULT_ESTIMATE = 3;
|
|
45380
|
+
var OVERSCAN_ROWS = 40;
|
|
45381
|
+
var COLD_START_COUNT = 20;
|
|
45382
|
+
var MAX_MOUNTED_ITEMS = 200;
|
|
45383
|
+
var PESSIMISTIC_HEIGHT = 1;
|
|
45384
|
+
function useVirtualScroll(scrollRef, itemKeys, columns) {
|
|
45385
|
+
const heightCache = useRef12(/* @__PURE__ */ new Map());
|
|
45386
|
+
const offsetVersionRef = useRef12(0);
|
|
45387
|
+
const lastScrollTopRef = useRef12(0);
|
|
45388
|
+
const offsetsRef = useRef12({
|
|
45389
|
+
arr: new Float64Array(0),
|
|
45390
|
+
version: -1,
|
|
45391
|
+
n: -1
|
|
45392
|
+
});
|
|
45393
|
+
const itemRefs = useRef12(/* @__PURE__ */ new Map());
|
|
45394
|
+
const refCache = useRef12(/* @__PURE__ */ new Map());
|
|
45395
|
+
const prevColumns = useRef12(columns);
|
|
45396
|
+
const skipMeasurementRef = useRef12(false);
|
|
45397
|
+
if (prevColumns.current !== columns) {
|
|
45398
|
+
const ratio = prevColumns.current / columns;
|
|
45399
|
+
prevColumns.current = columns;
|
|
45400
|
+
for (const [k, h] of heightCache.current) {
|
|
45401
|
+
heightCache.current.set(k, Math.max(1, Math.round(h * ratio)));
|
|
45402
|
+
}
|
|
45403
|
+
offsetVersionRef.current++;
|
|
45404
|
+
skipMeasurementRef.current = true;
|
|
45405
|
+
}
|
|
45406
|
+
const SCROLL_QUANTUM = OVERSCAN_ROWS >> 1;
|
|
45407
|
+
const subscribe = useCallback10(
|
|
45408
|
+
(cb) => scrollRef.current?.subscribe(cb) ?? (() => {
|
|
45409
|
+
}),
|
|
45410
|
+
[scrollRef]
|
|
45411
|
+
);
|
|
45412
|
+
const getSnapshot = useCallback10(() => {
|
|
45413
|
+
const sb = scrollRef.current;
|
|
45414
|
+
if (!sb) return NaN;
|
|
45415
|
+
const raw = sb.getScrollTop();
|
|
45416
|
+
const sticky = sb.isSticky();
|
|
45417
|
+
const quantized = Math.floor(raw / SCROLL_QUANTUM) * SCROLL_QUANTUM;
|
|
45418
|
+
return sticky ? -(quantized | 1) : quantized;
|
|
45419
|
+
}, [scrollRef, SCROLL_QUANTUM]);
|
|
45420
|
+
const getServerSnapshot = useCallback10(() => NaN, []);
|
|
45421
|
+
const scrollTop = useSyncExternalStore5(subscribe, getSnapshot, getServerSnapshot);
|
|
45422
|
+
const viewportHeight = scrollRef.current?.getViewportHeight() ?? 0;
|
|
45423
|
+
const isSticky = scrollRef.current?.isSticky() ?? true;
|
|
45424
|
+
const n = itemKeys.length;
|
|
45425
|
+
const computeOffsets = useCallback10(() => {
|
|
45426
|
+
const cached = offsetsRef.current;
|
|
45427
|
+
if (cached.n === n && cached.version === offsetVersionRef.current && cached.arr.length === n + 1) {
|
|
45428
|
+
return cached.arr;
|
|
45429
|
+
}
|
|
45430
|
+
const offsets2 = new Float64Array(n + 1);
|
|
45431
|
+
for (let i = 0; i < n; i++) {
|
|
45432
|
+
const h = heightCache.current.get(itemKeys[i]) ?? DEFAULT_ESTIMATE;
|
|
45433
|
+
offsets2[i + 1] = offsets2[i] + h;
|
|
45434
|
+
}
|
|
45435
|
+
offsetsRef.current = { arr: offsets2, version: offsetVersionRef.current, n };
|
|
45436
|
+
return offsets2;
|
|
45437
|
+
}, [n, itemKeys, offsetVersionRef.current]);
|
|
45438
|
+
const offsets = computeOffsets();
|
|
45439
|
+
const totalHeight = offsets[n] ?? 0;
|
|
45440
|
+
const range = useMemo7(() => {
|
|
45441
|
+
if (n === 0) return [0, 0];
|
|
45442
|
+
if (viewportHeight <= 0) {
|
|
45443
|
+
return [0, Math.min(n, COLD_START_COUNT)];
|
|
45444
|
+
}
|
|
45445
|
+
const absScrollTop = Math.abs(scrollTop);
|
|
45446
|
+
if (isSticky) {
|
|
45447
|
+
let hi3 = n;
|
|
45448
|
+
let remaining = viewportHeight + OVERSCAN_ROWS;
|
|
45449
|
+
while (hi3 > 0 && remaining > 0) {
|
|
45450
|
+
const h = heightCache.current.get(itemKeys[hi3 - 1]) ?? DEFAULT_ESTIMATE;
|
|
45451
|
+
remaining -= h;
|
|
45452
|
+
hi3--;
|
|
45453
|
+
}
|
|
45454
|
+
const lo3 = Math.max(0, hi3 - OVERSCAN_ROWS);
|
|
45455
|
+
return [lo3, n];
|
|
45456
|
+
}
|
|
45457
|
+
let lo2 = 0;
|
|
45458
|
+
{
|
|
45459
|
+
const target = Math.max(0, absScrollTop - OVERSCAN_ROWS);
|
|
45460
|
+
let lo_ = 0;
|
|
45461
|
+
let hi_ = n;
|
|
45462
|
+
while (lo_ < hi_) {
|
|
45463
|
+
const mid = lo_ + hi_ >>> 1;
|
|
45464
|
+
if (offsets[mid] < target) lo_ = mid + 1;
|
|
45465
|
+
else hi_ = mid;
|
|
45466
|
+
}
|
|
45467
|
+
lo2 = lo_;
|
|
45468
|
+
}
|
|
45469
|
+
let hi2 = lo2;
|
|
45470
|
+
let accumulated = 0;
|
|
45471
|
+
const needed = viewportHeight + 2 * OVERSCAN_ROWS;
|
|
45472
|
+
while (hi2 < n && accumulated < needed) {
|
|
45473
|
+
const h = heightCache.current.get(itemKeys[hi2]) ?? PESSIMISTIC_HEIGHT;
|
|
45474
|
+
accumulated += h;
|
|
45475
|
+
hi2++;
|
|
45476
|
+
}
|
|
45477
|
+
return [lo2, Math.min(hi2, lo2 + MAX_MOUNTED_ITEMS)];
|
|
45478
|
+
}, [scrollTop, viewportHeight, isSticky, n, offsets, itemKeys]);
|
|
45479
|
+
const measureRef = useCallback10((key) => {
|
|
45480
|
+
if (refCache.current.has(key)) return refCache.current.get(key);
|
|
45481
|
+
const refFn = (el) => {
|
|
45482
|
+
if (skipMeasurementRef.current) return;
|
|
45483
|
+
if (el) {
|
|
45484
|
+
itemRefs.current.set(key, el);
|
|
45485
|
+
const h = el.yogaNode?.getComputedHeight();
|
|
45486
|
+
if (h != null && h > 0) {
|
|
45487
|
+
const prev = heightCache.current.get(key);
|
|
45488
|
+
if (prev !== h) {
|
|
45489
|
+
heightCache.current.set(key, h);
|
|
45490
|
+
offsetVersionRef.current++;
|
|
45491
|
+
}
|
|
45492
|
+
}
|
|
45493
|
+
}
|
|
45494
|
+
};
|
|
45495
|
+
refCache.current.set(key, refFn);
|
|
45496
|
+
return refFn;
|
|
45497
|
+
}, []);
|
|
45498
|
+
const [lo, hi] = range;
|
|
45499
|
+
const topSpacer = offsets[lo] ?? 0;
|
|
45500
|
+
const bottomSpacer = totalHeight - (offsets[hi] ?? totalHeight);
|
|
45501
|
+
return {
|
|
45502
|
+
range,
|
|
45503
|
+
topSpacer,
|
|
45504
|
+
bottomSpacer,
|
|
45505
|
+
offsets,
|
|
45506
|
+
measureRef
|
|
45507
|
+
};
|
|
45508
|
+
}
|
|
45509
|
+
function useSyncExternalStore5(subscribe, getSnapshot, getServerSnapshot) {
|
|
45510
|
+
const [value, setValue] = useState24(getSnapshot);
|
|
45511
|
+
const getSnapshotRef = useRef12(getSnapshot);
|
|
45512
|
+
getSnapshotRef.current = getSnapshot;
|
|
45513
|
+
useLayoutEffect3(() => {
|
|
45514
|
+
let didSubscribe = false;
|
|
45515
|
+
const checkForUpdates2 = () => {
|
|
45516
|
+
if (didSubscribe) {
|
|
45517
|
+
const newValue = getSnapshotRef.current();
|
|
45518
|
+
setValue(newValue);
|
|
45519
|
+
}
|
|
45520
|
+
};
|
|
45521
|
+
didSubscribe = true;
|
|
45522
|
+
checkForUpdates2();
|
|
45523
|
+
const unsubscribe = subscribe(checkForUpdates2);
|
|
45524
|
+
return () => {
|
|
45525
|
+
didSubscribe = false;
|
|
45526
|
+
unsubscribe();
|
|
45527
|
+
};
|
|
45528
|
+
}, [subscribe]);
|
|
45529
|
+
return value;
|
|
45530
|
+
}
|
|
45531
|
+
|
|
45380
45532
|
// src/app/ui/BlumaSession.tsx
|
|
45381
45533
|
import { Fragment as Fragment19, jsx as jsx104, jsxs as jsxs85 } from "react/jsx-runtime";
|
|
45382
45534
|
var blumaUpdateRegistryCheckStarted = false;
|
|
@@ -45442,23 +45594,23 @@ function UserMessageWithOptionalImages({
|
|
|
45442
45594
|
) : /* @__PURE__ */ jsx104(Text, { color: BLUMA_TERMINAL.m3OnSurface, wrap: "wrap", children: displayRaw }) });
|
|
45443
45595
|
}
|
|
45444
45596
|
var BlumaSessionComponent = ({ eventBus, sessionId, cliVersion }) => {
|
|
45445
|
-
const agentInstance =
|
|
45446
|
-
const [history, setHistory] =
|
|
45447
|
-
const [statusMessage, setStatusMessage] =
|
|
45597
|
+
const agentInstance = useRef13(null);
|
|
45598
|
+
const [history, setHistory] = useState25([]);
|
|
45599
|
+
const [statusMessage, setStatusMessage] = useState25(
|
|
45448
45600
|
"Initializing agent..."
|
|
45449
45601
|
);
|
|
45450
|
-
const [toolsCount, setToolsCount] =
|
|
45451
|
-
const [mcpStatus, setMcpStatus] =
|
|
45602
|
+
const [toolsCount, setToolsCount] = useState25(null);
|
|
45603
|
+
const [mcpStatus, setMcpStatus] = useState25(
|
|
45452
45604
|
"connecting"
|
|
45453
45605
|
);
|
|
45454
|
-
const [isProcessing, setIsProcessing] =
|
|
45455
|
-
const [pendingConfirmation, setPendingConfirmation] =
|
|
45606
|
+
const [isProcessing, setIsProcessing] = useState25(true);
|
|
45607
|
+
const [pendingConfirmation, setPendingConfirmation] = useState25(
|
|
45456
45608
|
null
|
|
45457
45609
|
);
|
|
45458
|
-
const [confirmationPreview, setConfirmationPreview] =
|
|
45610
|
+
const [confirmationPreview, setConfirmationPreview] = useState25(
|
|
45459
45611
|
null
|
|
45460
45612
|
);
|
|
45461
|
-
const [pendingAskUserQuestions, setPendingAskUserQuestions] =
|
|
45613
|
+
const [pendingAskUserQuestions, setPendingAskUserQuestions] = useState25(null);
|
|
45462
45614
|
const {
|
|
45463
45615
|
tokenCount,
|
|
45464
45616
|
tokenBudget,
|
|
@@ -45471,7 +45623,7 @@ var BlumaSessionComponent = ({ eventBus, sessionId, cliVersion }) => {
|
|
|
45471
45623
|
const { currentPlan, isPlanMode, parseMessage, resetPlan } = usePlanMode();
|
|
45472
45624
|
const { agentMode } = useAgentMode();
|
|
45473
45625
|
const workdir = getSandboxPolicy().workspaceRoot;
|
|
45474
|
-
const lastUpdateRef =
|
|
45626
|
+
const lastUpdateRef = useRef13(0);
|
|
45475
45627
|
useEffect22(() => {
|
|
45476
45628
|
const now2 = Date.now();
|
|
45477
45629
|
if (now2 - lastUpdateRef.current < 250) {
|
|
@@ -45490,29 +45642,29 @@ var BlumaSessionComponent = ({ eventBus, sessionId, cliVersion }) => {
|
|
|
45490
45642
|
activeProjects
|
|
45491
45643
|
});
|
|
45492
45644
|
}, [tokenCount, tokenBudget, isCompressing, compressionProgress, agentMode, isPlanMode, workdir, activeProjects]);
|
|
45493
|
-
const [isInitAgentActive, setIsInitAgentActive] =
|
|
45494
|
-
const [liveToolName, setLiveToolName] =
|
|
45495
|
-
const [liveToolArgs, setLiveToolArgs] =
|
|
45496
|
-
const [isReasoning, setIsReasoning] =
|
|
45497
|
-
const alwaysAcceptList =
|
|
45498
|
-
const turnStartedAtRef =
|
|
45499
|
-
const [processingStartMs, setProcessingStartMs] =
|
|
45500
|
-
const [lastTurnDurationLabel, setLastTurnDurationLabel] =
|
|
45501
|
-
const markTurnStarted =
|
|
45645
|
+
const [isInitAgentActive, setIsInitAgentActive] = useState25(false);
|
|
45646
|
+
const [liveToolName, setLiveToolName] = useState25(null);
|
|
45647
|
+
const [liveToolArgs, setLiveToolArgs] = useState25(void 0);
|
|
45648
|
+
const [isReasoning, setIsReasoning] = useState25(false);
|
|
45649
|
+
const alwaysAcceptList = useRef13([]);
|
|
45650
|
+
const turnStartedAtRef = useRef13(null);
|
|
45651
|
+
const [processingStartMs, setProcessingStartMs] = useState25(null);
|
|
45652
|
+
const [lastTurnDurationLabel, setLastTurnDurationLabel] = useState25(null);
|
|
45653
|
+
const markTurnStarted = useCallback11(() => {
|
|
45502
45654
|
const t = Date.now();
|
|
45503
45655
|
turnStartedAtRef.current = t;
|
|
45504
45656
|
setProcessingStartMs(t);
|
|
45505
45657
|
setLastTurnDurationLabel(null);
|
|
45506
45658
|
}, []);
|
|
45507
|
-
const handleWorkComplete =
|
|
45659
|
+
const handleWorkComplete = useCallback11((elapsedMs) => {
|
|
45508
45660
|
const label = formatTurnDurationMs(elapsedMs);
|
|
45509
45661
|
setLastTurnDurationLabel(label);
|
|
45510
45662
|
}, []);
|
|
45511
|
-
const lastReasoningTextRef =
|
|
45512
|
-
const streamedReasoningTextRef =
|
|
45513
|
-
const activeReasoningHistoryIdRef =
|
|
45514
|
-
const lastStreamAssistantKeyRef =
|
|
45515
|
-
const appendExpandPreviewToHistory =
|
|
45663
|
+
const lastReasoningTextRef = useRef13(null);
|
|
45664
|
+
const streamedReasoningTextRef = useRef13("");
|
|
45665
|
+
const activeReasoningHistoryIdRef = useRef13(null);
|
|
45666
|
+
const lastStreamAssistantKeyRef = useRef13(null);
|
|
45667
|
+
const appendExpandPreviewToHistory = useCallback11(() => {
|
|
45516
45668
|
const p = peekLatestExpandable();
|
|
45517
45669
|
setHistory((prev) => {
|
|
45518
45670
|
const id = nextHistoryId(prev);
|
|
@@ -45557,7 +45709,7 @@ var BlumaSessionComponent = ({ eventBus, sessionId, cliVersion }) => {
|
|
|
45557
45709
|
});
|
|
45558
45710
|
});
|
|
45559
45711
|
}, []);
|
|
45560
|
-
const handleInterrupt =
|
|
45712
|
+
const handleInterrupt = useCallback11(() => {
|
|
45561
45713
|
if (!isProcessing) return;
|
|
45562
45714
|
eventBus.emit("user_interrupt");
|
|
45563
45715
|
turnStartedAtRef.current = null;
|
|
@@ -45574,7 +45726,7 @@ var BlumaSessionComponent = ({ eventBus, sessionId, cliVersion }) => {
|
|
|
45574
45726
|
];
|
|
45575
45727
|
});
|
|
45576
45728
|
}, [isProcessing]);
|
|
45577
|
-
const handleSubmit =
|
|
45729
|
+
const handleSubmit = useCallback11(
|
|
45578
45730
|
(text) => {
|
|
45579
45731
|
if (!text || !agentInstance.current) return;
|
|
45580
45732
|
const trimmedForSlash = text.trim();
|
|
@@ -45823,7 +45975,7 @@ Please use command_status to check the result and report back to the user.`;
|
|
|
45823
45975
|
[isProcessing, markTurnStarted]
|
|
45824
45976
|
);
|
|
45825
45977
|
const { snapshot: queuedMessages, clear: clearQueue } = useMessageQueue_default();
|
|
45826
|
-
const isAgentIdle =
|
|
45978
|
+
const isAgentIdle = useMemo8(
|
|
45827
45979
|
() => !isProcessing && !pendingConfirmation && !pendingAskUserQuestions?.length && !isInitAgentActive,
|
|
45828
45980
|
[isProcessing, pendingConfirmation, pendingAskUserQuestions, isInitAgentActive]
|
|
45829
45981
|
);
|
|
@@ -45855,7 +46007,7 @@ Please use command_status to check the result and report back to the user.`;
|
|
|
45855
46007
|
subscription.off("clear_queue", handleClearQueue);
|
|
45856
46008
|
};
|
|
45857
46009
|
}, [queuedMessages.length, clearQueue]);
|
|
45858
|
-
const handleConfirmation =
|
|
46010
|
+
const handleConfirmation = useCallback11(
|
|
45859
46011
|
async (decision, toolCalls, opts) => {
|
|
45860
46012
|
if (!agentInstance.current) return;
|
|
45861
46013
|
setPendingConfirmation(null);
|
|
@@ -45878,7 +46030,7 @@ Please use command_status to check the result and report back to the user.`;
|
|
|
45878
46030
|
},
|
|
45879
46031
|
[]
|
|
45880
46032
|
);
|
|
45881
|
-
const appendStreamedReasoning =
|
|
46033
|
+
const appendStreamedReasoning = useCallback11((reasoning) => {
|
|
45882
46034
|
const r = String(reasoning ?? "").trim();
|
|
45883
46035
|
if (!r) return;
|
|
45884
46036
|
setHistory((prev) => {
|
|
@@ -45896,7 +46048,7 @@ Please use command_status to check the result and report back to the user.`;
|
|
|
45896
46048
|
return [...prev, { id, component }];
|
|
45897
46049
|
});
|
|
45898
46050
|
}, []);
|
|
45899
|
-
const appendStreamedAssistant =
|
|
46051
|
+
const appendStreamedAssistant = useCallback11((content) => {
|
|
45900
46052
|
const t = String(content ?? "").trim();
|
|
45901
46053
|
if (!t) return;
|
|
45902
46054
|
const key = reasoningDedupeKey(t);
|
|
@@ -45922,9 +46074,9 @@ Please use command_status to check the result and report back to the user.`;
|
|
|
45922
46074
|
return [...prev, { id, component: nextComponent }];
|
|
45923
46075
|
});
|
|
45924
46076
|
}, []);
|
|
45925
|
-
const handleConfirmationRef =
|
|
46077
|
+
const handleConfirmationRef = useRef13(handleConfirmation);
|
|
45926
46078
|
handleConfirmationRef.current = handleConfirmation;
|
|
45927
|
-
const sessionIdRef =
|
|
46079
|
+
const sessionIdRef = useRef13(sessionId);
|
|
45928
46080
|
sessionIdRef.current = sessionId;
|
|
45929
46081
|
useEffect22(() => {
|
|
45930
46082
|
const initializeAgent = async () => {
|
|
@@ -46217,17 +46369,17 @@ Please use command_status to check the result and report back to the user.`;
|
|
|
46217
46369
|
eventBus.off("backend_message", handleBackendMessage);
|
|
46218
46370
|
};
|
|
46219
46371
|
}, [eventBus, handleConfirmation]);
|
|
46220
|
-
const handleAnswerQuestion =
|
|
46372
|
+
const handleAnswerQuestion = useCallback11((answerJson) => {
|
|
46221
46373
|
setPendingAskUserQuestions(null);
|
|
46222
46374
|
eventBus.emit("ask_user_question_answer", { answer: answerJson });
|
|
46223
46375
|
}, [eventBus]);
|
|
46224
|
-
const handleCancelQuestion =
|
|
46376
|
+
const handleCancelQuestion = useCallback11(() => {
|
|
46225
46377
|
setPendingAskUserQuestions(null);
|
|
46226
46378
|
eventBus.emit("ask_user_question_answer", {
|
|
46227
46379
|
answer: JSON.stringify({ success: false, cancelled: true })
|
|
46228
46380
|
});
|
|
46229
46381
|
}, [eventBus]);
|
|
46230
|
-
const handleDecision =
|
|
46382
|
+
const handleDecision = useCallback11(async (decision) => {
|
|
46231
46383
|
if (!pendingConfirmation || pendingConfirmation.length === 0) return;
|
|
46232
46384
|
const [currentToolCall, ...remainingToolCalls] = pendingConfirmation;
|
|
46233
46385
|
if (!currentToolCall) return;
|
|
@@ -46244,8 +46396,33 @@ Please use command_status to check the result and report back to the user.`;
|
|
|
46244
46396
|
setIsProcessing(false);
|
|
46245
46397
|
}
|
|
46246
46398
|
}, [handleConfirmation, pendingConfirmation]);
|
|
46247
|
-
const
|
|
46248
|
-
|
|
46399
|
+
const scrollBoxRef = useRef13(null);
|
|
46400
|
+
const { columns } = useTerminalSize();
|
|
46401
|
+
const historyKeys = useMemo8(
|
|
46402
|
+
() => history.map((item) => String(item.id)),
|
|
46403
|
+
[history.length, history.length > 0 ? history[history.length - 1].id : 0]
|
|
46404
|
+
);
|
|
46405
|
+
const { range, topSpacer, bottomSpacer, measureRef } = useVirtualScroll(
|
|
46406
|
+
scrollBoxRef,
|
|
46407
|
+
historyKeys,
|
|
46408
|
+
columns
|
|
46409
|
+
);
|
|
46410
|
+
const [lo, hi] = range;
|
|
46411
|
+
const mountedItems = useMemo8(() => {
|
|
46412
|
+
return history.slice(lo, hi);
|
|
46413
|
+
}, [history, lo, hi]);
|
|
46414
|
+
const transcript = useMemo8(() => /* @__PURE__ */ jsx104(Fragment19, { children: /* @__PURE__ */ jsx104(ScrollBox_default, { ref: scrollBoxRef, stickyScroll: true, flexDirection: "column", flexGrow: 1, minHeight: 0, width: "100%", children: /* @__PURE__ */ jsxs85(Box_default, { flexDirection: "column", minHeight: 0, width: "100%", children: [
|
|
46415
|
+
topSpacer > 0 && /* @__PURE__ */ jsx104(Box_default, { height: topSpacer }),
|
|
46416
|
+
mountedItems.map((item) => /* @__PURE__ */ jsx104(
|
|
46417
|
+
Box_default,
|
|
46418
|
+
{
|
|
46419
|
+
flexDirection: "column",
|
|
46420
|
+
ref: measureRef(String(item.id)),
|
|
46421
|
+
children: item.component
|
|
46422
|
+
},
|
|
46423
|
+
item.id
|
|
46424
|
+
)),
|
|
46425
|
+
bottomSpacer > 0 && /* @__PURE__ */ jsx104(Box_default, { height: bottomSpacer }),
|
|
46249
46426
|
/* @__PURE__ */ jsx104(
|
|
46250
46427
|
StreamingText,
|
|
46251
46428
|
{
|
|
@@ -46258,10 +46435,13 @@ Please use command_status to check the result and report back to the user.`;
|
|
|
46258
46435
|
appendStreamedAssistant,
|
|
46259
46436
|
appendStreamedReasoning,
|
|
46260
46437
|
eventBus,
|
|
46261
|
-
|
|
46438
|
+
mountedItems,
|
|
46439
|
+
topSpacer,
|
|
46440
|
+
bottomSpacer,
|
|
46441
|
+
measureRef,
|
|
46262
46442
|
liveToolName
|
|
46263
46443
|
]);
|
|
46264
|
-
const bottomDock =
|
|
46444
|
+
const bottomDock = useMemo8(() => /* @__PURE__ */ jsx104(
|
|
46265
46445
|
BlumaBottomDock,
|
|
46266
46446
|
{
|
|
46267
46447
|
eventBus,
|
|
@@ -46311,9 +46491,9 @@ Please use command_status to check the result and report back to the user.`;
|
|
|
46311
46491
|
statusMessage,
|
|
46312
46492
|
workdir
|
|
46313
46493
|
]);
|
|
46314
|
-
const header =
|
|
46315
|
-
const overlay =
|
|
46316
|
-
const floating =
|
|
46494
|
+
const header = useMemo8(() => /* @__PURE__ */ jsx104(Header, { sessionId, workdir, cliVersion }), [cliVersion, sessionId, workdir]);
|
|
46495
|
+
const overlay = useMemo8(() => /* @__PURE__ */ jsx104(BlumaWorkersOverlay, { sessionId }), [sessionId]);
|
|
46496
|
+
const floating = useMemo8(() => /* @__PURE__ */ jsx104(CoordinatorTaskPanel, {}), []);
|
|
46317
46497
|
return /* @__PURE__ */ jsx104(
|
|
46318
46498
|
BlumaViewport,
|
|
46319
46499
|
{
|
|
@@ -46497,7 +46677,7 @@ import React39 from "react";
|
|
|
46497
46677
|
init_agent_session_paths();
|
|
46498
46678
|
|
|
46499
46679
|
// src/app/ui/components/SessionResumePicker.tsx
|
|
46500
|
-
import { memo as memo26, useCallback as
|
|
46680
|
+
import { memo as memo26, useCallback as useCallback12, useEffect as useEffect23, useMemo as useMemo9, useState as useState26 } from "react";
|
|
46501
46681
|
|
|
46502
46682
|
// src/app/agent/session_manager/session_resume_browser.ts
|
|
46503
46683
|
init_bluma_app_dir();
|
|
@@ -46644,12 +46824,12 @@ var SessionResumePickerComponent = ({
|
|
|
46644
46824
|
4,
|
|
46645
46825
|
Math.min(VISIBLE_DEFAULT, (stdout?.rows ?? 24) - 14)
|
|
46646
46826
|
);
|
|
46647
|
-
const [cwd2, setCwd] =
|
|
46648
|
-
const [entries, setEntries] =
|
|
46649
|
-
const [loading, setLoading] =
|
|
46650
|
-
const [selectedIndex, setSelectedIndex] =
|
|
46651
|
-
const [scrollTop, setScrollTop] =
|
|
46652
|
-
const reload =
|
|
46827
|
+
const [cwd2, setCwd] = useState26("");
|
|
46828
|
+
const [entries, setEntries] = useState26([]);
|
|
46829
|
+
const [loading, setLoading] = useState26(true);
|
|
46830
|
+
const [selectedIndex, setSelectedIndex] = useState26(0);
|
|
46831
|
+
const [scrollTop, setScrollTop] = useState26(0);
|
|
46832
|
+
const reload = useCallback12(async (rel) => {
|
|
46653
46833
|
setLoading(true);
|
|
46654
46834
|
try {
|
|
46655
46835
|
const list = await listSessionBrowserEntries(rel);
|
|
@@ -46675,7 +46855,7 @@ var SessionResumePickerComponent = ({
|
|
|
46675
46855
|
setScrollTop(selectedIndex - visibleCount + 1);
|
|
46676
46856
|
}
|
|
46677
46857
|
}, [selectedIndex, scrollTop, visibleCount]);
|
|
46678
|
-
const windowItems =
|
|
46858
|
+
const windowItems = useMemo9(
|
|
46679
46859
|
() => entries.slice(scrollTop, scrollTop + visibleCount),
|
|
46680
46860
|
[entries, scrollTop, visibleCount]
|
|
46681
46861
|
);
|