mixdog 0.9.64 → 0.9.66
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/package.json +1 -1
- package/src/app.mjs +2 -2
- package/src/cli.mjs +1 -1
- package/src/repl.mjs +72 -6
- package/src/runtime/agent/orchestrator/session/context-utils.mjs +76 -21
- package/src/runtime/agent/orchestrator/session/manager/pending-messages.mjs +45 -4
- package/src/runtime/agent/orchestrator/session/manager/session-crud.mjs +11 -1
- package/src/runtime/agent/orchestrator/session/store/summary-cache.mjs +36 -13
- package/src/runtime/agent/orchestrator/session/store-summary-index.mjs +79 -18
- package/src/runtime/agent/orchestrator/session/store-summary-reader.mjs +4 -0
- package/src/runtime/agent/orchestrator/session/store.mjs +37 -2
- package/src/runtime/shared/turn-snapshot.mjs +184 -0
- package/src/session-runtime/context-status.mjs +2 -1
- package/src/session-runtime/provider-request-tools.mjs +6 -0
- package/src/session-runtime/runtime-core.mjs +4 -0
- package/src/session-runtime/session-turn-api.mjs +7 -0
- package/src/session-runtime/tool-catalog-schema.mjs +5 -1
- package/src/tui/App.jsx +1 -1
- package/src/tui/app/transcript-window.mjs +16 -0
- package/src/tui/app/use-transcript-window.mjs +36 -1
- package/src/tui/components/Markdown.jsx +15 -1
- package/src/tui/components/Message.jsx +1 -1
- package/src/tui/components/PromptInput.jsx +7 -0
- package/src/tui/dist/index.mjs +431 -81
- package/src/tui/engine/frame-batched-store.mjs +5 -3
- package/src/tui/engine/live-share.mjs +100 -0
- package/src/tui/engine/render-timing.mjs +28 -0
- package/src/tui/engine/session-api-ext.mjs +10 -0
- package/src/tui/engine/tui-steering-persist.mjs +25 -4
- package/src/tui/engine.mjs +36 -1
- package/src/tui/index.jsx +11 -3
- package/src/tui/markdown/measure-rendered-rows.mjs +28 -16
- package/src/tui/markdown/render-ansi.mjs +34 -1
- package/src/tui/markdown/stream-fence.mjs +44 -7
- package/src/tui/markdown/streaming-markdown.mjs +95 -27
- package/src/ui/stream-finalize.mjs +45 -0
package/src/tui/dist/index.mjs
CHANGED
|
@@ -2588,7 +2588,7 @@ import { render } from "../../../vendor/ink/build/index.js";
|
|
|
2588
2588
|
import { closeSync as closeSync3, constants as fsConstants, createWriteStream as createWriteStream2, mkdirSync as mkdirSync9, openSync as openSync3, readSync } from "node:fs";
|
|
2589
2589
|
import { tmpdir as tmpdir3 } from "node:os";
|
|
2590
2590
|
import { dirname as dirname12, join as join15 } from "node:path";
|
|
2591
|
-
import { performance as
|
|
2591
|
+
import { performance as performance4 } from "node:perf_hooks";
|
|
2592
2592
|
import { format } from "node:util";
|
|
2593
2593
|
|
|
2594
2594
|
// src/tui/App.jsx
|
|
@@ -7274,6 +7274,7 @@ function PromptInput({
|
|
|
7274
7274
|
if (valueRef) valueRef.current = draftRef.current.value;
|
|
7275
7275
|
const { isRawModeSupported } = useStdin();
|
|
7276
7276
|
const boxRef = useRef4(null);
|
|
7277
|
+
const inkRootRef = useRef4(null);
|
|
7277
7278
|
const cursorEnabledRef = useRef4(false);
|
|
7278
7279
|
const contentWidthRef = useRef4(80);
|
|
7279
7280
|
const preferredColumnRef = useRef4(null);
|
|
@@ -7288,9 +7289,15 @@ function PromptInput({
|
|
|
7288
7289
|
}
|
|
7289
7290
|
const flushThrottleRef = useRef4({ lastAt: 0, timer: null });
|
|
7290
7291
|
const flushImmediate = () => {
|
|
7292
|
+
const cachedRoot = inkRootRef.current;
|
|
7293
|
+
if (typeof cachedRoot?.onImmediateRender === "function") {
|
|
7294
|
+
cachedRoot.onImmediateRender();
|
|
7295
|
+
return;
|
|
7296
|
+
}
|
|
7291
7297
|
let node = boxRef.current;
|
|
7292
7298
|
for (let i = 0; node && i < 64; i++) {
|
|
7293
7299
|
if (node.nodeName === "ink-root") {
|
|
7300
|
+
inkRootRef.current = node;
|
|
7294
7301
|
if (typeof node.onImmediateRender === "function") node.onImmediateRender();
|
|
7295
7302
|
return;
|
|
7296
7303
|
}
|
|
@@ -11289,18 +11296,22 @@ function trimPartialClosingFences(tokens) {
|
|
|
11289
11296
|
}
|
|
11290
11297
|
var OPEN_FENCE_RE = /^( {0,3})(`{3,}|~{3,})(.*)$/;
|
|
11291
11298
|
var CLOSE_FENCE_RE = /^ {0,3}([`~]+)[ \t]*$/;
|
|
11299
|
+
var OPEN_FENCE_SCAN_LRU_MAX = 32;
|
|
11300
|
+
var openFenceScanByStreamKey = /* @__PURE__ */ new Map();
|
|
11292
11301
|
function isClosingFence(line, char, openLen) {
|
|
11293
11302
|
const m = CLOSE_FENCE_RE.exec(line);
|
|
11294
11303
|
if (!m) return false;
|
|
11295
11304
|
const run = m[1];
|
|
11296
11305
|
return run.startsWith(char.repeat(openLen));
|
|
11297
11306
|
}
|
|
11298
|
-
function
|
|
11299
|
-
|
|
11300
|
-
let
|
|
11301
|
-
|
|
11302
|
-
|
|
11307
|
+
function scanOpenFence(value, startAt = 0, initialOpen = null) {
|
|
11308
|
+
let open = initialOpen;
|
|
11309
|
+
let start = startAt;
|
|
11310
|
+
const checkpointIndex = value.lastIndexOf("\n") + 1;
|
|
11311
|
+
let openBeforeCheckpoint = start === checkpointIndex ? open : null;
|
|
11312
|
+
for (let i = startAt; i <= value.length; i++) {
|
|
11303
11313
|
if (i !== value.length && value[i] !== "\n") continue;
|
|
11314
|
+
if (start === checkpointIndex) openBeforeCheckpoint = open;
|
|
11304
11315
|
const line = value.slice(start, i);
|
|
11305
11316
|
if (!open) {
|
|
11306
11317
|
const m = OPEN_FENCE_RE.exec(line);
|
|
@@ -11316,13 +11327,42 @@ function findOpenFenceStart(text) {
|
|
|
11316
11327
|
}
|
|
11317
11328
|
start = i + 1;
|
|
11318
11329
|
}
|
|
11319
|
-
|
|
11320
|
-
|
|
11330
|
+
return { open, checkpointIndex, openBeforeCheckpoint };
|
|
11331
|
+
}
|
|
11332
|
+
function touchOpenFenceScan(key, entry) {
|
|
11333
|
+
if (openFenceScanByStreamKey.has(key)) openFenceScanByStreamKey.delete(key);
|
|
11334
|
+
openFenceScanByStreamKey.set(key, entry);
|
|
11335
|
+
while (openFenceScanByStreamKey.size > OPEN_FENCE_SCAN_LRU_MAX) {
|
|
11336
|
+
const oldest = openFenceScanByStreamKey.keys().next().value;
|
|
11337
|
+
if (oldest === void 0) break;
|
|
11338
|
+
openFenceScanByStreamKey.delete(oldest);
|
|
11339
|
+
}
|
|
11340
|
+
}
|
|
11341
|
+
function resetOpenFenceScan(streamKey) {
|
|
11342
|
+
if (streamKey == null || streamKey === "") return;
|
|
11343
|
+
openFenceScanByStreamKey.delete(String(streamKey));
|
|
11344
|
+
}
|
|
11345
|
+
function resetAllOpenFenceScans() {
|
|
11346
|
+
openFenceScanByStreamKey.clear();
|
|
11347
|
+
}
|
|
11348
|
+
function findOpenFenceStart(text, streamKey = null) {
|
|
11349
|
+
const value = String(text ?? "");
|
|
11350
|
+
const key = streamKey == null || streamKey === "" ? null : String(streamKey);
|
|
11351
|
+
const cached = key ? openFenceScanByStreamKey.get(key) : null;
|
|
11352
|
+
if (cached?.text === value) return cached.result;
|
|
11353
|
+
const scanned = cached && value.startsWith(cached.text) ? scanOpenFence(value, cached.checkpointIndex, cached.openBeforeCheckpoint) : scanOpenFence(value);
|
|
11354
|
+
const result = !scanned.open || scanned.open.indent !== 0 ? null : { index: scanned.open.index, lang: scanned.open.lang };
|
|
11355
|
+
if (key) touchOpenFenceScan(key, { text: value, ...scanned, result });
|
|
11356
|
+
return result;
|
|
11321
11357
|
}
|
|
11322
11358
|
|
|
11323
11359
|
// src/tui/markdown/render-ansi.mjs
|
|
11324
11360
|
var TOKEN_CACHE_MAX = 500;
|
|
11325
11361
|
var tokenCache = /* @__PURE__ */ new Map();
|
|
11362
|
+
var renderedSegmentCache = [];
|
|
11363
|
+
var RENDERED_SEGMENT_CACHE_MAX = 12;
|
|
11364
|
+
var RENDERED_SEGMENT_CACHE_MAX_CHARS = 256 * 1024;
|
|
11365
|
+
var renderedSegmentCacheChars = 0;
|
|
11326
11366
|
var MD_SYNTAX_RE = /[#*`|[>\-_~]|\n\n|^\d+\. |\n\d+\. /;
|
|
11327
11367
|
var _configured = false;
|
|
11328
11368
|
function configureMarked() {
|
|
@@ -11384,8 +11424,19 @@ function lexMarkdown(content, { trimPartialFences = false } = {}) {
|
|
|
11384
11424
|
return tokens;
|
|
11385
11425
|
}
|
|
11386
11426
|
function renderTokenAnsiSegments(content, opts = {}) {
|
|
11387
|
-
const
|
|
11427
|
+
const text = String(content ?? "");
|
|
11388
11428
|
const width = Number(opts.width) || 0;
|
|
11429
|
+
const trimPartialFences = opts.trimPartialFences === true;
|
|
11430
|
+
const themeVersion = getThemeVersion();
|
|
11431
|
+
for (let index = renderedSegmentCache.length - 1; index >= 0; index -= 1) {
|
|
11432
|
+
const entry = renderedSegmentCache[index];
|
|
11433
|
+
if (entry.text === text && entry.width === width && entry.trimPartialFences === trimPartialFences && entry.themeVersion === themeVersion) {
|
|
11434
|
+
renderedSegmentCache.splice(index, 1);
|
|
11435
|
+
renderedSegmentCache.push(entry);
|
|
11436
|
+
return entry.segments;
|
|
11437
|
+
}
|
|
11438
|
+
}
|
|
11439
|
+
const tokens = lexMarkdown(text, opts);
|
|
11389
11440
|
const segments = [];
|
|
11390
11441
|
for (const token of tokens) {
|
|
11391
11442
|
if (token.type === "table") {
|
|
@@ -11398,55 +11449,104 @@ function renderTokenAnsiSegments(content, opts = {}) {
|
|
|
11398
11449
|
segments.push({ type: "ansi", ansi, token });
|
|
11399
11450
|
}
|
|
11400
11451
|
}
|
|
11452
|
+
if (text.length <= RENDERED_SEGMENT_CACHE_MAX_CHARS) {
|
|
11453
|
+
const entry = { text, width, trimPartialFences, themeVersion, segments };
|
|
11454
|
+
renderedSegmentCache.push(entry);
|
|
11455
|
+
renderedSegmentCacheChars += text.length;
|
|
11456
|
+
while (renderedSegmentCache.length > RENDERED_SEGMENT_CACHE_MAX || renderedSegmentCacheChars > RENDERED_SEGMENT_CACHE_MAX_CHARS) {
|
|
11457
|
+
const removed = renderedSegmentCache.shift();
|
|
11458
|
+
renderedSegmentCacheChars -= removed?.text.length || 0;
|
|
11459
|
+
}
|
|
11460
|
+
}
|
|
11401
11461
|
return segments;
|
|
11402
11462
|
}
|
|
11403
11463
|
|
|
11404
11464
|
// src/tui/markdown/streaming-markdown.mjs
|
|
11405
11465
|
import { marked as marked2 } from "marked";
|
|
11406
11466
|
var stablePrefixByStreamKey = /* @__PURE__ */ new Map();
|
|
11467
|
+
var markdownSyntaxByStreamKey = /* @__PURE__ */ new Map();
|
|
11468
|
+
var plainWindowSyntaxByStreamKey = /* @__PURE__ */ new Map();
|
|
11407
11469
|
var resolvedPartsByStreamKey = /* @__PURE__ */ new Map();
|
|
11408
11470
|
var STABLE_PREFIX_LRU_MAX = 32;
|
|
11409
11471
|
function streamingLayoutText(text) {
|
|
11410
11472
|
return String(text ?? "").replace(/^\n+|\n+$/g, "");
|
|
11411
11473
|
}
|
|
11412
|
-
function windowPlainStreamingText(text, columns, maxRows) {
|
|
11474
|
+
function windowPlainStreamingText(text, columns, maxRows, streamKey = null) {
|
|
11413
11475
|
const value = streamingLayoutText(text);
|
|
11414
11476
|
const rowBudget = Math.max(0, Math.floor(Number(maxRows) || 0));
|
|
11415
|
-
|
|
11416
|
-
|
|
11477
|
+
const key = streamKey == null || streamKey === "" ? null : String(streamKey);
|
|
11478
|
+
if (!value || rowBudget <= 0 || cachedStreamingHasMarkdownSyntax(
|
|
11479
|
+
plainWindowSyntaxByStreamKey,
|
|
11480
|
+
value,
|
|
11481
|
+
key
|
|
11482
|
+
)) return value;
|
|
11417
11483
|
const width = Math.max(1, Math.floor(Number(columns) || 80));
|
|
11418
11484
|
let rows = 0;
|
|
11419
|
-
let
|
|
11420
|
-
|
|
11421
|
-
|
|
11485
|
+
let end = value.length;
|
|
11486
|
+
let start = end;
|
|
11487
|
+
while (end >= 0) {
|
|
11488
|
+
const newline = value.lastIndexOf("\n", end - 1);
|
|
11489
|
+
const lineStart2 = newline + 1;
|
|
11490
|
+
const line = value.slice(lineStart2, end);
|
|
11422
11491
|
const lineRows = Math.max(1, Math.ceil(displayWidth(line) / width));
|
|
11423
11492
|
if (rows > 0 && rows + lineRows > rowBudget) break;
|
|
11424
11493
|
rows += lineRows;
|
|
11425
|
-
start
|
|
11426
|
-
if (rows >= rowBudget) break;
|
|
11494
|
+
start = lineStart2;
|
|
11495
|
+
if (rows >= rowBudget || newline < 0) break;
|
|
11496
|
+
end = newline;
|
|
11427
11497
|
}
|
|
11428
|
-
return start > 0 ?
|
|
11498
|
+
return start > 0 ? value.slice(start) : value;
|
|
11429
11499
|
}
|
|
11430
11500
|
function isWhitespaceOnlyText(text) {
|
|
11431
11501
|
return !String(text ?? "").trim();
|
|
11432
11502
|
}
|
|
11433
|
-
function
|
|
11503
|
+
function touchLruKey(cache, key, value) {
|
|
11434
11504
|
if (!key) return;
|
|
11435
|
-
if (
|
|
11436
|
-
|
|
11437
|
-
while (
|
|
11438
|
-
const oldest =
|
|
11505
|
+
if (cache.has(key)) cache.delete(key);
|
|
11506
|
+
cache.set(key, value);
|
|
11507
|
+
while (cache.size > STABLE_PREFIX_LRU_MAX) {
|
|
11508
|
+
const oldest = cache.keys().next().value;
|
|
11439
11509
|
if (oldest === void 0) break;
|
|
11440
|
-
|
|
11510
|
+
cache.delete(oldest);
|
|
11441
11511
|
}
|
|
11442
11512
|
}
|
|
11513
|
+
function touchStablePrefixKey(key, value) {
|
|
11514
|
+
touchLruKey(stablePrefixByStreamKey, key, value);
|
|
11515
|
+
}
|
|
11443
11516
|
function getStablePrefixKey(key) {
|
|
11444
|
-
if (!key || !stablePrefixByStreamKey.has(key)) return "";
|
|
11517
|
+
if (!key || !stablePrefixByStreamKey.has(key)) return { text: "", chunks: [] };
|
|
11445
11518
|
const value = stablePrefixByStreamKey.get(key);
|
|
11446
|
-
|
|
11447
|
-
stablePrefixByStreamKey.set(key, value);
|
|
11519
|
+
touchStablePrefixKey(key, value);
|
|
11448
11520
|
return value;
|
|
11449
11521
|
}
|
|
11522
|
+
function stableStateForText(text, previous) {
|
|
11523
|
+
if (!text) return { text: "", chunks: [] };
|
|
11524
|
+
if (text.startsWith(previous.text)) {
|
|
11525
|
+
const appended = text.substring(previous.text.length);
|
|
11526
|
+
return appended ? { text, chunks: [...previous.chunks, appended] } : previous;
|
|
11527
|
+
}
|
|
11528
|
+
return { text, chunks: [text] };
|
|
11529
|
+
}
|
|
11530
|
+
function cachedStreamingHasMarkdownSyntax(cache, text, key) {
|
|
11531
|
+
if (!key) return hasMarkdownSyntax(text);
|
|
11532
|
+
const previous = cache.get(key);
|
|
11533
|
+
let value;
|
|
11534
|
+
if (previous && text.startsWith(previous.text)) {
|
|
11535
|
+
if (previous.value) {
|
|
11536
|
+
value = true;
|
|
11537
|
+
} else {
|
|
11538
|
+
const lineStart2 = previous.text.lastIndexOf("\n") + 1;
|
|
11539
|
+
value = hasMarkdownSyntax(text.substring(Math.max(0, lineStart2 - 1)));
|
|
11540
|
+
}
|
|
11541
|
+
} else {
|
|
11542
|
+
value = hasMarkdownSyntax(text);
|
|
11543
|
+
}
|
|
11544
|
+
touchLruKey(cache, key, { text, value });
|
|
11545
|
+
return value;
|
|
11546
|
+
}
|
|
11547
|
+
function streamingHasMarkdownSyntax(text, key) {
|
|
11548
|
+
return cachedStreamingHasMarkdownSyntax(markdownSyntaxByStreamKey, text, key);
|
|
11549
|
+
}
|
|
11450
11550
|
function getResolvedPartsKey(key, text) {
|
|
11451
11551
|
if (!key) return null;
|
|
11452
11552
|
const entry = resolvedPartsByStreamKey.get(key);
|
|
@@ -11518,11 +11618,17 @@ function resetStreamingMarkdownStablePrefix(streamKey) {
|
|
|
11518
11618
|
if (streamKey == null || streamKey === "") return;
|
|
11519
11619
|
const key = String(streamKey);
|
|
11520
11620
|
stablePrefixByStreamKey.delete(key);
|
|
11621
|
+
markdownSyntaxByStreamKey.delete(key);
|
|
11622
|
+
plainWindowSyntaxByStreamKey.delete(key);
|
|
11521
11623
|
resolvedPartsByStreamKey.delete(key);
|
|
11624
|
+
resetOpenFenceScan(key);
|
|
11522
11625
|
}
|
|
11523
11626
|
function resetAllStreamingMarkdownStablePrefixes() {
|
|
11524
11627
|
stablePrefixByStreamKey.clear();
|
|
11628
|
+
markdownSyntaxByStreamKey.clear();
|
|
11629
|
+
plainWindowSyntaxByStreamKey.clear();
|
|
11525
11630
|
resolvedPartsByStreamKey.clear();
|
|
11631
|
+
resetAllOpenFenceScans();
|
|
11526
11632
|
}
|
|
11527
11633
|
function resolveStreamingMarkdownParts(text, streamKey) {
|
|
11528
11634
|
const t = streamingLayoutText(text);
|
|
@@ -11534,34 +11640,39 @@ function resolveStreamingMarkdownParts(text, streamKey) {
|
|
|
11534
11640
|
return cacheResolvedPartsKey(key, t, {
|
|
11535
11641
|
plain: true,
|
|
11536
11642
|
stablePrefix: "",
|
|
11643
|
+
stableChunks: [],
|
|
11537
11644
|
unstableSuffix: "",
|
|
11538
11645
|
unstableForRender: ""
|
|
11539
11646
|
});
|
|
11540
11647
|
}
|
|
11541
|
-
if (!
|
|
11648
|
+
if (!streamingHasMarkdownSyntax(t, key)) {
|
|
11542
11649
|
if (key) stablePrefixByStreamKey.delete(key);
|
|
11543
11650
|
return cacheResolvedPartsKey(key, t, {
|
|
11544
11651
|
plain: true,
|
|
11545
11652
|
stablePrefix: "",
|
|
11653
|
+
stableChunks: [],
|
|
11546
11654
|
unstableSuffix: t,
|
|
11547
11655
|
unstableForRender: t
|
|
11548
11656
|
});
|
|
11549
11657
|
}
|
|
11550
|
-
let
|
|
11551
|
-
if (!t.startsWith(
|
|
11552
|
-
|
|
11658
|
+
let stableState = key ? getStablePrefixKey(key) : { text: "", chunks: [] };
|
|
11659
|
+
if (!t.startsWith(stableState.text)) {
|
|
11660
|
+
stableState = { text: "", chunks: [] };
|
|
11553
11661
|
}
|
|
11554
|
-
|
|
11662
|
+
let stablePrefix = stableState.text;
|
|
11663
|
+
const open = findOpenFenceStart(t, key);
|
|
11555
11664
|
if (open) {
|
|
11556
11665
|
let openPrefix = t.substring(0, open.index);
|
|
11557
11666
|
if (isWhitespaceOnlyText(openPrefix)) openPrefix = "";
|
|
11558
|
-
|
|
11667
|
+
stableState = stableStateForText(openPrefix, stableState);
|
|
11668
|
+
if (key && openPrefix) touchStablePrefixKey(key, stableState);
|
|
11559
11669
|
else if (key) stablePrefixByStreamKey.delete(key);
|
|
11560
11670
|
const unstableSuffix2 = t.substring(openPrefix.length);
|
|
11561
11671
|
return cacheResolvedPartsKey(key, t, {
|
|
11562
11672
|
plain: false,
|
|
11563
11673
|
openFence: true,
|
|
11564
11674
|
stablePrefix: openPrefix,
|
|
11675
|
+
stableChunks: stableState.chunks,
|
|
11565
11676
|
unstableSuffix: unstableSuffix2,
|
|
11566
11677
|
unstableForRender: unstableSuffix2
|
|
11567
11678
|
});
|
|
@@ -11584,18 +11695,24 @@ function resolveStreamingMarkdownParts(text, streamKey) {
|
|
|
11584
11695
|
if (advance > 0) {
|
|
11585
11696
|
stablePrefix = t.substring(0, boundary + advance);
|
|
11586
11697
|
if (isWhitespaceOnlyText(stablePrefix)) stablePrefix = "";
|
|
11587
|
-
|
|
11698
|
+
stableState = stableStateForText(stablePrefix, stableState);
|
|
11699
|
+
if (key && stablePrefix) touchStablePrefixKey(key, stableState);
|
|
11588
11700
|
else if (key && !stablePrefix) stablePrefixByStreamKey.delete(key);
|
|
11589
11701
|
}
|
|
11590
11702
|
} catch {
|
|
11591
11703
|
stablePrefix = "";
|
|
11704
|
+
stableState = { text: "", chunks: [] };
|
|
11592
11705
|
if (key) stablePrefixByStreamKey.delete(key);
|
|
11593
11706
|
}
|
|
11594
|
-
if (isWhitespaceOnlyText(stablePrefix))
|
|
11707
|
+
if (isWhitespaceOnlyText(stablePrefix)) {
|
|
11708
|
+
stablePrefix = "";
|
|
11709
|
+
stableState = { text: "", chunks: [] };
|
|
11710
|
+
}
|
|
11595
11711
|
const unstableSuffix = t.substring(stablePrefix.length);
|
|
11596
11712
|
return cacheResolvedPartsKey(key, t, {
|
|
11597
11713
|
plain: false,
|
|
11598
11714
|
stablePrefix,
|
|
11715
|
+
stableChunks: stableState.chunks,
|
|
11599
11716
|
unstableSuffix,
|
|
11600
11717
|
unstableForRender: balanceStreamingMarkdown(unstableSuffix)
|
|
11601
11718
|
});
|
|
@@ -11721,22 +11838,31 @@ function measureStreamingMarkdownRenderedRows(text, columns, streamKey) {
|
|
|
11721
11838
|
let rows = 0;
|
|
11722
11839
|
let childCount = 0;
|
|
11723
11840
|
let stableRows = 0;
|
|
11724
|
-
|
|
11725
|
-
|
|
11726
|
-
|
|
11727
|
-
|
|
11728
|
-
|
|
11841
|
+
const stableChunks = parts.stableChunks?.length ? parts.stableChunks : parts.stablePrefix ? [parts.stablePrefix] : [];
|
|
11842
|
+
const reusableChunks = cached && cached.mode === "markdown" && cached.columns === columns && Array.isArray(cached.stableChunks) && cached.stableChunks.length <= stableChunks.length && cached.stableChunks.every((chunk, index) => chunk === stableChunks[index]);
|
|
11843
|
+
let measuredStableChunks = 0;
|
|
11844
|
+
if (reusableChunks) {
|
|
11845
|
+
stableRows = cached.stableRows;
|
|
11846
|
+
measuredStableChunks = cached.stableChunks.length;
|
|
11847
|
+
}
|
|
11848
|
+
for (let index = measuredStableChunks; index < stableChunks.length; index += 1) {
|
|
11849
|
+
if (index > 0) stableRows += 1;
|
|
11850
|
+
stableRows += measureMarkdownRenderedRows(stableChunks[index], columns, { trimPartialFences: false });
|
|
11851
|
+
}
|
|
11852
|
+
rows += stableRows;
|
|
11853
|
+
childCount = stableChunks.length;
|
|
11729
11854
|
if (parts.unstableSuffix) {
|
|
11855
|
+
if (childCount > 0) rows += 1;
|
|
11730
11856
|
rows += measureMarkdownRenderedRows(parts.unstableForRender, columns, { trimPartialFences: true });
|
|
11731
11857
|
childCount += 1;
|
|
11732
11858
|
}
|
|
11733
|
-
if (childCount === 2) rows += 1;
|
|
11734
11859
|
const measuredRows = childCount === 0 ? 1 : Math.max(1, rows);
|
|
11735
11860
|
cacheStreamingRows(key, {
|
|
11736
11861
|
text: value,
|
|
11737
11862
|
columns,
|
|
11738
11863
|
mode: "markdown",
|
|
11739
11864
|
stablePrefix: parts.stablePrefix,
|
|
11865
|
+
stableChunks: stableChunks.slice(),
|
|
11740
11866
|
stableRows,
|
|
11741
11867
|
rows: measuredRows
|
|
11742
11868
|
});
|
|
@@ -12818,6 +12944,9 @@ function cacheStreamingTailEstimate(id, entry) {
|
|
|
12818
12944
|
function hasStreamingRowStateToPrune() {
|
|
12819
12945
|
return streamingMeasuredRowsById.size > 0 || streamingEstimateHighWaterById.size > 0 || streamingTailEstimateById.size > 0;
|
|
12820
12946
|
}
|
|
12947
|
+
function transcriptHarvestInputsEqual(left, right) {
|
|
12948
|
+
return !!left && !!right && left.revision === right.revision && left.settledItems === right.settledItems && left.streamingTailItem === right.streamingTailItem && left.startIndex === right.startIndex && left.endIndex === right.endIndex && left.frameColumns === right.frameColumns && left.toolOutputExpanded === right.toolOutputExpanded && left.transcriptContentHeight === right.transcriptContentHeight && left.floatingPanelRows === right.floatingPanelRows && left.overlayHintRequested === right.overlayHintRequested && left.transcriptGuardRows === right.transcriptGuardRows && left.themeEpoch === right.themeEpoch;
|
|
12949
|
+
}
|
|
12821
12950
|
function pruneStreamingMeasuredRowsById(liveIds) {
|
|
12822
12951
|
if (!liveIds) return;
|
|
12823
12952
|
if (streamingMeasuredRowsById.size > 0) {
|
|
@@ -13632,13 +13761,30 @@ import { useCallback as useCallback3, useEffect as useEffect8, useRef as useRef8
|
|
|
13632
13761
|
// src/tui/engine/render-timing.mjs
|
|
13633
13762
|
var RENDER_ACK_HANG_GUARD_MS = 250;
|
|
13634
13763
|
var RENDER_SETTLE_IDLE_MS = 64;
|
|
13764
|
+
var TUI_RENDER_FPS = 60;
|
|
13765
|
+
var TUI_FRAME_MS = Math.ceil(1e3 / TUI_RENDER_FPS);
|
|
13635
13766
|
var pendingRenderAcks = [];
|
|
13636
13767
|
var renderAckSeq = 0;
|
|
13768
|
+
var lastRenderFrameAt = 0;
|
|
13769
|
+
var renderFrameDelay = (lastFrameAt, currentTime, frameMs = TUI_FRAME_MS) => {
|
|
13770
|
+
if (!(lastFrameAt > 0)) return frameMs;
|
|
13771
|
+
return Math.max(0, frameMs - Math.max(0, currentTime - lastFrameAt));
|
|
13772
|
+
};
|
|
13773
|
+
var scheduleRenderAlignedStoreFlush = (callback, frameMs = TUI_FRAME_MS) => {
|
|
13774
|
+
const timer2 = setTimeout(
|
|
13775
|
+
callback,
|
|
13776
|
+
renderFrameDelay(lastRenderFrameAt, performance.now(), frameMs)
|
|
13777
|
+
);
|
|
13778
|
+
timer2.unref?.();
|
|
13779
|
+
return timer2;
|
|
13780
|
+
};
|
|
13781
|
+
var cancelRenderAlignedStoreFlush = (timer2) => clearTimeout(timer2);
|
|
13637
13782
|
var scheduleRenderFrameAck = () => {
|
|
13638
13783
|
const seq = ++renderAckSeq;
|
|
13639
13784
|
setImmediate(() => notifyRenderFrame(seq));
|
|
13640
13785
|
};
|
|
13641
13786
|
var notifyRenderFrame = (seq = ++renderAckSeq) => {
|
|
13787
|
+
lastRenderFrameAt = performance.now();
|
|
13642
13788
|
if (pendingRenderAcks.length === 0) return;
|
|
13643
13789
|
const acks = pendingRenderAcks;
|
|
13644
13790
|
pendingRenderAcks = [];
|
|
@@ -14285,6 +14431,11 @@ function useTranscriptWindow({
|
|
|
14285
14431
|
const prevViewportGeomRef = useRef9({ contentHeight: 0, floatingPanelRows: 0 });
|
|
14286
14432
|
const transcriptItemElsRef = useRef9(/* @__PURE__ */ new Map());
|
|
14287
14433
|
const transcriptMeasureRefCache = useRef9(/* @__PURE__ */ new Map());
|
|
14434
|
+
const harvestGateRef = useRef9({
|
|
14435
|
+
inputs: null,
|
|
14436
|
+
skippedForDrag: false,
|
|
14437
|
+
forceNext: false
|
|
14438
|
+
});
|
|
14288
14439
|
const transcriptMeasureItemsRef = useRef9(/* @__PURE__ */ new Map());
|
|
14289
14440
|
const transcriptMeasureRef = useCallback4((item) => {
|
|
14290
14441
|
if (!TRANSCRIPT_MEASURED_ROWS || !item || item.id == null) return void 0;
|
|
@@ -14516,11 +14667,33 @@ function useTranscriptWindow({
|
|
|
14516
14667
|
const transcriptTailPinned = Math.max(0, Number(transcriptWindow.effectiveScrollOffset) || 0) === 0;
|
|
14517
14668
|
const overlayHintOnLastItem = overlayHintRequested && floatingPanelRows <= 0 && transcriptWindow.bottomSpacerRows === 0 && transcriptTailPinned && overlayHintAttachItemIndex >= 0;
|
|
14518
14669
|
const overlayHintFallbackRow = overlayHintRequested && floatingPanelRows <= 0 && transcriptGuardRows > 0 && !overlayHintOnLastItem;
|
|
14670
|
+
const harvestInputs = {
|
|
14671
|
+
revision,
|
|
14672
|
+
settledItems,
|
|
14673
|
+
streamingTailItem,
|
|
14674
|
+
startIndex: transcriptWindow.startIndex,
|
|
14675
|
+
endIndex: transcriptWindow.endIndex,
|
|
14676
|
+
frameColumns,
|
|
14677
|
+
toolOutputExpanded,
|
|
14678
|
+
transcriptContentHeight,
|
|
14679
|
+
floatingPanelRows,
|
|
14680
|
+
overlayHintRequested,
|
|
14681
|
+
transcriptGuardRows,
|
|
14682
|
+
themeEpoch
|
|
14683
|
+
};
|
|
14519
14684
|
useLayoutEffect3(() => {
|
|
14520
14685
|
if (!TRANSCRIPT_MEASURED_ROWS) return;
|
|
14521
|
-
|
|
14686
|
+
const gate = harvestGateRef.current;
|
|
14687
|
+
if (dragRef.current.active) {
|
|
14688
|
+
gate.skippedForDrag = true;
|
|
14689
|
+
return;
|
|
14690
|
+
}
|
|
14691
|
+
if (!gate.skippedForDrag && !gate.forceNext && transcriptHarvestInputsEqual(gate.inputs, harvestInputs)) return;
|
|
14522
14692
|
const els = transcriptItemElsRef.current;
|
|
14523
14693
|
if (!els || els.size === 0) return;
|
|
14694
|
+
gate.inputs = harvestInputs;
|
|
14695
|
+
gate.skippedForDrag = false;
|
|
14696
|
+
gate.forceNext = false;
|
|
14524
14697
|
const liveItems = transcriptMeasureItemsRef.current;
|
|
14525
14698
|
const toolExpandedFlag = toolOutputExpanded ? 1 : 0;
|
|
14526
14699
|
let changed = false;
|
|
@@ -14595,6 +14768,7 @@ function useTranscriptWindow({
|
|
|
14595
14768
|
}, 0);
|
|
14596
14769
|
if (typeof streak.timer?.unref === "function") streak.timer.unref();
|
|
14597
14770
|
}
|
|
14771
|
+
gate.forceNext = true;
|
|
14598
14772
|
setMeasuredRowsVersion((v) => (v + 1) % 1e6);
|
|
14599
14773
|
}
|
|
14600
14774
|
}
|
|
@@ -20156,13 +20330,29 @@ function Markdown({ children, themeEpoch = 0, trimPartialFences = false, columns
|
|
|
20156
20330
|
}, [children, themeEpoch, trimPartialFences, columns]);
|
|
20157
20331
|
return /* @__PURE__ */ jsx13(Box11, { flexDirection: "column", gap: 1, children: elements });
|
|
20158
20332
|
}
|
|
20333
|
+
var StableMarkdownChunk = React13.memo(function StableMarkdownChunk2({
|
|
20334
|
+
text,
|
|
20335
|
+
themeEpoch,
|
|
20336
|
+
columns
|
|
20337
|
+
}) {
|
|
20338
|
+
return /* @__PURE__ */ jsx13(Markdown, { themeEpoch, columns, children: text });
|
|
20339
|
+
});
|
|
20159
20340
|
function StreamingMarkdown({ children, themeEpoch = 0, columns, streamKey }) {
|
|
20160
20341
|
const parts = resolveStreamingMarkdownParts(children, streamKey);
|
|
20161
20342
|
if (parts.plain) {
|
|
20162
20343
|
return /* @__PURE__ */ jsx13(Text13, { color: theme.text, wrap: "wrap", children: parts.unstableForRender });
|
|
20163
20344
|
}
|
|
20345
|
+
const stableChunks = parts.stableChunks?.length ? parts.stableChunks : parts.stablePrefix ? [parts.stablePrefix] : [];
|
|
20164
20346
|
return /* @__PURE__ */ jsxs9(Box11, { flexDirection: "column", gap: 1, children: [
|
|
20165
|
-
|
|
20347
|
+
stableChunks.map((text, index) => /* @__PURE__ */ jsx13(
|
|
20348
|
+
StableMarkdownChunk,
|
|
20349
|
+
{
|
|
20350
|
+
text,
|
|
20351
|
+
themeEpoch,
|
|
20352
|
+
columns
|
|
20353
|
+
},
|
|
20354
|
+
`stable-${index}`
|
|
20355
|
+
)),
|
|
20166
20356
|
parts.unstableSuffix ? /* @__PURE__ */ jsx13(Markdown, { themeEpoch, columns, trimPartialFences: true, children: parts.unstableForRender }) : null
|
|
20167
20357
|
] });
|
|
20168
20358
|
}
|
|
@@ -20181,7 +20371,7 @@ var AssistantMessage = React14.memo(function AssistantMessage2({
|
|
|
20181
20371
|
if (!streaming && assistantId) resetStreamingMarkdownStablePrefix(assistantId);
|
|
20182
20372
|
}, [streaming, assistantId]);
|
|
20183
20373
|
const bodyWidth = assistantBodyWidth(columns);
|
|
20184
|
-
const renderText = streaming && streamingWindowRows > 0 ? windowPlainStreamingText(text, bodyWidth, streamingWindowRows) : text;
|
|
20374
|
+
const renderText = streaming && streamingWindowRows > 0 ? windowPlainStreamingText(text, bodyWidth, streamingWindowRows, assistantId) : text;
|
|
20185
20375
|
return /* @__PURE__ */ jsxs10(Box12, { flexDirection: "row", marginTop: 1, children: [
|
|
20186
20376
|
/* @__PURE__ */ jsx14(Box12, { flexShrink: 0, minWidth: 2, children: /* @__PURE__ */ jsx14(Text14, { color: theme.text, children: TURN_MARKER }) }),
|
|
20187
20377
|
/* @__PURE__ */ jsx14(Box12, { flexDirection: "column", flexShrink: 0, width: bodyWidth, children: streaming ? /* @__PURE__ */ jsx14(StreamingMarkdown, { themeEpoch, columns: bodyWidth, streamKey: assistantId, children: renderText }) : /* @__PURE__ */ jsx14(Markdown, { themeEpoch, columns: bodyWidth, children: text }) })
|
|
@@ -23604,7 +23794,7 @@ function App({ store, initialStatusLine = "", forceOnboarding = false }) {
|
|
|
23604
23794
|
StatusLine,
|
|
23605
23795
|
{
|
|
23606
23796
|
sessionId: state.sessionId,
|
|
23607
|
-
clientHostPid: state.clientHostPid,
|
|
23797
|
+
clientHostPid: state.ownerClientHostPid || state.clientHostPid,
|
|
23608
23798
|
provider: state.provider,
|
|
23609
23799
|
model: state.model,
|
|
23610
23800
|
effort: state.effort,
|
|
@@ -23633,7 +23823,7 @@ function App({ store, initialStatusLine = "", forceOnboarding = false }) {
|
|
|
23633
23823
|
}
|
|
23634
23824
|
|
|
23635
23825
|
// src/tui/engine.mjs
|
|
23636
|
-
import { performance as
|
|
23826
|
+
import { performance as performance3 } from "node:perf_hooks";
|
|
23637
23827
|
import { mkdtempSync as mkdtempSync2, readFileSync as readFileSync11, readdirSync as readdirSync5, rmSync as rmSync4, statSync as statSync7, watch as watch2, writeFileSync as writeFileSync8 } from "node:fs";
|
|
23638
23828
|
import { basename as basename7, dirname as dirname11, join as join14 } from "node:path";
|
|
23639
23829
|
|
|
@@ -23916,12 +24106,12 @@ function sessionPath(id) {
|
|
|
23916
24106
|
}
|
|
23917
24107
|
|
|
23918
24108
|
// src/tui/engine/boot-profile.mjs
|
|
23919
|
-
import { performance } from "node:perf_hooks";
|
|
24109
|
+
import { performance as performance2 } from "node:perf_hooks";
|
|
23920
24110
|
var BOOT_PROFILE_ENABLED = /^(1|true|yes|on)$/i.test(String(process.env.MIXDOG_BOOT_PROFILE || ""));
|
|
23921
|
-
var BOOT_PROFILE_START = globalThis.__mixdogBootProfileStart || (globalThis.__mixdogBootProfileStart =
|
|
24111
|
+
var BOOT_PROFILE_START = globalThis.__mixdogBootProfileStart || (globalThis.__mixdogBootProfileStart = performance2.now());
|
|
23922
24112
|
function bootProfile(event, fields = {}) {
|
|
23923
24113
|
if (!BOOT_PROFILE_ENABLED) return;
|
|
23924
|
-
const elapsedMs =
|
|
24114
|
+
const elapsedMs = performance2.now() - BOOT_PROFILE_START;
|
|
23925
24115
|
const parts = [`[mixdog-boot] +${elapsedMs.toFixed(1)}ms`, `tui:${event}`];
|
|
23926
24116
|
for (const [key, value] of Object.entries(fields || {})) {
|
|
23927
24117
|
if (value === void 0 || value === null || value === "") continue;
|
|
@@ -25611,6 +25801,7 @@ import { randomBytes as randomBytes3 } from "crypto";
|
|
|
25611
25801
|
import { join as join10 } from "path";
|
|
25612
25802
|
var PENDING_MESSAGES_FILE = "session-pending-messages.json";
|
|
25613
25803
|
var PENDING_MESSAGES_MODE = 384;
|
|
25804
|
+
var STALE_STEERING_RESTORE_TTL_MS = 30 * 60 * 1e3;
|
|
25614
25805
|
var _persistChain = Promise.resolve();
|
|
25615
25806
|
function _serialize(task) {
|
|
25616
25807
|
const run = _persistChain.then(task, task);
|
|
@@ -25637,7 +25828,9 @@ function normalizeTuiSteeringQueueEntry(entry) {
|
|
|
25637
25828
|
if (typeof entry.text === "string" && entry.text.trim()) {
|
|
25638
25829
|
const text = entry.text.trim();
|
|
25639
25830
|
const id = typeof entry.id === "string" && entry.id.trim() ? entry.id.trim() : null;
|
|
25640
|
-
|
|
25831
|
+
if (!id) return text;
|
|
25832
|
+
const at = Number(entry.at);
|
|
25833
|
+
return Number.isFinite(at) && at > 0 ? { id, text, at } : { id, text };
|
|
25641
25834
|
}
|
|
25642
25835
|
return null;
|
|
25643
25836
|
}
|
|
@@ -25689,7 +25882,7 @@ function appendTuiSteeringPersist(leadSessionId, entry) {
|
|
|
25689
25882
|
const key = tuiSteeringSessionKey(leadSessionId);
|
|
25690
25883
|
if (!key) return Promise.resolve();
|
|
25691
25884
|
if (!entry.steeringPersistId) entry.steeringPersistId = newSteeringPersistId();
|
|
25692
|
-
const record = { id: entry.steeringPersistId, text };
|
|
25885
|
+
const record = { id: entry.steeringPersistId, text, at: Date.now() };
|
|
25693
25886
|
return _serialize(async () => {
|
|
25694
25887
|
try {
|
|
25695
25888
|
await updateJsonAtomic(pendingMessagesPath(), (raw) => {
|
|
@@ -25761,12 +25954,21 @@ function drainTuiSteeringPersist(leadSessionId) {
|
|
|
25761
25954
|
if (!key) return Promise.resolve([]);
|
|
25762
25955
|
return _serialize(async () => {
|
|
25763
25956
|
let drained = [];
|
|
25957
|
+
let droppedStale = 0;
|
|
25764
25958
|
try {
|
|
25765
25959
|
await updateJsonAtomic(pendingMessagesPath(), (raw) => {
|
|
25766
25960
|
const next = normalizePendingStore(raw);
|
|
25767
25961
|
const q = Array.isArray(next.sessions[key]) ? next.sessions[key] : [];
|
|
25768
|
-
|
|
25769
|
-
|
|
25962
|
+
const now = Date.now();
|
|
25963
|
+
const touchedAt = Number(next.sessionTouchedAt?.[key]) || 0;
|
|
25964
|
+
const fresh = q.filter((row) => {
|
|
25965
|
+
const at = Number(row?.at) || touchedAt;
|
|
25966
|
+
const stale = at > 0 && now - at > STALE_STEERING_RESTORE_TTL_MS;
|
|
25967
|
+
if (stale) droppedStale += 1;
|
|
25968
|
+
return !stale;
|
|
25969
|
+
});
|
|
25970
|
+
drained = fresh.map(drainedRowToRestore).filter(Boolean);
|
|
25971
|
+
if (drained.length === 0 && droppedStale === 0) return void 0;
|
|
25770
25972
|
delete next.sessions[key];
|
|
25771
25973
|
if (next.sessionTouchedAt) delete next.sessionTouchedAt[key];
|
|
25772
25974
|
next.updatedAt = Date.now();
|
|
@@ -25775,6 +25977,13 @@ function drainTuiSteeringPersist(leadSessionId) {
|
|
|
25775
25977
|
} catch (err) {
|
|
25776
25978
|
try {
|
|
25777
25979
|
process.stderr.write(`[tui] steering-queue drain failed sessionId=${leadSessionId}: ${err?.message || err}
|
|
25980
|
+
`);
|
|
25981
|
+
} catch {
|
|
25982
|
+
}
|
|
25983
|
+
}
|
|
25984
|
+
if (droppedStale > 0) {
|
|
25985
|
+
try {
|
|
25986
|
+
process.stderr.write(`[tui] dropped ${droppedStale} stale steering row(s) sessionId=${leadSessionId}
|
|
25778
25987
|
`);
|
|
25779
25988
|
} catch {
|
|
25780
25989
|
}
|
|
@@ -28049,6 +28258,9 @@ function createEngineApiB(bag) {
|
|
|
28049
28258
|
getUsageDashboard: async (options = {}) => {
|
|
28050
28259
|
return await runtime.getUsageDashboard?.(options);
|
|
28051
28260
|
},
|
|
28261
|
+
getTurnReviewDiff: async () => {
|
|
28262
|
+
return await runtime.getTurnReviewDiff?.() ?? { supported: false, files: [], patch: "" };
|
|
28263
|
+
},
|
|
28052
28264
|
getOnboardingStatus: () => {
|
|
28053
28265
|
return runtime.getOnboardingStatus?.() || { completed: true, workflowRoutes: {} };
|
|
28054
28266
|
},
|
|
@@ -28273,6 +28485,17 @@ function createEngineApiB(bag) {
|
|
|
28273
28485
|
listSessions: (options) => {
|
|
28274
28486
|
return runtime.listSessions(options);
|
|
28275
28487
|
},
|
|
28488
|
+
// Desktop sidebar watcher hook: EngineHost fs.watches this directory so
|
|
28489
|
+
// heartbeat sidecar create/delete pushes instant working/dot updates.
|
|
28490
|
+
// Without it the watcher silently no-ops and the sidebar falls back to
|
|
28491
|
+
// the 60s safety poll (user: spinner kept spinning after the turn ended).
|
|
28492
|
+
sessionStoreDir: () => {
|
|
28493
|
+
try {
|
|
28494
|
+
return runtime.sessionStoreDir?.() || null;
|
|
28495
|
+
} catch {
|
|
28496
|
+
return null;
|
|
28497
|
+
}
|
|
28498
|
+
},
|
|
28276
28499
|
deleteSession: async (id) => {
|
|
28277
28500
|
if (getState().commandBusy) return false;
|
|
28278
28501
|
const deletingCurrent = String(runtime.session?.id || getState().sessionId || "") === String(id || "");
|
|
@@ -29244,7 +29467,9 @@ function createFrameBatchedStorePublisher({
|
|
|
29244
29467
|
frameMs = 16,
|
|
29245
29468
|
setTimer = setTimeout,
|
|
29246
29469
|
clearTimer = clearTimeout,
|
|
29247
|
-
enqueueMicrotask = queueMicrotask
|
|
29470
|
+
enqueueMicrotask = queueMicrotask,
|
|
29471
|
+
scheduleFrame = (callback, delay2) => setTimer(callback, delay2),
|
|
29472
|
+
cancelFrame = (handle) => clearTimer(handle)
|
|
29248
29473
|
}) {
|
|
29249
29474
|
let timer2 = null;
|
|
29250
29475
|
let emitPending = false;
|
|
@@ -29252,7 +29477,7 @@ function createFrameBatchedStorePublisher({
|
|
|
29252
29477
|
let immediatePending = false;
|
|
29253
29478
|
const flush = () => {
|
|
29254
29479
|
if (timer2 !== null) {
|
|
29255
|
-
|
|
29480
|
+
cancelFrame(timer2);
|
|
29256
29481
|
timer2 = null;
|
|
29257
29482
|
}
|
|
29258
29483
|
immediatePending = false;
|
|
@@ -29274,7 +29499,7 @@ function createFrameBatchedStorePublisher({
|
|
|
29274
29499
|
const emit = () => {
|
|
29275
29500
|
emitPending = true;
|
|
29276
29501
|
if (timer2 !== null || isDisposed()) return;
|
|
29277
|
-
timer2 =
|
|
29502
|
+
timer2 = scheduleFrame(flush, frameMs);
|
|
29278
29503
|
timer2?.unref?.();
|
|
29279
29504
|
};
|
|
29280
29505
|
const markStructureChange = () => {
|
|
@@ -29288,7 +29513,7 @@ function createFrameBatchedStorePublisher({
|
|
|
29288
29513
|
};
|
|
29289
29514
|
const dispose = () => {
|
|
29290
29515
|
if (emitPending && !isDisposed()) flush();
|
|
29291
|
-
else if (timer2 !== null)
|
|
29516
|
+
else if (timer2 !== null) cancelFrame(timer2);
|
|
29292
29517
|
timer2 = null;
|
|
29293
29518
|
emitPending = false;
|
|
29294
29519
|
structureChangePending = false;
|
|
@@ -29341,6 +29566,7 @@ function createLiveShare({
|
|
|
29341
29566
|
getPublishedState,
|
|
29342
29567
|
listeners,
|
|
29343
29568
|
onRemoteSubmit,
|
|
29569
|
+
onRemoteAbort,
|
|
29344
29570
|
onOwnerClosed,
|
|
29345
29571
|
viewerApply
|
|
29346
29572
|
}) {
|
|
@@ -29351,6 +29577,7 @@ function createLiveShare({
|
|
|
29351
29577
|
let lastItems = null;
|
|
29352
29578
|
let lastTail = null;
|
|
29353
29579
|
let lastSpinner = null;
|
|
29580
|
+
let lastLiveSig = "";
|
|
29354
29581
|
const broadcast = (frame) => {
|
|
29355
29582
|
if (sockets.size === 0) return;
|
|
29356
29583
|
const line = frameLine(frame);
|
|
@@ -29361,12 +29588,50 @@ function createLiveShare({
|
|
|
29361
29588
|
}
|
|
29362
29589
|
}
|
|
29363
29590
|
};
|
|
29591
|
+
const LIVE_STATS_KEYS = [
|
|
29592
|
+
"currentContextSource",
|
|
29593
|
+
"currentContextTokens",
|
|
29594
|
+
"currentEstimatedContextTokens",
|
|
29595
|
+
"currentContextUpdatedAt",
|
|
29596
|
+
"costUsd",
|
|
29597
|
+
"turns",
|
|
29598
|
+
"inputTokens",
|
|
29599
|
+
"outputTokens",
|
|
29600
|
+
"latestInputTokens",
|
|
29601
|
+
"latestPromptTokens",
|
|
29602
|
+
"contextTokens"
|
|
29603
|
+
];
|
|
29604
|
+
const liveStateOf = (st) => {
|
|
29605
|
+
const stats = st.stats && typeof st.stats === "object" ? st.stats : {};
|
|
29606
|
+
const statsSubset = {};
|
|
29607
|
+
for (const key of LIVE_STATS_KEYS) {
|
|
29608
|
+
if (stats[key] !== void 0) statsSubset[key] = stats[key];
|
|
29609
|
+
}
|
|
29610
|
+
return {
|
|
29611
|
+
busy: st.busy === true,
|
|
29612
|
+
commandBusy: st.commandBusy === true,
|
|
29613
|
+
queued: (Array.isArray(st.queued) ? st.queued : []).map((entry) => ({
|
|
29614
|
+
id: entry?.id,
|
|
29615
|
+
text: String(entry?.displayText ?? entry?.text ?? entry?.message ?? "").slice(0, 2e3),
|
|
29616
|
+
...entry?.enqueuedAt ? { enqueuedAt: entry.enqueuedAt } : {}
|
|
29617
|
+
})),
|
|
29618
|
+
activeToolSummary: st.activeToolSummary || null,
|
|
29619
|
+
agentWorkers: Array.isArray(st.agentWorkers) ? st.agentWorkers : [],
|
|
29620
|
+
agentJobs: Array.isArray(st.agentJobs) ? st.agentJobs : [],
|
|
29621
|
+
ownerClientHostPid: Number(st.clientHostPid) || process.pid,
|
|
29622
|
+
displayContextWindow: Number(st.displayContextWindow) || 0,
|
|
29623
|
+
compactBoundaryTokens: Number(st.compactBoundaryTokens) || 0,
|
|
29624
|
+
autoCompactTokenLimit: Number(st.autoCompactTokenLimit) || 0,
|
|
29625
|
+
stats: statsSubset
|
|
29626
|
+
};
|
|
29627
|
+
};
|
|
29364
29628
|
const fullFrame = (st) => ({
|
|
29365
29629
|
t: "full",
|
|
29366
29630
|
sessionId: serverId,
|
|
29367
29631
|
items: Array.isArray(st.items) ? st.items : [],
|
|
29368
29632
|
tail: st.streamingTail || null,
|
|
29369
|
-
spinner: st.spinner || null
|
|
29633
|
+
spinner: st.spinner || null,
|
|
29634
|
+
live: liveStateOf(st)
|
|
29370
29635
|
});
|
|
29371
29636
|
const onPublish = () => {
|
|
29372
29637
|
const st = getPublishedState();
|
|
@@ -29374,6 +29639,7 @@ function createLiveShare({
|
|
|
29374
29639
|
lastItems = st.items;
|
|
29375
29640
|
lastTail = st.streamingTail;
|
|
29376
29641
|
lastSpinner = st.spinner;
|
|
29642
|
+
lastLiveSig = "";
|
|
29377
29643
|
return;
|
|
29378
29644
|
}
|
|
29379
29645
|
const frame = { t: "delta" };
|
|
@@ -29432,6 +29698,13 @@ function createLiveShare({
|
|
|
29432
29698
|
lastSpinner = st.spinner;
|
|
29433
29699
|
dirty = true;
|
|
29434
29700
|
}
|
|
29701
|
+
const live = liveStateOf(st);
|
|
29702
|
+
const liveSig = JSON.stringify(live);
|
|
29703
|
+
if (liveSig !== lastLiveSig) {
|
|
29704
|
+
frame.live = live;
|
|
29705
|
+
lastLiveSig = liveSig;
|
|
29706
|
+
dirty = true;
|
|
29707
|
+
}
|
|
29435
29708
|
if (dirty) broadcast(frame);
|
|
29436
29709
|
};
|
|
29437
29710
|
listeners.add(onPublish);
|
|
@@ -29480,6 +29753,8 @@ function createLiveShare({
|
|
|
29480
29753
|
attachLineReader(socket, (frame) => {
|
|
29481
29754
|
if (frame.t === "submit" && typeof frame.text === "string" && frame.text.trim()) {
|
|
29482
29755
|
onRemoteSubmit(frame.text);
|
|
29756
|
+
} else if (frame.t === "abort") {
|
|
29757
|
+
onRemoteAbort?.();
|
|
29483
29758
|
} else if (frame.t === "sync") {
|
|
29484
29759
|
try {
|
|
29485
29760
|
socket.write(frameLine(fullFrame(getPublishedState())));
|
|
@@ -29497,6 +29772,7 @@ function createLiveShare({
|
|
|
29497
29772
|
lastItems = st.items;
|
|
29498
29773
|
lastTail = st.streamingTail;
|
|
29499
29774
|
lastSpinner = st.spinner;
|
|
29775
|
+
lastLiveSig = JSON.stringify(liveStateOf(st));
|
|
29500
29776
|
socket.write(frameLine(fullFrame(st)));
|
|
29501
29777
|
} catch {
|
|
29502
29778
|
try {
|
|
@@ -29582,11 +29858,47 @@ function createLiveShare({
|
|
|
29582
29858
|
if (exists) viewerApply.patchItem(item.id, item);
|
|
29583
29859
|
else viewerApply.appendItems([item]);
|
|
29584
29860
|
};
|
|
29861
|
+
const applyLiveState = (live) => {
|
|
29862
|
+
if (!live || typeof live !== "object") return;
|
|
29863
|
+
const patch = {
|
|
29864
|
+
busy: live.busy === true,
|
|
29865
|
+
commandBusy: live.commandBusy === true,
|
|
29866
|
+
queued: Array.isArray(live.queued) ? live.queued : [],
|
|
29867
|
+
activeToolSummary: live.activeToolSummary || null,
|
|
29868
|
+
agentWorkers: Array.isArray(live.agentWorkers) ? live.agentWorkers : [],
|
|
29869
|
+
agentJobs: Array.isArray(live.agentJobs) ? live.agentJobs : [],
|
|
29870
|
+
ownerClientHostPid: Number(live.ownerClientHostPid) || 0
|
|
29871
|
+
};
|
|
29872
|
+
for (const key of ["displayContextWindow", "compactBoundaryTokens", "autoCompactTokenLimit"]) {
|
|
29873
|
+
if (Number(live[key]) > 0) patch[key] = Number(live[key]);
|
|
29874
|
+
}
|
|
29875
|
+
if (live.stats && typeof live.stats === "object" && Object.keys(live.stats).length > 0) {
|
|
29876
|
+
const current = viewerApply.getState().stats;
|
|
29877
|
+
patch.stats = { ...current && typeof current === "object" ? current : {}, ...live.stats };
|
|
29878
|
+
}
|
|
29879
|
+
viewerApply.set(patch);
|
|
29880
|
+
};
|
|
29881
|
+
const clearMirroredLiveState = () => {
|
|
29882
|
+
try {
|
|
29883
|
+
viewerApply?.set?.({
|
|
29884
|
+
busy: false,
|
|
29885
|
+
commandBusy: false,
|
|
29886
|
+
spinner: null,
|
|
29887
|
+
queued: [],
|
|
29888
|
+
activeToolSummary: null,
|
|
29889
|
+
agentWorkers: [],
|
|
29890
|
+
agentJobs: [],
|
|
29891
|
+
ownerClientHostPid: 0
|
|
29892
|
+
});
|
|
29893
|
+
} catch {
|
|
29894
|
+
}
|
|
29895
|
+
};
|
|
29585
29896
|
const applyViewerFrame = (frame, socket) => {
|
|
29586
29897
|
if (frame.t === "full") {
|
|
29587
29898
|
viewerApply.replaceItems(Array.isArray(frame.items) ? frame.items : []);
|
|
29588
29899
|
if (frame.tail) viewerApply.updateStreamingTail(frame.tail.id, frame.tail);
|
|
29589
29900
|
viewerApply.set({ spinner: frame.spinner || null });
|
|
29901
|
+
applyLiveState(frame.live);
|
|
29590
29902
|
return;
|
|
29591
29903
|
}
|
|
29592
29904
|
if (frame.t !== "delta") return;
|
|
@@ -29612,6 +29924,7 @@ function createLiveShare({
|
|
|
29612
29924
|
else viewerApply.clearStreamingTail();
|
|
29613
29925
|
}
|
|
29614
29926
|
if ("spinner" in frame) viewerApply.set({ spinner: frame.spinner || null });
|
|
29927
|
+
if ("live" in frame) applyLiveState(frame.live);
|
|
29615
29928
|
};
|
|
29616
29929
|
const stopClient = () => {
|
|
29617
29930
|
const closing = client;
|
|
@@ -29654,6 +29967,7 @@ function createLiveShare({
|
|
|
29654
29967
|
socket.destroy();
|
|
29655
29968
|
} catch {
|
|
29656
29969
|
}
|
|
29970
|
+
if (wasUp) clearMirroredLiveState();
|
|
29657
29971
|
if (wasUp) onOwnerClosed?.(id, ownerClosed);
|
|
29658
29972
|
};
|
|
29659
29973
|
socket.on("error", () => down(false));
|
|
@@ -29698,6 +30012,15 @@ function createLiveShare({
|
|
|
29698
30012
|
return false;
|
|
29699
30013
|
}
|
|
29700
30014
|
},
|
|
30015
|
+
sendAbort() {
|
|
30016
|
+
if (!clientUp || !client) return false;
|
|
30017
|
+
try {
|
|
30018
|
+
client.write(frameLine({ t: "abort" }));
|
|
30019
|
+
return true;
|
|
30020
|
+
} catch {
|
|
30021
|
+
return false;
|
|
30022
|
+
}
|
|
30023
|
+
},
|
|
29701
30024
|
dispose() {
|
|
29702
30025
|
listeners.delete(onPublish);
|
|
29703
30026
|
stopServer();
|
|
@@ -30212,16 +30535,16 @@ async function createEngineSession({
|
|
|
30212
30535
|
cwd,
|
|
30213
30536
|
desktopSession
|
|
30214
30537
|
} = {}) {
|
|
30215
|
-
const startedAt =
|
|
30538
|
+
const startedAt = performance3.now();
|
|
30216
30539
|
bootProfile("engine:create:start", { provider: providerName, model, toolMode, remote });
|
|
30217
30540
|
process.env.MIXDOG_QUIET_PROVIDER_LOG = "1";
|
|
30218
30541
|
process.env.MIXDOG_QUIET_SESSION_LOG = "1";
|
|
30219
30542
|
process.env.MIXDOG_QUIET_MCP_LOG = "1";
|
|
30220
30543
|
process.env.MIXDOG_QUIET_MEMORY_LOG = "1";
|
|
30221
30544
|
process.env.MIXDOG_PATCH_NATIVE_PREWARM ??= "0";
|
|
30222
|
-
const importStartedAt =
|
|
30545
|
+
const importStartedAt = performance3.now();
|
|
30223
30546
|
const { createMixdogSessionRuntime } = await import(SESSION_RUNTIME_MODULE);
|
|
30224
|
-
bootProfile("session-runtime:imported", { ms: (
|
|
30547
|
+
bootProfile("session-runtime:imported", { ms: (performance3.now() - importStartedAt).toFixed(1) });
|
|
30225
30548
|
const runtime = await createMixdogSessionRuntime({
|
|
30226
30549
|
provider: providerName,
|
|
30227
30550
|
model,
|
|
@@ -30230,9 +30553,9 @@ async function createEngineSession({
|
|
|
30230
30553
|
...cwd ? { cwd } : {},
|
|
30231
30554
|
...desktopSession ? { desktopSession } : {}
|
|
30232
30555
|
});
|
|
30233
|
-
bootProfile("engine:create:runtime-ready", { ms: (
|
|
30556
|
+
bootProfile("engine:create:runtime-ready", { ms: (performance3.now() - startedAt).toFixed(1) });
|
|
30234
30557
|
const runtimeCwd = runtime.cwd || process.cwd();
|
|
30235
|
-
const stateStartedAt =
|
|
30558
|
+
const stateStartedAt = performance3.now();
|
|
30236
30559
|
const flags = {
|
|
30237
30560
|
disposed: false,
|
|
30238
30561
|
draining: false,
|
|
@@ -30308,11 +30631,11 @@ async function createEngineSession({
|
|
|
30308
30631
|
cwd: runtimeCwd,
|
|
30309
30632
|
themeEpoch: 0
|
|
30310
30633
|
};
|
|
30311
|
-
bootProfile("engine:route-state-ready", { ms: (
|
|
30312
|
-
bootProfile("engine:state-ready", { ms: (
|
|
30313
|
-
const contextStartedAt =
|
|
30634
|
+
bootProfile("engine:route-state-ready", { ms: (performance3.now() - stateStartedAt).toFixed(1) });
|
|
30635
|
+
bootProfile("engine:state-ready", { ms: (performance3.now() - stateStartedAt).toFixed(1) });
|
|
30636
|
+
const contextStartedAt = performance3.now();
|
|
30314
30637
|
syncContextStats({ allowEstimated: true });
|
|
30315
|
-
bootProfile("engine:context-ready", { ms: (
|
|
30638
|
+
bootProfile("engine:context-ready", { ms: (performance3.now() - contextStartedAt).toFixed(1) });
|
|
30316
30639
|
const listeners = /* @__PURE__ */ new Set();
|
|
30317
30640
|
let publishedState = process.env.NODE_ENV === "production" ? state : Object.freeze(state);
|
|
30318
30641
|
state = { ...state, stats: { ...state.stats } };
|
|
@@ -30323,7 +30646,10 @@ async function createEngineSession({
|
|
|
30323
30646
|
state = { ...next, stats: { ...next.stats } };
|
|
30324
30647
|
},
|
|
30325
30648
|
listeners,
|
|
30326
|
-
isDisposed: () => flags.disposed
|
|
30649
|
+
isDisposed: () => flags.disposed,
|
|
30650
|
+
frameMs: TUI_FRAME_MS,
|
|
30651
|
+
scheduleFrame: scheduleRenderAlignedStoreFlush,
|
|
30652
|
+
cancelFrame: cancelRenderAlignedStoreFlush
|
|
30327
30653
|
});
|
|
30328
30654
|
const emit = publisher.emit;
|
|
30329
30655
|
const flushEmit = publisher.flush;
|
|
@@ -30667,6 +30993,10 @@ async function createEngineSession({
|
|
|
30667
30993
|
lifecycle.runtimePulseTimer = setInterval(() => {
|
|
30668
30994
|
if (flags.disposed) return;
|
|
30669
30995
|
if (flags.pendingSessionReset) return;
|
|
30996
|
+
if (bag.liveShareMirroring?.()) {
|
|
30997
|
+
set({ ...routeState() });
|
|
30998
|
+
return;
|
|
30999
|
+
}
|
|
30670
31000
|
syncContextStats({ allowEstimated: true });
|
|
30671
31001
|
set({
|
|
30672
31002
|
...routeState(),
|
|
@@ -30812,6 +31142,13 @@ async function createEngineSession({
|
|
|
30812
31142
|
bag.enqueue(text);
|
|
30813
31143
|
void bag.drain();
|
|
30814
31144
|
},
|
|
31145
|
+
onRemoteAbort: () => {
|
|
31146
|
+
if (flags.disposed || state.sessionRemoteAttached) return;
|
|
31147
|
+
try {
|
|
31148
|
+
api.abort?.();
|
|
31149
|
+
} catch {
|
|
31150
|
+
}
|
|
31151
|
+
},
|
|
30815
31152
|
onOwnerClosed: (id) => {
|
|
30816
31153
|
const timer2 = setTimeout(() => {
|
|
30817
31154
|
if (flags.disposed || !state.sessionRemoteAttached) return;
|
|
@@ -30837,6 +31174,7 @@ async function createEngineSession({
|
|
|
30837
31174
|
} catch {
|
|
30838
31175
|
}
|
|
30839
31176
|
};
|
|
31177
|
+
bag.liveShareMirroring = () => state.sessionRemoteAttached && liveShare.viewerConnected();
|
|
30840
31178
|
if (typeof api.submit === "function") {
|
|
30841
31179
|
const baseSubmit = api.submit;
|
|
30842
31180
|
api.submit = (prompt, options = {}) => {
|
|
@@ -30847,6 +31185,15 @@ async function createEngineSession({
|
|
|
30847
31185
|
return baseSubmit(prompt, options);
|
|
30848
31186
|
};
|
|
30849
31187
|
}
|
|
31188
|
+
if (typeof api.abort === "function") {
|
|
31189
|
+
const baseAbort = api.abort;
|
|
31190
|
+
api.abort = (...args) => {
|
|
31191
|
+
if (state.sessionRemoteAttached && liveShare.viewerConnected() && liveShare.sendAbort()) {
|
|
31192
|
+
return true;
|
|
31193
|
+
}
|
|
31194
|
+
return baseAbort(...args);
|
|
31195
|
+
};
|
|
31196
|
+
}
|
|
30850
31197
|
const reconcileLiveShareNow = () => {
|
|
30851
31198
|
try {
|
|
30852
31199
|
liveShare.ensure();
|
|
@@ -30978,7 +31325,7 @@ var XTSHIFTESCAPE_ON = process.env.WT_SESSION ? "" : "\x1B[>1s";
|
|
|
30978
31325
|
var MOUSE_TRACKING_ON2 = `\x1B[?1000h\x1B[?1002h\x1B[?1006h\x1B[?1007l${XTSHIFTESCAPE_ON}`;
|
|
30979
31326
|
var ALT_SCROLL_RESTORE = "\x1B[?1007h";
|
|
30980
31327
|
var BOOT_PROFILE_ENABLED2 = /^(1|true|yes|on)$/i.test(String(process.env.MIXDOG_BOOT_PROFILE || ""));
|
|
30981
|
-
var BOOT_PROFILE_START2 = globalThis.__mixdogBootProfileStart || (globalThis.__mixdogBootProfileStart =
|
|
31328
|
+
var BOOT_PROFILE_START2 = globalThis.__mixdogBootProfileStart || (globalThis.__mixdogBootProfileStart = performance4.now());
|
|
30982
31329
|
var EXIT_WAIT_TIMEOUT_MS = positiveIntEnv2("MIXDOG_TUI_EXIT_WAIT_MS", 2500);
|
|
30983
31330
|
var EXIT_HARD_DELAY_MS = positiveIntEnv2("MIXDOG_TUI_HARD_EXIT_DELAY_MS", 500);
|
|
30984
31331
|
var EXIT_HARD_ENABLED = !/^(0|false|no|off)$/i.test(String(process.env.MIXDOG_TUI_HARD_EXIT || "1"));
|
|
@@ -30994,9 +31341,9 @@ function positiveIntEnv2(name, fallback) {
|
|
|
30994
31341
|
function installTuiLoopProbe() {
|
|
30995
31342
|
if (!LOOP_PROBE_ENABLED) return () => {
|
|
30996
31343
|
};
|
|
30997
|
-
let last =
|
|
31344
|
+
let last = performance4.now();
|
|
30998
31345
|
const timer2 = setInterval(() => {
|
|
30999
|
-
const now =
|
|
31346
|
+
const now = performance4.now();
|
|
31000
31347
|
const drift = now - last - LOOP_PROBE_INTERVAL_MS;
|
|
31001
31348
|
last = now;
|
|
31002
31349
|
if (drift > LOOP_PROBE_DRIFT_THRESHOLD_MS) {
|
|
@@ -31021,7 +31368,7 @@ var PERF_STALL_THRESHOLD_MS = positiveIntEnv2("MIXDOG_TUI_PERF_STALL_MS", 80);
|
|
|
31021
31368
|
var PERF_RENDER_GAP_MS = positiveIntEnv2("MIXDOG_TUI_PERF_RENDER_GAP_MS", 120);
|
|
31022
31369
|
function perfLog(event, fields = {}) {
|
|
31023
31370
|
if (!PERF_ENABLED) return;
|
|
31024
|
-
const elapsedMs =
|
|
31371
|
+
const elapsedMs = performance4.now() - BOOT_PROFILE_START2;
|
|
31025
31372
|
const parts = [`[mixdog-perf] +${elapsedMs.toFixed(1)}ms`, event];
|
|
31026
31373
|
for (const [key, value] of Object.entries(fields || {})) {
|
|
31027
31374
|
if (value === void 0 || value === null || value === "") continue;
|
|
@@ -31036,7 +31383,7 @@ function perfLog(event, fields = {}) {
|
|
|
31036
31383
|
function installTuiPerfProbe() {
|
|
31037
31384
|
if (!PERF_ENABLED) return () => {
|
|
31038
31385
|
};
|
|
31039
|
-
let last =
|
|
31386
|
+
let last = performance4.now();
|
|
31040
31387
|
let lastCpu = process.cpuUsage();
|
|
31041
31388
|
perfLog("probe:start", {
|
|
31042
31389
|
intervalMs: PERF_STALL_INTERVAL_MS,
|
|
@@ -31044,7 +31391,7 @@ function installTuiPerfProbe() {
|
|
|
31044
31391
|
renderGapMs: PERF_RENDER_GAP_MS
|
|
31045
31392
|
});
|
|
31046
31393
|
const timer2 = setInterval(() => {
|
|
31047
|
-
const now =
|
|
31394
|
+
const now = performance4.now();
|
|
31048
31395
|
const elapsed = now - last;
|
|
31049
31396
|
const lagMs = elapsed - PERF_STALL_INTERVAL_MS;
|
|
31050
31397
|
const cpu = process.cpuUsage(lastCpu);
|
|
@@ -31082,7 +31429,7 @@ function makeRenderProfiler() {
|
|
|
31082
31429
|
let lastFrameAt = 0;
|
|
31083
31430
|
return ({ renderTime } = {}) => {
|
|
31084
31431
|
ackRenderedFrame();
|
|
31085
|
-
const now =
|
|
31432
|
+
const now = performance4.now();
|
|
31086
31433
|
const ms = Number(renderTime) || 0;
|
|
31087
31434
|
const gap = lastFrameAt ? now - lastFrameAt : 0;
|
|
31088
31435
|
lastFrameAt = now;
|
|
@@ -31116,7 +31463,7 @@ function makeRenderProfiler() {
|
|
|
31116
31463
|
}
|
|
31117
31464
|
function bootProfile2(event, fields = {}) {
|
|
31118
31465
|
if (!BOOT_PROFILE_ENABLED2) return;
|
|
31119
|
-
const elapsedMs =
|
|
31466
|
+
const elapsedMs = performance4.now() - BOOT_PROFILE_START2;
|
|
31120
31467
|
const parts = [`[mixdog-boot] +${elapsedMs.toFixed(1)}ms`, `tui:${event}`];
|
|
31121
31468
|
for (const [key, value] of Object.entries(fields || {})) {
|
|
31122
31469
|
if (value === void 0 || value === null || value === "") continue;
|
|
@@ -31334,7 +31681,7 @@ function installTuiConsoleGuard() {
|
|
|
31334
31681
|
};
|
|
31335
31682
|
}
|
|
31336
31683
|
async function runTui({ provider, model, toolMode, remote, forceOnboarding } = {}) {
|
|
31337
|
-
const startedAt =
|
|
31684
|
+
const startedAt = performance4.now();
|
|
31338
31685
|
bootProfile2("run:start", { provider, model, toolMode, remote });
|
|
31339
31686
|
if (!process.stdin.isTTY) {
|
|
31340
31687
|
process.stderr.write(
|
|
@@ -31365,6 +31712,7 @@ async function runTui({ provider, model, toolMode, remote, forceOnboarding } = {
|
|
|
31365
31712
|
process.stdout.write(`${TERMINAL_MODE_RESET_HIDDEN_CURSOR}\x1B[?1049h${TERMINAL_MODE_RESET_HIDDEN_CURSOR}\x1B[2J\x1B[H`);
|
|
31366
31713
|
process.stdout.write("\x1B[5 q");
|
|
31367
31714
|
process.on("exit", restoreTerminal);
|
|
31715
|
+
const storeOutcomePromise = createEngineSession({ provider, model, toolMode, remote }).then((store2) => ({ store: store2, error: null }), (error) => ({ store: null, error }));
|
|
31368
31716
|
try {
|
|
31369
31717
|
await loadThemeSettingFromConfig();
|
|
31370
31718
|
} catch {
|
|
@@ -31374,8 +31722,10 @@ async function runTui({ provider, model, toolMode, remote, forceOnboarding } = {
|
|
|
31374
31722
|
} };
|
|
31375
31723
|
let store;
|
|
31376
31724
|
try {
|
|
31377
|
-
|
|
31378
|
-
|
|
31725
|
+
const outcome = await storeOutcomePromise;
|
|
31726
|
+
if (outcome.error) throw outcome.error;
|
|
31727
|
+
store = outcome.store;
|
|
31728
|
+
bootProfile2("store:ready", { ms: (performance4.now() - startedAt).toFixed(1) });
|
|
31379
31729
|
} catch (error) {
|
|
31380
31730
|
splash.stop();
|
|
31381
31731
|
stopPerfProbe();
|
|
@@ -31440,8 +31790,8 @@ async function runTui({ provider, model, toolMode, remote, forceOnboarding } = {
|
|
|
31440
31790
|
registerStdioDeath(process.stderr, "error", { requireCode: true });
|
|
31441
31791
|
registerStdioDeath(process.stderr, "close");
|
|
31442
31792
|
try {
|
|
31443
|
-
const instance = render(/* @__PURE__ */ jsx21(App, { store, forceOnboarding: forceOnboarding === true }), { exitOnCtrlC: false, maxFps:
|
|
31444
|
-
bootProfile2("render:mounted", { ms: (
|
|
31793
|
+
const instance = render(/* @__PURE__ */ jsx21(App, { store, forceOnboarding: forceOnboarding === true }), { exitOnCtrlC: false, maxFps: TUI_RENDER_FPS, incrementalRendering: true, patchConsole: false, onRender: makeRenderProfiler() });
|
|
31794
|
+
bootProfile2("render:mounted", { ms: (performance4.now() - startedAt).toFixed(1) });
|
|
31445
31795
|
const { waitUntilExit } = instance;
|
|
31446
31796
|
if (mouseTracking && typeof instance.setSelection === "function") {
|
|
31447
31797
|
store.setRenderSelection = instance.setSelection;
|