@wrongstack/tui 0.296.3 → 0.297.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/app-action-type.d.ts +2 -0
- package/dist/app-action-type.d.ts.map +1 -1
- package/dist/app-initial-state.d.ts.map +1 -1
- package/dist/app-settings-type.d.ts +4 -0
- package/dist/app-settings-type.d.ts.map +1 -1
- package/dist/app-state.d.ts +4 -0
- package/dist/app-state.d.ts.map +1 -1
- package/dist/app-view.d.ts.map +1 -1
- package/dist/components/history/entry.d.ts +7 -1
- package/dist/components/history/entry.d.ts.map +1 -1
- package/dist/components/history/index.d.ts +1 -1
- package/dist/components/history/index.d.ts.map +1 -1
- package/dist/components/history/replay.d.ts.map +1 -1
- package/dist/components/history/tool-group.d.ts +1 -1
- package/dist/components/history/tool-group.d.ts.map +1 -1
- package/dist/components/history/types.d.ts +6 -0
- package/dist/components/history/types.d.ts.map +1 -1
- package/dist/components/scrollable-history.d.ts +1 -1
- package/dist/components/scrollable-history.d.ts.map +1 -1
- package/dist/components/settings-picker-jumps.d.ts.map +1 -1
- package/dist/components/settings-picker-model.d.ts +7 -1
- package/dist/components/settings-picker-model.d.ts.map +1 -1
- package/dist/components/settings-picker.d.ts +5 -1
- package/dist/components/settings-picker.d.ts.map +1 -1
- package/dist/components/status-bar.d.ts.map +1 -1
- package/dist/connections-health.d.ts.map +1 -1
- package/dist/heap-watchdog.d.ts +6 -42
- package/dist/heap-watchdog.d.ts.map +1 -1
- package/dist/history-archive.d.ts +0 -1
- package/dist/history-archive.d.ts.map +1 -1
- package/dist/history-entry.d.ts +9 -0
- package/dist/history-entry.d.ts.map +1 -1
- package/dist/hooks/use-panel-controllers.d.ts.map +1 -1
- package/dist/hooks/use-provider-event-bridge.d.ts.map +1 -1
- package/dist/hooks/use-settings-auto-save.d.ts.map +1 -1
- package/dist/hooks/use-tui-activity.d.ts.map +1 -1
- package/dist/index.js +354 -262
- package/dist/index.js.map +4 -4
- package/dist/overlay-key-router.d.ts.map +1 -1
- package/dist/reducers/settings-panel.d.ts.map +1 -1
- package/dist/reducers/settings-values.d.ts.map +1 -1
- package/dist/rehydrate-history.d.ts.map +1 -1
- package/dist/run-blocks-controller.d.ts.map +1 -1
- package/dist/settings-contracts.d.ts +4 -0
- package/dist/settings-contracts.d.ts.map +1 -1
- package/dist/tui-memory-counters.d.ts +38 -0
- package/dist/tui-memory-counters.d.ts.map +1 -0
- package/package.json +7 -7
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// src/app.tsx
|
|
2
|
-
import * as
|
|
2
|
+
import * as path7 from "node:path";
|
|
3
3
|
import {
|
|
4
4
|
applyRewindToConversation,
|
|
5
5
|
DefaultSessionRewinder
|
|
@@ -1565,7 +1565,7 @@ function StatusBar({
|
|
|
1565
1565
|
const liveActive = memoryMonitor ? activeMemoryContextCount(memoryMonitor) : 0;
|
|
1566
1566
|
const reportedActive = memoryMonitor ? liveActive : Sage?.activeInContext ?? 0;
|
|
1567
1567
|
memoryDetailChips.push(
|
|
1568
|
-
/* @__PURE__ */ jsx5(Text, { color: chipColor(theme.accent, isNoColor), children: isNoColor ? "Memory " : `${STATUSLINE_ICONS.memory_context} ` }, "mem-label")
|
|
1568
|
+
/* @__PURE__ */ jsx5(Text, { color: chipColor(theme.accent, isNoColor), children: isNoColor ? "Memory " : `${STATUSLINE_ICONS.memory_context} Memory ` }, "mem-label")
|
|
1569
1569
|
);
|
|
1570
1570
|
if (Sage) {
|
|
1571
1571
|
memoryDetailChips.push(
|
|
@@ -1808,7 +1808,15 @@ function StatusBar({
|
|
|
1808
1808
|
const detailChips = [];
|
|
1809
1809
|
if (mailbox && showMailbox) {
|
|
1810
1810
|
detailChips.push(
|
|
1811
|
-
mailbox.unread > 0 ? /* @__PURE__ */
|
|
1811
|
+
mailbox.unread > 0 ? /* @__PURE__ */ jsxs4(Text, { color: isNoColor ? void 0 : theme.warn, bold: true, children: [
|
|
1812
|
+
STATUSLINE_ICONS.mailbox,
|
|
1813
|
+
" ",
|
|
1814
|
+
mailbox.unread,
|
|
1815
|
+
" new"
|
|
1816
|
+
] }) : /* @__PURE__ */ jsxs4(Text, { dimColor: !isNoColor, children: [
|
|
1817
|
+
STATUSLINE_ICONS.mailbox,
|
|
1818
|
+
" 0"
|
|
1819
|
+
] }),
|
|
1812
1820
|
/* @__PURE__ */ jsxs4(Text, { color: isNoColor ? void 0 : theme.accent, children: [
|
|
1813
1821
|
glyphs.peers,
|
|
1814
1822
|
" ",
|
|
@@ -3582,7 +3590,9 @@ var SETTINGS_PICKER_JUMP_CHORDS = Object.freeze([
|
|
|
3582
3590
|
{ mod: "alt-shift", letter: "g", field: 35, label: "Config scope" },
|
|
3583
3591
|
{ mod: "alt", letter: "n", field: 36, label: "Animation" },
|
|
3584
3592
|
{ mod: "alt", letter: "p", field: 40, label: "Show agent swarm panel" },
|
|
3585
|
-
{ mod: "alt", letter: "r", field: 41, label: "Pre-refine countdown" }
|
|
3593
|
+
{ mod: "alt", letter: "r", field: 41, label: "Pre-refine countdown" },
|
|
3594
|
+
{ mod: "alt-shift", letter: "s", field: 43, label: "Show SAGE Memory Inject" },
|
|
3595
|
+
{ mod: "alt-shift", letter: "t", field: 44, label: "SAGE Memory Inject threshold" }
|
|
3586
3596
|
]);
|
|
3587
3597
|
function settingsPickerJumpField(mod, letter) {
|
|
3588
3598
|
const lower = letter.toLowerCase();
|
|
@@ -3708,7 +3718,7 @@ var MODE_DESC = {
|
|
|
3708
3718
|
suggest: "Shows next-step suggestions after each turn",
|
|
3709
3719
|
auto: "Self-driving \u2014 agent continues automatically"
|
|
3710
3720
|
};
|
|
3711
|
-
var SETTINGS_FIELD_COUNT =
|
|
3721
|
+
var SETTINGS_FIELD_COUNT = 45;
|
|
3712
3722
|
var THINKING_WORD_FIELD = 22;
|
|
3713
3723
|
var THINKING_WORD_PRESETS = [
|
|
3714
3724
|
"thinking",
|
|
@@ -3811,8 +3821,12 @@ var SETTINGS_FIELD_LABELS = [
|
|
|
3811
3821
|
// 40
|
|
3812
3822
|
"Pre-refine countdown",
|
|
3813
3823
|
// 41
|
|
3814
|
-
"Read symbols"
|
|
3824
|
+
"Read symbols",
|
|
3815
3825
|
// 42
|
|
3826
|
+
"Show SAGE Memory Inject",
|
|
3827
|
+
// 43
|
|
3828
|
+
"SAGE Memory Inject threshold"
|
|
3829
|
+
// 44
|
|
3816
3830
|
];
|
|
3817
3831
|
function resolveSettingsFieldValue(field, input) {
|
|
3818
3832
|
const raw = input.trim().toLowerCase();
|
|
@@ -3837,7 +3851,8 @@ function resolveSettingsFieldValue(field, input) {
|
|
|
3837
3851
|
[37, "breakerEnabled"],
|
|
3838
3852
|
[39, "showModelReasoning"],
|
|
3839
3853
|
[40, "showAgentSwarmPanel"],
|
|
3840
|
-
[42, "readSymbols"]
|
|
3854
|
+
[42, "readSymbols"],
|
|
3855
|
+
[43, "showSageMemoryInject"]
|
|
3841
3856
|
]);
|
|
3842
3857
|
const boolKey = BOOL_FIELDS.get(field);
|
|
3843
3858
|
if (boolKey) {
|
|
@@ -3906,6 +3921,26 @@ function resolveSettingsFieldValue(field, input) {
|
|
|
3906
3921
|
error: `Invalid value "${input}" for ${label}. Valid: ${values.join(", ")}.`
|
|
3907
3922
|
};
|
|
3908
3923
|
}
|
|
3924
|
+
if (field === 44) {
|
|
3925
|
+
const presets = SAGE_THRESHOLD_PRESETS;
|
|
3926
|
+
const rawMatch = raw.match(/^(\d+(?:\.\d+)?)$/);
|
|
3927
|
+
if (rawMatch) {
|
|
3928
|
+
const asFloat = Number.parseFloat(rawMatch[1]);
|
|
3929
|
+
if (presets.includes(asFloat)) {
|
|
3930
|
+
return {
|
|
3931
|
+
ok: true,
|
|
3932
|
+
patch: { sageMemoryInjectThreshold: asFloat },
|
|
3933
|
+
label,
|
|
3934
|
+
displayValue: formatSageThreshold(asFloat)
|
|
3935
|
+
};
|
|
3936
|
+
}
|
|
3937
|
+
}
|
|
3938
|
+
const options = presets.map((p) => formatSageThreshold(p)).join(", ");
|
|
3939
|
+
return {
|
|
3940
|
+
ok: false,
|
|
3941
|
+
error: `Invalid value "${input}" for ${label}. Available: ${options}.`
|
|
3942
|
+
};
|
|
3943
|
+
}
|
|
3909
3944
|
const presetLabel = (n, zeroLabel) => n === 0 ? zeroLabel : String(n);
|
|
3910
3945
|
const PRESET_FIELDS = [
|
|
3911
3946
|
[1, "delayMs", DELAY_PRESETS_MS, (n) => formatSettingsDelay(n)],
|
|
@@ -3988,7 +4023,8 @@ function getSettingsFieldValue(values, field) {
|
|
|
3988
4023
|
[37, "breakerEnabled"],
|
|
3989
4024
|
[39, "showModelReasoning"],
|
|
3990
4025
|
[40, "showAgentSwarmPanel"],
|
|
3991
|
-
[42, "readSymbols"]
|
|
4026
|
+
[42, "readSymbols"],
|
|
4027
|
+
[43, "showSageMemoryInject"]
|
|
3992
4028
|
];
|
|
3993
4029
|
for (const [f, key] of BOOL_KEYS) {
|
|
3994
4030
|
if (field !== f) continue;
|
|
@@ -4023,7 +4059,8 @@ function getSettingsFieldValue(values, field) {
|
|
|
4023
4059
|
[41, "preRefineSeconds", formatPreRefineSeconds],
|
|
4024
4060
|
[21, "multiDiffSummaryThreshold", formatMultiDiffSummaryThreshold],
|
|
4025
4061
|
[30, "maxConcurrent", (n) => presetLabel(n, "runtime default")],
|
|
4026
|
-
[38, "breakerAutoKillResetMs", formatBreakerTimeout]
|
|
4062
|
+
[38, "breakerAutoKillResetMs", formatBreakerTimeout],
|
|
4063
|
+
[44, "sageMemoryInjectThreshold", formatSageThreshold]
|
|
4027
4064
|
];
|
|
4028
4065
|
for (const [f, key, fmt2] of PRESET_KEYS) {
|
|
4029
4066
|
if (field !== f) continue;
|
|
@@ -4077,7 +4114,7 @@ var SETTINGS_SECTIONS = [
|
|
|
4077
4114
|
},
|
|
4078
4115
|
{
|
|
4079
4116
|
name: "Display",
|
|
4080
|
-
fields: [39, 40, 41]
|
|
4117
|
+
fields: [39, 40, 41, 43, 44]
|
|
4081
4118
|
}
|
|
4082
4119
|
];
|
|
4083
4120
|
function formatAllSettingsSummary(values) {
|
|
@@ -4093,6 +4130,10 @@ function formatAllSettingsSummary(values) {
|
|
|
4093
4130
|
}
|
|
4094
4131
|
return lines.join("\n");
|
|
4095
4132
|
}
|
|
4133
|
+
var SAGE_THRESHOLD_PRESETS = [0.72, 0.75, 0.85, 0.9, 0.95];
|
|
4134
|
+
function formatSageThreshold(t) {
|
|
4135
|
+
return t.toFixed(2);
|
|
4136
|
+
}
|
|
4096
4137
|
var SETTINGS_DEFAULTS = Object.freeze({
|
|
4097
4138
|
// Factory defaults mirror the core config defaults: autonomy 'auto'
|
|
4098
4139
|
// (self-driving) and yolo on (auto-approve). Live values still come from
|
|
@@ -4139,7 +4180,9 @@ var SETTINGS_DEFAULTS = Object.freeze({
|
|
|
4139
4180
|
breakerAutoKillResetMs: 6e4,
|
|
4140
4181
|
showModelReasoning: true,
|
|
4141
4182
|
showAgentSwarmPanel: true,
|
|
4142
|
-
readSymbols: false
|
|
4183
|
+
readSymbols: false,
|
|
4184
|
+
showSageMemoryInject: false,
|
|
4185
|
+
sageMemoryInjectThreshold: 0.85
|
|
4143
4186
|
});
|
|
4144
4187
|
function resetSettingsFieldValue(field) {
|
|
4145
4188
|
const result = getSettingsFieldValue(SETTINGS_DEFAULTS, field);
|
|
@@ -4192,7 +4235,9 @@ function buildResetPatch(field) {
|
|
|
4192
4235
|
[39, "showModelReasoning"],
|
|
4193
4236
|
[40, "showAgentSwarmPanel"],
|
|
4194
4237
|
[41, "preRefineSeconds"],
|
|
4195
|
-
[42, "readSymbols"]
|
|
4238
|
+
[42, "readSymbols"],
|
|
4239
|
+
[43, "showSageMemoryInject"],
|
|
4240
|
+
[44, "sageMemoryInjectThreshold"]
|
|
4196
4241
|
];
|
|
4197
4242
|
for (const [f, key] of KEY_MAP) {
|
|
4198
4243
|
if (f === field) {
|
|
@@ -4323,6 +4368,8 @@ function SettingsPicker({
|
|
|
4323
4368
|
breakerAutoKillResetMs,
|
|
4324
4369
|
showModelReasoning,
|
|
4325
4370
|
showAgentSwarmPanel,
|
|
4371
|
+
showSageMemoryInject,
|
|
4372
|
+
sageMemoryInjectThreshold,
|
|
4326
4373
|
readSymbols,
|
|
4327
4374
|
hint
|
|
4328
4375
|
}) {
|
|
@@ -4562,6 +4609,16 @@ function SettingsPicker({
|
|
|
4562
4609
|
label: "Read symbols",
|
|
4563
4610
|
value: boolVal(readSymbols),
|
|
4564
4611
|
detail: "Include codebase-index symbols in read tool results"
|
|
4612
|
+
},
|
|
4613
|
+
{
|
|
4614
|
+
label: "Show SAGE Memory Inject",
|
|
4615
|
+
value: boolVal(showSageMemoryInject),
|
|
4616
|
+
detail: "Show SAGE memory injection blocks in tool results"
|
|
4617
|
+
},
|
|
4618
|
+
{
|
|
4619
|
+
label: "SAGE Memory Inject threshold",
|
|
4620
|
+
value: formatSageThreshold(sageMemoryInjectThreshold),
|
|
4621
|
+
detail: "Min relation strength for injection (0.72\u20130.95)"
|
|
4565
4622
|
}
|
|
4566
4623
|
];
|
|
4567
4624
|
const fieldRowIndex = [];
|
|
@@ -10427,6 +10484,7 @@ function retainCheckpoints(checkpoints, budget = {}) {
|
|
|
10427
10484
|
|
|
10428
10485
|
// src/components/history/replay.ts
|
|
10429
10486
|
import { SESSION_MARKER_EVENT_TYPES, sessionEventToMarker } from "@wrongstack/core/types";
|
|
10487
|
+
import { isFinalTurnStopReason } from "@wrongstack/tools/next-steps";
|
|
10430
10488
|
var MARKER_EVENT_TYPES = SESSION_MARKER_EVENT_TYPES;
|
|
10431
10489
|
var SUBAGENT_MARKER_STYLE = {
|
|
10432
10490
|
agent_spawned: { color: "magenta", icon: "\u26A1" },
|
|
@@ -10464,18 +10522,18 @@ function replaySessionMessages(messages, events, startId) {
|
|
|
10464
10522
|
backbone.push({ ts, entry });
|
|
10465
10523
|
return entry;
|
|
10466
10524
|
};
|
|
10467
|
-
const appendText = (role, text, ts) => {
|
|
10525
|
+
const appendText = (role, text, ts, final) => {
|
|
10468
10526
|
if (!text.trim()) return;
|
|
10469
10527
|
push(
|
|
10470
10528
|
ts,
|
|
10471
|
-
role === "assistant" ? { kind: "assistant", text } : role === "system" ? { kind: "info", text } : { kind: "user", text }
|
|
10529
|
+
role === "assistant" ? { kind: "assistant", text, final } : role === "system" ? { kind: "info", text } : { kind: "user", text }
|
|
10472
10530
|
);
|
|
10473
10531
|
};
|
|
10474
10532
|
for (const message of messages) {
|
|
10475
10533
|
const ts = message.ts ?? lastTs;
|
|
10476
10534
|
if (message.ts) lastTs = message.ts;
|
|
10477
10535
|
if (typeof message.content === "string") {
|
|
10478
|
-
appendText(message.role, message.content, ts);
|
|
10536
|
+
appendText(message.role, message.content, ts, true);
|
|
10479
10537
|
continue;
|
|
10480
10538
|
}
|
|
10481
10539
|
for (const block of message.content) {
|
|
@@ -10486,7 +10544,8 @@ function replaySessionMessages(messages, events, startId) {
|
|
|
10486
10544
|
appendText(
|
|
10487
10545
|
message.role,
|
|
10488
10546
|
message.content.filter((block) => block.type === "text").map((block) => block.text).join(""),
|
|
10489
|
-
ts
|
|
10547
|
+
ts,
|
|
10548
|
+
!message.content.some((block) => block.type === "tool_use")
|
|
10490
10549
|
);
|
|
10491
10550
|
for (const block of message.content) {
|
|
10492
10551
|
if (block.type === "tool_use") {
|
|
@@ -10567,7 +10626,7 @@ function eventToEntry(ev, pendingTools, completedTools) {
|
|
|
10567
10626
|
}
|
|
10568
10627
|
const text = ev.content.filter((b) => b.type === "text").map((b) => b.text).join("");
|
|
10569
10628
|
if (!text.trim()) return null;
|
|
10570
|
-
return { kind: "assistant", text };
|
|
10629
|
+
return { kind: "assistant", text, final: isFinalTurnStopReason(ev.stopReason) };
|
|
10571
10630
|
}
|
|
10572
10631
|
case "tool_use": {
|
|
10573
10632
|
pendingTools.set(ev.id, { name: ev.name, input: ev.input, ts: ev.ts });
|
|
@@ -10824,9 +10883,9 @@ function rehydrateHistory(messages, startId, toolCalls) {
|
|
|
10824
10883
|
outputTokens: tc.outputTokens,
|
|
10825
10884
|
outputLines: tc.outputLines
|
|
10826
10885
|
});
|
|
10827
|
-
const pushAssistantText = (parts) => {
|
|
10886
|
+
const pushAssistantText = (parts, final) => {
|
|
10828
10887
|
const text = parts.join("").trim();
|
|
10829
|
-
if (text) entries.push({ id: nextId++, kind: "assistant", text });
|
|
10888
|
+
if (text) entries.push({ id: nextId++, kind: "assistant", text, final });
|
|
10830
10889
|
parts.length = 0;
|
|
10831
10890
|
};
|
|
10832
10891
|
for (const msg of messages) {
|
|
@@ -10839,23 +10898,25 @@ function rehydrateHistory(messages, startId, toolCalls) {
|
|
|
10839
10898
|
if (msg.role === "assistant") {
|
|
10840
10899
|
if (!Array.isArray(msg.content)) {
|
|
10841
10900
|
const text = textOf(msg).trim();
|
|
10842
|
-
if (text) entries.push({ id: nextId++, kind: "assistant", text });
|
|
10901
|
+
if (text) entries.push({ id: nextId++, kind: "assistant", text, final: true });
|
|
10843
10902
|
continue;
|
|
10844
10903
|
}
|
|
10904
|
+
const blocks = msg.content;
|
|
10905
|
+
const final = !blocks.some((block) => block.type === "tool_use");
|
|
10845
10906
|
const textParts = [];
|
|
10846
|
-
for (const block of
|
|
10907
|
+
for (const block of blocks) {
|
|
10847
10908
|
if (block.type === "text") {
|
|
10848
10909
|
textParts.push(block.text);
|
|
10849
10910
|
continue;
|
|
10850
10911
|
}
|
|
10851
10912
|
if (block.type !== "tool_use") continue;
|
|
10852
|
-
pushAssistantText(textParts);
|
|
10913
|
+
pushAssistantText(textParts, final);
|
|
10853
10914
|
const tc = toolCallsById.get(block.id);
|
|
10854
10915
|
if (!tc) continue;
|
|
10855
10916
|
entries.push(toolEntryFor(tc));
|
|
10856
10917
|
consumed.add(block.id);
|
|
10857
10918
|
}
|
|
10858
|
-
pushAssistantText(textParts);
|
|
10919
|
+
pushAssistantText(textParts, final);
|
|
10859
10920
|
}
|
|
10860
10921
|
}
|
|
10861
10922
|
if (toolCalls) {
|
|
@@ -11049,6 +11110,8 @@ function createInitialState(options) {
|
|
|
11049
11110
|
breakerAutoKillResetMs: 6e4,
|
|
11050
11111
|
showModelReasoning: true,
|
|
11051
11112
|
showAgentSwarmPanel: true,
|
|
11113
|
+
showSageMemoryInject: false,
|
|
11114
|
+
sageMemoryInjectThreshold: 0.85,
|
|
11052
11115
|
readSymbols: false
|
|
11053
11116
|
},
|
|
11054
11117
|
statuslinePicker: {
|
|
@@ -13343,6 +13406,8 @@ function reduceSettingsPanel(state, action) {
|
|
|
13343
13406
|
breakerAutoKillResetMs: action.breakerAutoKillResetMs,
|
|
13344
13407
|
showModelReasoning: action.showModelReasoning,
|
|
13345
13408
|
showAgentSwarmPanel: action.showAgentSwarmPanel,
|
|
13409
|
+
showSageMemoryInject: action.showSageMemoryInject,
|
|
13410
|
+
sageMemoryInjectThreshold: action.sageMemoryInjectThreshold,
|
|
13346
13411
|
readSymbols: action.readSymbols,
|
|
13347
13412
|
hint: void 0
|
|
13348
13413
|
}
|
|
@@ -13791,6 +13856,24 @@ function reduceSettingsValues(state, action) {
|
|
|
13791
13856
|
...state,
|
|
13792
13857
|
settingsPicker: { ...sp, readSymbols: !sp.readSymbols, hint: void 0 }
|
|
13793
13858
|
};
|
|
13859
|
+
if (f === 43)
|
|
13860
|
+
return {
|
|
13861
|
+
...state,
|
|
13862
|
+
settingsPicker: { ...sp, showSageMemoryInject: !sp.showSageMemoryInject, hint: void 0 }
|
|
13863
|
+
};
|
|
13864
|
+
if (f === 44) {
|
|
13865
|
+
const j = SAGE_THRESHOLD_PRESETS.indexOf(sp.sageMemoryInjectThreshold);
|
|
13866
|
+
const base = j < 0 ? 0 : j;
|
|
13867
|
+
const next = (base + action.delta + SAGE_THRESHOLD_PRESETS.length) % SAGE_THRESHOLD_PRESETS.length;
|
|
13868
|
+
return {
|
|
13869
|
+
...state,
|
|
13870
|
+
settingsPicker: {
|
|
13871
|
+
...sp,
|
|
13872
|
+
sageMemoryInjectThreshold: expectDefined2(SAGE_THRESHOLD_PRESETS[next]),
|
|
13873
|
+
hint: void 0
|
|
13874
|
+
}
|
|
13875
|
+
};
|
|
13876
|
+
}
|
|
13794
13877
|
return state;
|
|
13795
13878
|
}
|
|
13796
13879
|
case "settingsValueSet": {
|
|
@@ -15856,6 +15939,8 @@ function usePanelControllers({
|
|
|
15856
15939
|
breakerAutoKillResetMs: s2.breakerAutoKillResetMs ?? 6e4,
|
|
15857
15940
|
showModelReasoning: s2.showModelReasoning ?? true,
|
|
15858
15941
|
showAgentSwarmPanel: s2.showAgentSwarmPanel ?? true,
|
|
15942
|
+
showSageMemoryInject: s2.showSageMemoryInject ?? false,
|
|
15943
|
+
sageMemoryInjectThreshold: s2.sageMemoryInjectThreshold ?? 0.85,
|
|
15859
15944
|
readSymbols: s2.readSymbols ?? false
|
|
15860
15945
|
});
|
|
15861
15946
|
}, [getSettings]);
|
|
@@ -16318,6 +16403,7 @@ function usePromptPicker({
|
|
|
16318
16403
|
|
|
16319
16404
|
// src/hooks/use-provider-event-bridge.ts
|
|
16320
16405
|
import { tuiStreamFlushMs } from "@wrongstack/core/utils";
|
|
16406
|
+
import { isFinalTurnStopReason as isFinalTurnStopReason2 } from "@wrongstack/tools/next-steps";
|
|
16321
16407
|
import {
|
|
16322
16408
|
DEFAULT_MIN_IMPORTANCE,
|
|
16323
16409
|
DEFAULT_MIN_SCORE,
|
|
@@ -16433,6 +16519,65 @@ function shortId(node) {
|
|
|
16433
16519
|
return value.length > 22 ? `${value.slice(0, 19)}\u2026` : value;
|
|
16434
16520
|
}
|
|
16435
16521
|
|
|
16522
|
+
// src/tui-memory-counters.ts
|
|
16523
|
+
var counters = {
|
|
16524
|
+
appRenders: 0,
|
|
16525
|
+
providerTextDeltaEvents: 0,
|
|
16526
|
+
providerTextDeltaChars: 0,
|
|
16527
|
+
providerThinkingDeltaEvents: 0,
|
|
16528
|
+
providerThinkingDeltaChars: 0,
|
|
16529
|
+
providerResponses: 0,
|
|
16530
|
+
toolProgressEvents: 0,
|
|
16531
|
+
toolProgressChars: 0,
|
|
16532
|
+
toolExecutedEvents: 0,
|
|
16533
|
+
toolOutputBytes: 0,
|
|
16534
|
+
streamFlushes: 0,
|
|
16535
|
+
historyRetainedEntries: 0,
|
|
16536
|
+
historyGroupedEntries: 0,
|
|
16537
|
+
historyMountedGroups: 0,
|
|
16538
|
+
historyMountedEntries: 0,
|
|
16539
|
+
historyCachedGroups: 0,
|
|
16540
|
+
historyMeasuredGroups: 0,
|
|
16541
|
+
historyViewportRows: 0,
|
|
16542
|
+
historyTotalRows: 0
|
|
16543
|
+
};
|
|
16544
|
+
function add(key, amount = 1) {
|
|
16545
|
+
counters[key] += Number.isFinite(amount) ? Math.max(0, amount) : 0;
|
|
16546
|
+
}
|
|
16547
|
+
function recordTuiAppRender() {
|
|
16548
|
+
add("appRenders");
|
|
16549
|
+
}
|
|
16550
|
+
function recordProviderTextDelta(chars) {
|
|
16551
|
+
add("providerTextDeltaEvents");
|
|
16552
|
+
add("providerTextDeltaChars", chars);
|
|
16553
|
+
}
|
|
16554
|
+
function recordProviderThinkingDelta(chars) {
|
|
16555
|
+
add("providerThinkingDeltaEvents");
|
|
16556
|
+
add("providerThinkingDeltaChars", chars);
|
|
16557
|
+
}
|
|
16558
|
+
function recordProviderResponse() {
|
|
16559
|
+
add("providerResponses");
|
|
16560
|
+
}
|
|
16561
|
+
function recordToolProgress(chars) {
|
|
16562
|
+
add("toolProgressEvents");
|
|
16563
|
+
add("toolProgressChars", chars);
|
|
16564
|
+
}
|
|
16565
|
+
function recordToolExecuted(outputBytes) {
|
|
16566
|
+
add("toolExecutedEvents");
|
|
16567
|
+
add("toolOutputBytes", outputBytes ?? 0);
|
|
16568
|
+
}
|
|
16569
|
+
function recordStreamFlush() {
|
|
16570
|
+
add("streamFlushes");
|
|
16571
|
+
}
|
|
16572
|
+
function setTuiHistoryMemoryGauges(gauges) {
|
|
16573
|
+
for (const [key, value] of Object.entries(gauges)) {
|
|
16574
|
+
counters[key] = Number.isFinite(value) ? Math.max(0, value) : 0;
|
|
16575
|
+
}
|
|
16576
|
+
}
|
|
16577
|
+
function snapshotTuiMemoryCounters() {
|
|
16578
|
+
return { ...counters };
|
|
16579
|
+
}
|
|
16580
|
+
|
|
16436
16581
|
// src/hooks/subagent-history-format.ts
|
|
16437
16582
|
function formatHistoryDuration(ms) {
|
|
16438
16583
|
if (!Number.isFinite(ms) || ms < 0) return "0s";
|
|
@@ -16544,14 +16689,11 @@ function useProviderEventBridge({
|
|
|
16544
16689
|
}
|
|
16545
16690
|
};
|
|
16546
16691
|
const flush = () => {
|
|
16547
|
-
if (pendingDeltaRef.current) {
|
|
16548
|
-
dispatch({ type: "streamDelta", delta: pendingDeltaRef.current });
|
|
16549
|
-
pendingDeltaRef.current = "";
|
|
16550
|
-
}
|
|
16551
16692
|
if (pendingToolStream) {
|
|
16552
16693
|
dispatch({ type: "toolStreamAppend", ...pendingToolStream });
|
|
16553
16694
|
pendingToolStream = null;
|
|
16554
16695
|
}
|
|
16696
|
+
recordStreamFlush();
|
|
16555
16697
|
flushTimerRef.current = null;
|
|
16556
16698
|
};
|
|
16557
16699
|
const scheduleFlush = () => {
|
|
@@ -16560,29 +16702,19 @@ function useProviderEventBridge({
|
|
|
16560
16702
|
const offDelta = events.on("provider.text_delta", (e) => {
|
|
16561
16703
|
if (activeRunGenerationRef.current !== sessionGenerationRef.current) return;
|
|
16562
16704
|
const text = e.text.replace(/\x1b?\[200~|\x1b?\[201~/g, "");
|
|
16705
|
+
recordProviderTextDelta(text.length);
|
|
16563
16706
|
streamingTextRef.current = retainStreamTail(
|
|
16564
16707
|
streamingTextRef.current,
|
|
16565
16708
|
text,
|
|
16566
16709
|
MAX_ASSISTANT_STREAM_RETAINED_CHARS
|
|
16567
16710
|
);
|
|
16568
|
-
pendingDeltaRef.current = retainStreamTail(
|
|
16569
|
-
pendingDeltaRef.current,
|
|
16570
|
-
text,
|
|
16571
|
-
MAX_ASSISTANT_STREAM_RETAINED_CHARS
|
|
16572
|
-
);
|
|
16573
16711
|
appendStreamSegment("assistant", text);
|
|
16574
|
-
scheduleFlush();
|
|
16575
16712
|
});
|
|
16576
16713
|
const offThinking = events.on("provider.thinking_delta", (e) => {
|
|
16577
16714
|
if (activeRunGenerationRef.current !== sessionGenerationRef.current) return;
|
|
16578
16715
|
const text = e.text.replace(/\x1b?\[200~|\x1b?\[201~/g, "");
|
|
16716
|
+
recordProviderThinkingDelta(text.length);
|
|
16579
16717
|
appendStreamSegment("thinking", text);
|
|
16580
|
-
pendingDeltaRef.current = retainStreamTail(
|
|
16581
|
-
pendingDeltaRef.current,
|
|
16582
|
-
text,
|
|
16583
|
-
MAX_ASSISTANT_STREAM_RETAINED_CHARS
|
|
16584
|
-
);
|
|
16585
|
-
scheduleFlush();
|
|
16586
16718
|
});
|
|
16587
16719
|
const offToolStart = events.on("tool.started", (e) => {
|
|
16588
16720
|
dispatch({ type: "toolStarted", id: e.id, name: e.name });
|
|
@@ -16596,11 +16728,16 @@ function useProviderEventBridge({
|
|
|
16596
16728
|
});
|
|
16597
16729
|
const offToolProgress = events.on("tool.progress", (e) => {
|
|
16598
16730
|
if (e.event.type !== "partial_output" || !e.event.text) return;
|
|
16731
|
+
recordToolProgress(e.event.text.length);
|
|
16599
16732
|
const prev = pendingToolStream;
|
|
16600
16733
|
if (prev && prev.toolUseId === e.id) {
|
|
16601
16734
|
pendingToolStream = {
|
|
16602
16735
|
...prev,
|
|
16603
|
-
text:
|
|
16736
|
+
text: retainStreamTail(
|
|
16737
|
+
prev.text,
|
|
16738
|
+
e.event.text,
|
|
16739
|
+
MAX_TOOL_STREAM_RETAINED_CHARS
|
|
16740
|
+
),
|
|
16604
16741
|
startedAt: prev.startedAt
|
|
16605
16742
|
};
|
|
16606
16743
|
} else {
|
|
@@ -16615,6 +16752,7 @@ function useProviderEventBridge({
|
|
|
16615
16752
|
scheduleFlush();
|
|
16616
16753
|
});
|
|
16617
16754
|
const offTool = events.on("tool.executed", (e) => {
|
|
16755
|
+
recordToolExecuted(e.outputBytes);
|
|
16618
16756
|
if (pendingToolStream) {
|
|
16619
16757
|
dispatch({ type: "toolStreamAppend", ...pendingToolStream });
|
|
16620
16758
|
pendingToolStream = null;
|
|
@@ -16674,6 +16812,7 @@ function useProviderEventBridge({
|
|
|
16674
16812
|
});
|
|
16675
16813
|
const offProvResp = events.on("provider.response", (e) => {
|
|
16676
16814
|
if (activeRunGenerationRef.current !== sessionGenerationRef.current) return;
|
|
16815
|
+
recordProviderResponse();
|
|
16677
16816
|
const segments = canonicalStreamSegments(e.content ?? []);
|
|
16678
16817
|
const fallbackText = contentBlocksText(e.content);
|
|
16679
16818
|
streamingTextRef.current = "";
|
|
@@ -16684,14 +16823,18 @@ function useProviderEventBridge({
|
|
|
16684
16823
|
flushTimerRef.current = null;
|
|
16685
16824
|
}
|
|
16686
16825
|
dispatch({ type: "streamReset" });
|
|
16826
|
+
const final = isFinalTurnStopReason2(e.stopReason);
|
|
16687
16827
|
for (const seg of segments) {
|
|
16688
16828
|
if (seg.text.trim()) {
|
|
16689
|
-
dispatch({
|
|
16829
|
+
dispatch({
|
|
16830
|
+
type: "addEntry",
|
|
16831
|
+
entry: seg.kind === "assistant" ? { kind: "assistant", text: seg.text, final } : { kind: "thinking", text: seg.text }
|
|
16832
|
+
});
|
|
16690
16833
|
if (seg.kind === "assistant") assistantCommittedThisRunRef.current = true;
|
|
16691
16834
|
}
|
|
16692
16835
|
}
|
|
16693
16836
|
if (segments.length === 0 && fallbackText.trim()) {
|
|
16694
|
-
dispatch({ type: "addEntry", entry: { kind: "assistant", text: fallbackText } });
|
|
16837
|
+
dispatch({ type: "addEntry", entry: { kind: "assistant", text: fallbackText, final } });
|
|
16695
16838
|
assistantCommittedThisRunRef.current = true;
|
|
16696
16839
|
}
|
|
16697
16840
|
});
|
|
@@ -17266,6 +17409,8 @@ function useSettingsAutoSave(state, saveSettings, dispatch) {
|
|
|
17266
17409
|
breakerAutoKillResetMs: sp.breakerAutoKillResetMs,
|
|
17267
17410
|
showModelReasoning: sp.showModelReasoning,
|
|
17268
17411
|
showAgentSwarmPanel: sp.showAgentSwarmPanel,
|
|
17412
|
+
showSageMemoryInject: sp.showSageMemoryInject,
|
|
17413
|
+
sageMemoryInjectThreshold: sp.sageMemoryInjectThreshold,
|
|
17269
17414
|
readSymbols: sp.readSymbols
|
|
17270
17415
|
})
|
|
17271
17416
|
).then((err) => {
|
|
@@ -17315,6 +17460,8 @@ function useSettingsAutoSave(state, saveSettings, dispatch) {
|
|
|
17315
17460
|
state.settingsPicker.breakerAutoKillResetMs,
|
|
17316
17461
|
state.settingsPicker.showModelReasoning,
|
|
17317
17462
|
state.settingsPicker.showAgentSwarmPanel,
|
|
17463
|
+
state.settingsPicker.showSageMemoryInject,
|
|
17464
|
+
state.settingsPicker.sageMemoryInjectThreshold,
|
|
17318
17465
|
state.settingsPicker.readSymbols,
|
|
17319
17466
|
saveSettings
|
|
17320
17467
|
]);
|
|
@@ -17949,131 +18096,12 @@ import { useCallback as useCallback18, useEffect as useEffect39, useMemo as useM
|
|
|
17949
18096
|
import * as os from "node:os";
|
|
17950
18097
|
|
|
17951
18098
|
// src/heap-watchdog.ts
|
|
17952
|
-
import
|
|
17953
|
-
|
|
17954
|
-
|
|
17955
|
-
|
|
17956
|
-
|
|
17957
|
-
|
|
17958
|
-
return path5.join(wstackGlobalRoot(), "logs", "heap.jsonl");
|
|
17959
|
-
}
|
|
17960
|
-
function takeHeapSample() {
|
|
17961
|
-
const m = process.memoryUsage();
|
|
17962
|
-
const limit = v8.getHeapStatistics().heap_size_limit || 0;
|
|
17963
|
-
return {
|
|
17964
|
-
ts: (/* @__PURE__ */ new Date()).toISOString(),
|
|
17965
|
-
rss: m.rss,
|
|
17966
|
-
heapUsed: m.heapUsed,
|
|
17967
|
-
heapTotal: m.heapTotal,
|
|
17968
|
-
external: m.external,
|
|
17969
|
-
heapLimit: limit,
|
|
17970
|
-
load: limit > 0 ? m.heapUsed / limit : 0
|
|
17971
|
-
};
|
|
17972
|
-
}
|
|
17973
|
-
function startHeapWatchdog(opts = {}) {
|
|
17974
|
-
const sampleEveryMs = opts.sampleEveryMs ?? 6e4;
|
|
17975
|
-
const logEveryMs = opts.logEveryMs ?? 3e5;
|
|
17976
|
-
const logPath = opts.logPath ?? defaultHeapLogPath();
|
|
17977
|
-
const warnAt = opts.warnAt ?? 0.6;
|
|
17978
|
-
const criticalAt = opts.criticalAt ?? 0.85;
|
|
17979
|
-
const REARM_MARGIN = 0.05;
|
|
17980
|
-
let warnArmed = true;
|
|
17981
|
-
let criticalArmed = true;
|
|
17982
|
-
let lastLogAt = 0;
|
|
17983
|
-
let writeInFlight = false;
|
|
17984
|
-
let pendingLine;
|
|
17985
|
-
let drainPromise;
|
|
17986
|
-
let stopped = false;
|
|
17987
|
-
let dirReady = false;
|
|
17988
|
-
const writeDiagnosticLine = opts.writeDiagnosticLine ?? (async (targetPath, line) => {
|
|
17989
|
-
if (!dirReady) {
|
|
17990
|
-
await fsp.mkdir(path5.dirname(targetPath), { recursive: true });
|
|
17991
|
-
dirReady = true;
|
|
17992
|
-
}
|
|
17993
|
-
await fsp.appendFile(targetPath, `${line}
|
|
17994
|
-
`, "utf8");
|
|
17995
|
-
});
|
|
17996
|
-
const drainWrites = async (firstLine) => {
|
|
17997
|
-
let line = firstLine;
|
|
17998
|
-
while (line !== void 0) {
|
|
17999
|
-
try {
|
|
18000
|
-
await writeDiagnosticLine(logPath, line);
|
|
18001
|
-
} catch {
|
|
18002
|
-
}
|
|
18003
|
-
line = pendingLine;
|
|
18004
|
-
pendingLine = void 0;
|
|
18005
|
-
}
|
|
18006
|
-
writeInFlight = false;
|
|
18007
|
-
};
|
|
18008
|
-
const append = (line) => {
|
|
18009
|
-
if (stopped) return;
|
|
18010
|
-
if (writeInFlight) {
|
|
18011
|
-
pendingLine = line;
|
|
18012
|
-
return;
|
|
18013
|
-
}
|
|
18014
|
-
writeInFlight = true;
|
|
18015
|
-
drainPromise = drainWrites(line);
|
|
18016
|
-
};
|
|
18017
|
-
const tick = () => {
|
|
18018
|
-
let userTimings = 0;
|
|
18019
|
-
try {
|
|
18020
|
-
userTimings = performance.getEntriesByType("mark").length + performance.getEntriesByType("measure").length;
|
|
18021
|
-
if (userTimings > 0) {
|
|
18022
|
-
performance.clearMarks();
|
|
18023
|
-
performance.clearMeasures();
|
|
18024
|
-
}
|
|
18025
|
-
} catch {
|
|
18026
|
-
}
|
|
18027
|
-
const s2 = takeHeapSample();
|
|
18028
|
-
if (s2.load >= criticalAt && criticalArmed) {
|
|
18029
|
-
criticalArmed = false;
|
|
18030
|
-
warnArmed = false;
|
|
18031
|
-
opts.onWarn?.(
|
|
18032
|
-
"critical",
|
|
18033
|
-
`Heap critical: ${Math.round(s2.heapUsed / MB)} MB of ~${Math.round(s2.heapLimit / MB)} MB V8 limit (${Math.round(s2.load * 100)}%). An out-of-memory crash is likely soon \u2014 finish/checkpoint work and restart the session. Diagnostics: ${logPath}`,
|
|
18034
|
-
s2
|
|
18035
|
-
);
|
|
18036
|
-
} else if (s2.load >= warnAt && warnArmed) {
|
|
18037
|
-
warnArmed = false;
|
|
18038
|
-
opts.onWarn?.(
|
|
18039
|
-
"warn",
|
|
18040
|
-
`Heap high: ${Math.round(s2.heapUsed / MB)} MB of ~${Math.round(s2.heapLimit / MB)} MB V8 limit (${Math.round(s2.load * 100)}%). Memory diagnostics are being recorded to ${logPath}`,
|
|
18041
|
-
s2
|
|
18042
|
-
);
|
|
18043
|
-
}
|
|
18044
|
-
if (!warnArmed && s2.load < warnAt - REARM_MARGIN) warnArmed = true;
|
|
18045
|
-
if (!criticalArmed && s2.load < criticalAt - REARM_MARGIN) criticalArmed = true;
|
|
18046
|
-
const due = Date.now() - lastLogAt >= logEveryMs;
|
|
18047
|
-
const crossed = s2.load >= warnAt;
|
|
18048
|
-
if (due || crossed) {
|
|
18049
|
-
lastLogAt = Date.now();
|
|
18050
|
-
let extras = {};
|
|
18051
|
-
try {
|
|
18052
|
-
extras = opts.collectStats?.() ?? {};
|
|
18053
|
-
} catch {
|
|
18054
|
-
}
|
|
18055
|
-
append(JSON.stringify({ pid: process.pid, ...s2, userTimings, ...extras }));
|
|
18056
|
-
}
|
|
18057
|
-
};
|
|
18058
|
-
const timer = setInterval(tick, sampleEveryMs);
|
|
18059
|
-
timer.unref?.();
|
|
18060
|
-
tick();
|
|
18061
|
-
if (process.env["NODE_ENV"] !== "production") {
|
|
18062
|
-
append(
|
|
18063
|
-
JSON.stringify({
|
|
18064
|
-
pid: process.pid,
|
|
18065
|
-
warn: "dev_reconciler",
|
|
18066
|
-
nodeEnv: process.env["NODE_ENV"] ?? "",
|
|
18067
|
-
ts: (/* @__PURE__ */ new Date()).toISOString()
|
|
18068
|
-
})
|
|
18069
|
-
);
|
|
18070
|
-
}
|
|
18071
|
-
return async () => {
|
|
18072
|
-
stopped = true;
|
|
18073
|
-
clearInterval(timer);
|
|
18074
|
-
await drainPromise;
|
|
18075
|
-
};
|
|
18076
|
-
}
|
|
18099
|
+
import {
|
|
18100
|
+
defaultHeapLogPath,
|
|
18101
|
+
startHeapWatchdog,
|
|
18102
|
+
startSharedHeapWatchdog,
|
|
18103
|
+
takeHeapSample
|
|
18104
|
+
} from "@wrongstack/core/utils";
|
|
18077
18105
|
|
|
18078
18106
|
// src/hooks/use-tui-activity.ts
|
|
18079
18107
|
function attachmentsSize(store) {
|
|
@@ -18102,6 +18130,7 @@ function useTuiActivity({
|
|
|
18102
18130
|
attachments,
|
|
18103
18131
|
builderRef
|
|
18104
18132
|
}) {
|
|
18133
|
+
recordTuiAppRender();
|
|
18105
18134
|
const [rolledThinkingWord, setRolledThinkingWord] = useState17(() => pickRandomTuiThinkingWord());
|
|
18106
18135
|
const thinkingWorking = status === "running" || status === "streaming";
|
|
18107
18136
|
const prevThinkingWorkingRef = useRef28(false);
|
|
@@ -18178,30 +18207,38 @@ function useTuiActivity({
|
|
|
18178
18207
|
return Math.min(100, Math.round(cpuDeltaUsec / 1e3 / wallMs / CPU_CORES * 100));
|
|
18179
18208
|
}, [nowTick]);
|
|
18180
18209
|
useEffect39(() => {
|
|
18181
|
-
const stopHeapWatchdog =
|
|
18182
|
-
collectStats: () =>
|
|
18183
|
-
|
|
18184
|
-
|
|
18185
|
-
|
|
18186
|
-
|
|
18187
|
-
|
|
18188
|
-
|
|
18189
|
-
|
|
18190
|
-
|
|
18191
|
-
|
|
18192
|
-
|
|
18193
|
-
|
|
18194
|
-
|
|
18195
|
-
|
|
18196
|
-
|
|
18197
|
-
|
|
18198
|
-
|
|
18199
|
-
|
|
18200
|
-
|
|
18201
|
-
|
|
18202
|
-
|
|
18203
|
-
|
|
18204
|
-
|
|
18210
|
+
const stopHeapWatchdog = startSharedHeapWatchdog({
|
|
18211
|
+
collectStats: () => {
|
|
18212
|
+
const currentState = stateRef.current;
|
|
18213
|
+
const messages = agentContext.state.messages;
|
|
18214
|
+
return {
|
|
18215
|
+
surface: "tui",
|
|
18216
|
+
sessionId: agentContext.session.id,
|
|
18217
|
+
// Keep this slice to shallow cardinalities: serializing the full
|
|
18218
|
+
// retained graphs created a second allocation spike precisely when
|
|
18219
|
+
// the heap was already high.
|
|
18220
|
+
historyEntries: currentState.entries.length,
|
|
18221
|
+
messages: messages.length,
|
|
18222
|
+
runningTools: currentState.runningTools.size,
|
|
18223
|
+
stdoutQueued: process.stdout.writableLength ?? 0,
|
|
18224
|
+
fleetSize: Object.keys(currentState.fleet ?? {}).length,
|
|
18225
|
+
queued: currentState.queue?.length ?? 0,
|
|
18226
|
+
inputHistory: currentState.inputHistory?.length ?? 0,
|
|
18227
|
+
toolStreamChars: currentState.toolStream?.text.length ?? 0,
|
|
18228
|
+
...snapshotTuiMemoryCounters(),
|
|
18229
|
+
// RAM retention sentinels — distinguish which layer holds old graphs
|
|
18230
|
+
// after /clear so we know where to add cleanup wiring.
|
|
18231
|
+
// attachments: DefaultAttachmentStore.items.size (cumulative
|
|
18232
|
+
// pastes/files/images for the lifetime of this process).
|
|
18233
|
+
// builderRefs: InputBuilder.refs.length (refs retained by the
|
|
18234
|
+
// mounted builder until reset() is called).
|
|
18235
|
+
// directorInFlight: coordinator in-flight task count, used to
|
|
18236
|
+
// detect that `/clear` did not actually drain subagent work.
|
|
18237
|
+
attachments: attachmentsSize(attachments),
|
|
18238
|
+
builderRefs: builderRefsLength(builderRef.current),
|
|
18239
|
+
directorInFlight: directorInFlight(agentContext)
|
|
18240
|
+
};
|
|
18241
|
+
},
|
|
18205
18242
|
onWarn: (level, message) => {
|
|
18206
18243
|
dispatch({
|
|
18207
18244
|
type: "addEntry",
|
|
@@ -19283,12 +19320,12 @@ ${menu}` };
|
|
|
19283
19320
|
kitId: active.kit,
|
|
19284
19321
|
outPath
|
|
19285
19322
|
});
|
|
19286
|
-
const
|
|
19323
|
+
const fsp = await import("node:fs/promises");
|
|
19287
19324
|
const nodePath = await import("node:path");
|
|
19288
19325
|
const abs = nodePath.join(projectRoot, result.path);
|
|
19289
19326
|
try {
|
|
19290
|
-
await
|
|
19291
|
-
await
|
|
19327
|
+
await fsp.mkdir(nodePath.dirname(abs), { recursive: true });
|
|
19328
|
+
await fsp.writeFile(abs, result.content);
|
|
19292
19329
|
} catch (e) {
|
|
19293
19330
|
return { message: `Failed to write ${result.path}: ${e.message}` };
|
|
19294
19331
|
}
|
|
@@ -19562,11 +19599,11 @@ Available chords:
|
|
|
19562
19599
|
}
|
|
19563
19600
|
|
|
19564
19601
|
// src/hooks/use-working-dir-chip.ts
|
|
19565
|
-
import * as
|
|
19602
|
+
import * as path5 from "node:path";
|
|
19566
19603
|
import { useEffect as useEffect45, useState as useState18 } from "react";
|
|
19567
19604
|
function formatWorkingDirChip(workingDir, projectRoot) {
|
|
19568
19605
|
if (!workingDir || workingDir === projectRoot) return void 0;
|
|
19569
|
-
const impl = workingDir.includes("\\") || projectRoot.includes("\\") ?
|
|
19606
|
+
const impl = workingDir.includes("\\") || projectRoot.includes("\\") ? path5.win32 : path5;
|
|
19570
19607
|
const rel = impl.relative(projectRoot, workingDir) || ".";
|
|
19571
19608
|
if (rel === ".") return void 0;
|
|
19572
19609
|
return rel.replaceAll(impl.sep, "/");
|
|
@@ -23452,7 +23489,7 @@ function PhasePanel({ phases, nowTick }) {
|
|
|
23452
23489
|
// src/components/plan-panel.tsx
|
|
23453
23490
|
import { useCallback as useCallback22, useEffect as useEffect56, useMemo as useMemo11, useState as useState29 } from "react";
|
|
23454
23491
|
import * as fs4 from "node:fs/promises";
|
|
23455
|
-
import * as
|
|
23492
|
+
import * as path6 from "node:path";
|
|
23456
23493
|
import { resolveWstackPaths as resolveWstackPaths4, sessionScopedPath } from "@wrongstack/core/utils";
|
|
23457
23494
|
import { jsx as jsx29, jsxs as jsxs28 } from "react/jsx-runtime";
|
|
23458
23495
|
var STATUS_COLOR = {
|
|
@@ -23468,12 +23505,12 @@ var STATUS_ICON = {
|
|
|
23468
23505
|
function planFilePath(projectRoot, sessionId, scope) {
|
|
23469
23506
|
const base = resolveWstackPaths4({ projectRoot }).projectSessions;
|
|
23470
23507
|
if (scope === "project") {
|
|
23471
|
-
return
|
|
23508
|
+
return path6.join(base, "backlog.plan.json");
|
|
23472
23509
|
}
|
|
23473
23510
|
if (sessionId) {
|
|
23474
23511
|
return sessionScopedPath(base, sessionId, ".plan.json");
|
|
23475
23512
|
}
|
|
23476
|
-
return
|
|
23513
|
+
return path6.join(base, "backlog.plan.json");
|
|
23477
23514
|
}
|
|
23478
23515
|
function PlanPanel({
|
|
23479
23516
|
projectRoot,
|
|
@@ -26413,8 +26450,8 @@ function detectLang(fenceInfo) {
|
|
|
26413
26450
|
const tag = fenceInfo.trim().toLowerCase().split(/\s+/)[0] ?? "";
|
|
26414
26451
|
return LANG_ALIASES[tag] ?? "plain";
|
|
26415
26452
|
}
|
|
26416
|
-
function langFromPath(
|
|
26417
|
-
const m = /\.([A-Za-z0-9]+)$/.exec(
|
|
26453
|
+
function langFromPath(path10) {
|
|
26454
|
+
const m = /\.([A-Za-z0-9]+)$/.exec(path10.trim());
|
|
26418
26455
|
const ext = m?.[1]?.toLowerCase() ?? "";
|
|
26419
26456
|
return LANG_ALIASES[ext] ?? "plain";
|
|
26420
26457
|
}
|
|
@@ -27463,7 +27500,7 @@ function parseMeta(meta) {
|
|
|
27463
27500
|
}
|
|
27464
27501
|
function parseSageMemoryLine(line) {
|
|
27465
27502
|
const match = SAGE_MEMORY_DETAIL.exec(line);
|
|
27466
|
-
if (!match
|
|
27503
|
+
if (!match?.groups) return null;
|
|
27467
27504
|
const rawLabels = match.groups["labels"] ?? "";
|
|
27468
27505
|
const labels = Array.from(rawLabels.matchAll(/\[([^\]]+)\]/g)).map((m) => m[1] ?? "").filter(Boolean);
|
|
27469
27506
|
return {
|
|
@@ -27726,19 +27763,19 @@ function formatToolArgs(toolName, input) {
|
|
|
27726
27763
|
case "codebase-stats":
|
|
27727
27764
|
return "index health";
|
|
27728
27765
|
case "lsp_diagnostics": {
|
|
27729
|
-
const
|
|
27766
|
+
const path10 = stringOf(obj["path"]);
|
|
27730
27767
|
const severity = stringArrayOf(obj["severity"]) ?? stringArrayOf(obj["severities"]);
|
|
27731
|
-
return [
|
|
27768
|
+
return [path10 ? shortenPath(path10, 40) : "workspace", severity?.join("+")].filter(Boolean).join(" \xB7 ");
|
|
27732
27769
|
}
|
|
27733
27770
|
case "lsp_definition":
|
|
27734
27771
|
case "lsp_completion":
|
|
27735
27772
|
case "lsp_rename": {
|
|
27736
|
-
const
|
|
27773
|
+
const path10 = stringOf(obj["path"]) ?? stringOf(obj["file"]);
|
|
27737
27774
|
const line = numOf(obj["line"]);
|
|
27738
27775
|
const character = numOf(obj["character"]);
|
|
27739
27776
|
const position = line !== void 0 ? `L${line}:${character ?? 1}` : "";
|
|
27740
27777
|
const rename = toolName === "lsp_rename" ? stringOf(obj["new_name"]) : void 0;
|
|
27741
|
-
return [
|
|
27778
|
+
return [path10 ? shortenPath(path10, 38) : "", position, rename ? `\u2192 ${rename}` : ""].filter(Boolean).join(" \xB7 ");
|
|
27742
27779
|
}
|
|
27743
27780
|
case "set_working_dir": {
|
|
27744
27781
|
const p = stringOf(obj["path"]);
|
|
@@ -28181,19 +28218,19 @@ function visualEdit(toolName, text, ok) {
|
|
|
28181
28218
|
const parsed = tryParseJson(text);
|
|
28182
28219
|
if (parsed && typeof parsed === "object") {
|
|
28183
28220
|
const obj = parsed;
|
|
28184
|
-
const
|
|
28221
|
+
const path10 = typeof obj["path"] === "string" ? obj["path"] : void 0;
|
|
28185
28222
|
const replacements = typeof obj["replacements"] === "number" ? obj["replacements"] : void 0;
|
|
28186
28223
|
const bytes = typeof obj["bytes"] === "number" ? obj["bytes"] : void 0;
|
|
28187
28224
|
const created = obj["created"] === true;
|
|
28188
28225
|
const files = Array.isArray(obj["files"]) ? obj["files"] : void 0;
|
|
28189
28226
|
const results = Array.isArray(obj["results"]) ? obj["results"] : void 0;
|
|
28190
|
-
if (toolName === "edit" &&
|
|
28227
|
+
if (toolName === "edit" && path10 !== void 0) {
|
|
28191
28228
|
const repText = replacements !== void 0 ? `${replacements} replacement${replacements === 1 ? "" : "s"}` : void 0;
|
|
28192
|
-
rows.push({ kind: "ok", text: "", marker: "edit ", path:
|
|
28229
|
+
rows.push({ kind: "ok", text: "", marker: "edit ", path: path10 });
|
|
28193
28230
|
if (repText) rows.push({ kind: "meta", text: repText });
|
|
28194
|
-
} else if (toolName === "write" &&
|
|
28231
|
+
} else if (toolName === "write" && path10 !== void 0) {
|
|
28195
28232
|
const sizeText = bytes !== void 0 ? `${bytes} bytes` : created ? "new file" : "updated";
|
|
28196
|
-
rows.push({ kind: "ok", text: "", marker: "write ", path:
|
|
28233
|
+
rows.push({ kind: "ok", text: "", marker: "write ", path: path10 });
|
|
28197
28234
|
rows.push({ kind: "meta", text: sizeText });
|
|
28198
28235
|
} else if ((toolName === "diff" || toolName === "patch") && files && files.length > 0) {
|
|
28199
28236
|
rows.push({
|
|
@@ -28216,8 +28253,8 @@ function visualEdit(toolName, text, ok) {
|
|
|
28216
28253
|
marker: "replace ",
|
|
28217
28254
|
text: `${results.length} replacement${results.length === 1 ? "" : "s"} across ${fileCount} file${fileCount === 1 ? "" : "s"}`
|
|
28218
28255
|
});
|
|
28219
|
-
} else if (
|
|
28220
|
-
rows.push({ kind: "ok", text: "", marker: `${toolName} `, path:
|
|
28256
|
+
} else if (path10 !== void 0) {
|
|
28257
|
+
rows.push({ kind: "ok", text: "", marker: `${toolName} `, path: path10 });
|
|
28221
28258
|
} else {
|
|
28222
28259
|
return void 0;
|
|
28223
28260
|
}
|
|
@@ -28311,12 +28348,12 @@ function parseMatchHit(hit) {
|
|
|
28311
28348
|
}
|
|
28312
28349
|
if (hit && typeof hit === "object") {
|
|
28313
28350
|
const o = hit;
|
|
28314
|
-
const
|
|
28351
|
+
const path10 = stringOf(o["file"]) ?? stringOf(o["path"]) ?? stringOf(o["url"]);
|
|
28315
28352
|
const line = numOf(o["line"]) ?? numOf(o["lineNumber"]);
|
|
28316
28353
|
const title = stringOf(o["title"]);
|
|
28317
28354
|
const snippet2 = stringOf(o["snippet"]);
|
|
28318
28355
|
const text = stringOf(o["text"]) ?? stringOf(o["match"]) ?? stringOf(o["preview"]) ?? [title, snippet2].filter(Boolean).join(" \u2014 ");
|
|
28319
|
-
return { path:
|
|
28356
|
+
return { path: path10, line: line === void 0 ? void 0 : String(line), text };
|
|
28320
28357
|
}
|
|
28321
28358
|
return void 0;
|
|
28322
28359
|
}
|
|
@@ -28414,8 +28451,8 @@ function splitReplaceDiffs(obj) {
|
|
|
28414
28451
|
const record = result;
|
|
28415
28452
|
const diff = stringOf(record["diff"]);
|
|
28416
28453
|
if (!diff?.trim()) continue;
|
|
28417
|
-
const
|
|
28418
|
-
items.push(
|
|
28454
|
+
const path10 = stringOf(record["path"]);
|
|
28455
|
+
items.push(path10 ? { path: path10, diff } : { diff });
|
|
28419
28456
|
}
|
|
28420
28457
|
return items;
|
|
28421
28458
|
}
|
|
@@ -28490,8 +28527,8 @@ function collectMultiFileDiffItems(toolName, output, _input) {
|
|
|
28490
28527
|
if (!diffText?.trim()) return void 0;
|
|
28491
28528
|
const blocks = splitGitStyleDiff(diffText);
|
|
28492
28529
|
if (blocks.length === 0) {
|
|
28493
|
-
const
|
|
28494
|
-
return [{ path:
|
|
28530
|
+
const path10 = explicitFiles[0] ?? extractPatchHeaderPath(diffText);
|
|
28531
|
+
return [{ path: path10, diff: diffText }];
|
|
28495
28532
|
}
|
|
28496
28533
|
return blocks.map((block, idx) => ({
|
|
28497
28534
|
path: explicitFiles[idx] ?? block.path,
|
|
@@ -28525,9 +28562,9 @@ function newFileDiffFromWriteInput(output, input) {
|
|
|
28525
28562
|
const obj = input;
|
|
28526
28563
|
const content = stringOf(obj["content"]);
|
|
28527
28564
|
if (content === void 0) return void 0;
|
|
28528
|
-
const
|
|
28565
|
+
const path10 = stringOf(output["path"]) ?? stringOf(obj["path"]) ?? "new file";
|
|
28529
28566
|
const lines = content === "" ? [] : content.replace(/\n$/, "").split("\n");
|
|
28530
|
-
const header = [`+++ ${
|
|
28567
|
+
const header = [`+++ ${path10}`, `@@ -0,0 +1,${lines.length} @@`];
|
|
28531
28568
|
return [...header, ...lines.map((line) => `+${line}`)].join("\n");
|
|
28532
28569
|
}
|
|
28533
28570
|
function splitGitStyleDiff(diff) {
|
|
@@ -28567,8 +28604,8 @@ function splitGitStyleDiff(diff) {
|
|
|
28567
28604
|
}
|
|
28568
28605
|
flush();
|
|
28569
28606
|
if (blocks.length === 1 && !blocks[0].path) {
|
|
28570
|
-
const
|
|
28571
|
-
if (
|
|
28607
|
+
const path10 = extractPatchHeaderPath(blocks[0].diff);
|
|
28608
|
+
if (path10) blocks[0] = { path: path10, diff: blocks[0].diff };
|
|
28572
28609
|
}
|
|
28573
28610
|
return blocks;
|
|
28574
28611
|
}
|
|
@@ -28589,8 +28626,8 @@ function parseDiffGitPath(line) {
|
|
|
28589
28626
|
function extractPatchHeaderPath(diffText) {
|
|
28590
28627
|
for (const line of diffText.split("\n")) {
|
|
28591
28628
|
if (line.startsWith("+++ ")) {
|
|
28592
|
-
const
|
|
28593
|
-
const cleaned =
|
|
28629
|
+
const path10 = line.slice(4).trim();
|
|
28630
|
+
const cleaned = path10.replace(/^b\//, "").split(" ")[0].trim();
|
|
28594
28631
|
return cleaned || void 0;
|
|
28595
28632
|
}
|
|
28596
28633
|
}
|
|
@@ -28722,13 +28759,13 @@ function formatMultiDiffSummary(summary, threshold = MULTI_DIFF_SUMMARY_THRESHOL
|
|
|
28722
28759
|
return parts.join(" \xB7 ");
|
|
28723
28760
|
}
|
|
28724
28761
|
function DiffFileBlock({
|
|
28725
|
-
path:
|
|
28762
|
+
path: path10,
|
|
28726
28763
|
preview,
|
|
28727
28764
|
useColor = true,
|
|
28728
28765
|
contentWidth
|
|
28729
28766
|
}) {
|
|
28730
28767
|
return /* @__PURE__ */ jsxs45(Box, { flexDirection: "column", marginTop: 1, children: [
|
|
28731
|
-
/* @__PURE__ */ jsx46(Text, { dimColor: true, italic: true, children:
|
|
28768
|
+
/* @__PURE__ */ jsx46(Text, { dimColor: true, italic: true, children: path10 }),
|
|
28732
28769
|
/* @__PURE__ */ jsx46(
|
|
28733
28770
|
DiffBlock,
|
|
28734
28771
|
{
|
|
@@ -28739,7 +28776,7 @@ function DiffFileBlock({
|
|
|
28739
28776
|
hiddenAdded: preview.hiddenAdded,
|
|
28740
28777
|
hiddenRemoved: preview.hiddenRemoved,
|
|
28741
28778
|
useColor,
|
|
28742
|
-
lang: langFromPath(
|
|
28779
|
+
lang: langFromPath(path10),
|
|
28743
28780
|
contentWidth
|
|
28744
28781
|
}
|
|
28745
28782
|
)
|
|
@@ -28996,7 +29033,7 @@ function renderDiffLine(line) {
|
|
|
28996
29033
|
"\n"
|
|
28997
29034
|
] }, line);
|
|
28998
29035
|
}
|
|
28999
|
-
function renderDiff(diff,
|
|
29036
|
+
function renderDiff(diff, path10) {
|
|
29000
29037
|
const preview = parseUnifiedDiff(diff, CONFIRM_DIFF_MAX_LINES);
|
|
29001
29038
|
if (preview.rows.length > 0) {
|
|
29002
29039
|
return /* @__PURE__ */ jsx47(
|
|
@@ -29009,7 +29046,7 @@ function renderDiff(diff, path11) {
|
|
|
29009
29046
|
hiddenAdded: preview.hiddenAdded,
|
|
29010
29047
|
hiddenRemoved: preview.hiddenRemoved,
|
|
29011
29048
|
useColor: theme.supportsBackground,
|
|
29012
|
-
lang: langFromPath(
|
|
29049
|
+
lang: langFromPath(path10 ?? "")
|
|
29013
29050
|
}
|
|
29014
29051
|
);
|
|
29015
29052
|
}
|
|
@@ -29092,7 +29129,11 @@ import {
|
|
|
29092
29129
|
import { resolveWstackPaths as resolveWstackPaths5 } from "@wrongstack/core/utils";
|
|
29093
29130
|
import { getKanbanServerConnection } from "@wrongstack/kanban";
|
|
29094
29131
|
import { isSageProjectServerAvailable, SageProjectServerConnection } from "@wrongstack/sage";
|
|
29095
|
-
import {
|
|
29132
|
+
import {
|
|
29133
|
+
checkCodebaseIndexServerHealth,
|
|
29134
|
+
getIndexState as getIndexState2,
|
|
29135
|
+
resolveProjectIndexDaemonAvailability
|
|
29136
|
+
} from "@wrongstack/tools";
|
|
29096
29137
|
async function collectConnectionsHealth(projectRoot) {
|
|
29097
29138
|
const services = await Promise.all([
|
|
29098
29139
|
chronicleHealth(projectRoot),
|
|
@@ -29138,6 +29179,19 @@ async function chronicleHealth(projectRoot) {
|
|
|
29138
29179
|
}
|
|
29139
29180
|
async function codebaseIndexHealth(projectRoot) {
|
|
29140
29181
|
const startedAt = Date.now();
|
|
29182
|
+
const availability = resolveProjectIndexDaemonAvailability(projectRoot);
|
|
29183
|
+
if (availability.kind === "endpoint-invalid") {
|
|
29184
|
+
return {
|
|
29185
|
+
id: "codebase-index",
|
|
29186
|
+
label: "Codebase index",
|
|
29187
|
+
status: "unavailable",
|
|
29188
|
+
required: false,
|
|
29189
|
+
mode: "endpoint-invalid",
|
|
29190
|
+
detail: `Socket path is ${availability.byteLength} bytes \u2014 over this platform's ${availability.maxBytes}-byte sun_path limit. Queries fall back to a process-local index. Set a shorter TMPDIR to restore the shared daemon.`,
|
|
29191
|
+
endpoint: availability.endpoint,
|
|
29192
|
+
latencyMs: Date.now() - startedAt
|
|
29193
|
+
};
|
|
29194
|
+
}
|
|
29141
29195
|
try {
|
|
29142
29196
|
const health2 = await checkCodebaseIndexServerHealth(projectRoot, void 0, { timeoutMs: 2e3 });
|
|
29143
29197
|
const connection = getIndexState2().server;
|
|
@@ -30187,8 +30241,8 @@ function FilePicker({ query, matches, selected }) {
|
|
|
30187
30241
|
] }, m))
|
|
30188
30242
|
] });
|
|
30189
30243
|
}
|
|
30190
|
-
function highlight(
|
|
30191
|
-
return
|
|
30244
|
+
function highlight(path10, _query) {
|
|
30245
|
+
return path10;
|
|
30192
30246
|
}
|
|
30193
30247
|
|
|
30194
30248
|
// src/components/help-panel.tsx
|
|
@@ -31536,14 +31590,14 @@ function estimateSageKvRows(cells, contentWidth) {
|
|
|
31536
31590
|
}
|
|
31537
31591
|
return rows;
|
|
31538
31592
|
}
|
|
31539
|
-
function estimateRenderGroupRows(group, contentWidth) {
|
|
31593
|
+
function estimateRenderGroupRows(group, contentWidth, showSageMemoryInject) {
|
|
31540
31594
|
if (group.type === "tool-group") return group.data.entries.length + 2;
|
|
31541
31595
|
const { entry } = group;
|
|
31542
31596
|
if (entry.kind === "tool") {
|
|
31543
31597
|
const { cleanOutput, sageLines } = resolveEntrySage(entry.output, entry.sageLines);
|
|
31544
31598
|
const memoryLines = sageLines.slice(1);
|
|
31545
31599
|
const panelContentWidth = Math.max(16, contentWidth - 4);
|
|
31546
|
-
const sagePanelRows = memoryLines.length
|
|
31600
|
+
const sagePanelRows = showSageMemoryInject === false || memoryLines.length === 0 ? 0 : 2 + estimateTextRows(
|
|
31547
31601
|
`\u{1F9E0} SAGE MEMORY INJECTED \xB7 ${entry.name} ${memoryLines.length} ${memoryLines.length === 1 ? "memory" : "memories"}${entry.sageStats ? ` \xB7 ${entry.sageStats}` : ""}`,
|
|
31548
31602
|
panelContentWidth,
|
|
31549
31603
|
MAX_TEXT_ESTIMATE_ROWS
|
|
@@ -31566,7 +31620,7 @@ function estimateRenderGroupRows(group, contentWidth) {
|
|
|
31566
31620
|
const kvRows = estimateSageKvRows(kvCells, panelContentWidth);
|
|
31567
31621
|
const gap = rows > 0 ? 1 : 0;
|
|
31568
31622
|
return rows + labelRow + bodyRow + kvRows + gap;
|
|
31569
|
-
}, 0)
|
|
31623
|
+
}, 0);
|
|
31570
31624
|
if (entry.resultRenderMode === "simple") return 3 + sagePanelRows;
|
|
31571
31625
|
if (STRUCTURED_DIFF_TOOLS.has(entry.name)) {
|
|
31572
31626
|
const previewCap = entry.name === "replace" || entry.name === "diff" || entry.name === "patch" ? MULTI_DIFF_MAX_ROWS : DIFF_MAX_LINES;
|
|
@@ -32825,9 +32879,11 @@ var Entry = React8.memo(function Entry2({
|
|
|
32825
32879
|
autonomyMode,
|
|
32826
32880
|
multiDiffSummaryThreshold,
|
|
32827
32881
|
todos,
|
|
32828
|
-
showModelReasoning
|
|
32882
|
+
showModelReasoning,
|
|
32883
|
+
showSageMemoryInject
|
|
32829
32884
|
}) {
|
|
32830
32885
|
const openTodos = hasOpenTodos(todos);
|
|
32886
|
+
const isFinalTurnEntry = entry.kind === "assistant" && entry.final === true;
|
|
32831
32887
|
const nextSteps = useMemo13(() => {
|
|
32832
32888
|
if (entry.kind !== "assistant") return { steps: [], stripped: "" };
|
|
32833
32889
|
return parseNextSteps(entry.text, true);
|
|
@@ -32836,10 +32892,17 @@ var Entry = React8.memo(function Entry2({
|
|
|
32836
32892
|
if (!setSuggestions) return;
|
|
32837
32893
|
if (entry.kind !== "assistant") return;
|
|
32838
32894
|
if (openTodos) return;
|
|
32895
|
+
if (!isFinalTurnEntry) return;
|
|
32839
32896
|
const text = entry.text ?? "";
|
|
32840
32897
|
const { texts } = parseNextSteps(text, true);
|
|
32841
32898
|
if (texts.length > 0) setSuggestions(texts);
|
|
32842
|
-
}, [
|
|
32899
|
+
}, [
|
|
32900
|
+
entry.kind,
|
|
32901
|
+
entry.text,
|
|
32902
|
+
openTodos,
|
|
32903
|
+
isFinalTurnEntry,
|
|
32904
|
+
setSuggestions
|
|
32905
|
+
]);
|
|
32843
32906
|
switch (entry.kind) {
|
|
32844
32907
|
case "user":
|
|
32845
32908
|
return /* @__PURE__ */ jsx70(
|
|
@@ -32894,7 +32957,7 @@ var Entry = React8.memo(function Entry2({
|
|
|
32894
32957
|
case "assistant": {
|
|
32895
32958
|
const contentWidth = assistantContentWidth(termWidth);
|
|
32896
32959
|
const { steps, stripped } = nextSteps;
|
|
32897
|
-
const hasNext = steps.length > 0 && !openTodos;
|
|
32960
|
+
const hasNext = steps.length > 0 && !openTodos && isFinalTurnEntry;
|
|
32898
32961
|
return /* @__PURE__ */ jsxs68(Box, { flexDirection: "column", children: [
|
|
32899
32962
|
/* @__PURE__ */ jsxs68(
|
|
32900
32963
|
Box,
|
|
@@ -32994,15 +33057,15 @@ var Entry = React8.memo(function Entry2({
|
|
|
32994
33057
|
const outObj = outJson && typeof outJson === "object" ? outJson : void 0;
|
|
32995
33058
|
const created = name === "write" && (outObj?.["created"] === true || /^[^\n]*\bcreated=true\b/.test(outputForFormatting));
|
|
32996
33059
|
const verb = created ? "Write" : "Update";
|
|
32997
|
-
const
|
|
33060
|
+
const path10 = stringOf(inputObj?.["path"]) ?? stringOf(outObj?.["path"]);
|
|
32998
33061
|
const agg = multiDiffs2 ? summarizeMultiFileDiffs(multiDiffs2) : void 0;
|
|
32999
|
-
const target = multiDiffs2 ? agg?.fileCount === 1 ? multiDiffs2[0].path : `${agg?.fileCount ?? multiDiffs2.length} files` :
|
|
33062
|
+
const target = multiDiffs2 ? agg?.fileCount === 1 ? multiDiffs2[0].path : `${agg?.fileCount ?? multiDiffs2.length} files` : path10 ?? "file";
|
|
33000
33063
|
return {
|
|
33001
33064
|
verb,
|
|
33002
33065
|
target,
|
|
33003
33066
|
added: agg ? agg.added : diff2?.added ?? 0,
|
|
33004
33067
|
removed: agg ? agg.removed : diff2?.removed ?? 0,
|
|
33005
|
-
lang: langFromPath(multiDiffs2 ? "" :
|
|
33068
|
+
lang: langFromPath(multiDiffs2 ? "" : path10 ?? "")
|
|
33006
33069
|
};
|
|
33007
33070
|
})();
|
|
33008
33071
|
return {
|
|
@@ -33086,14 +33149,14 @@ var Entry = React8.memo(function Entry2({
|
|
|
33086
33149
|
]
|
|
33087
33150
|
}
|
|
33088
33151
|
),
|
|
33089
|
-
/* @__PURE__ */ jsx70(
|
|
33152
|
+
showSageMemoryInject !== false ? /* @__PURE__ */ jsx70(
|
|
33090
33153
|
SageMemoryBlock,
|
|
33091
33154
|
{
|
|
33092
33155
|
sageLines,
|
|
33093
33156
|
toolName: entry.name,
|
|
33094
33157
|
stats: entry.sageStats
|
|
33095
33158
|
}
|
|
33096
|
-
)
|
|
33159
|
+
) : null
|
|
33097
33160
|
] });
|
|
33098
33161
|
}
|
|
33099
33162
|
const toolContentWidth = Math.max(20, termWidth - 2);
|
|
@@ -33173,7 +33236,7 @@ var Entry = React8.memo(function Entry2({
|
|
|
33173
33236
|
]
|
|
33174
33237
|
}
|
|
33175
33238
|
),
|
|
33176
|
-
/* @__PURE__ */ jsx70(SageMemoryBlock, { sageLines, toolName: entry.name, stats: entry.sageStats })
|
|
33239
|
+
showSageMemoryInject !== false ? /* @__PURE__ */ jsx70(SageMemoryBlock, { sageLines, toolName: entry.name, stats: entry.sageStats }) : null
|
|
33177
33240
|
] });
|
|
33178
33241
|
}
|
|
33179
33242
|
case "memory-activation": {
|
|
@@ -33450,7 +33513,8 @@ var History = memo2(function History2({
|
|
|
33450
33513
|
autonomyMode,
|
|
33451
33514
|
multiDiffSummaryThreshold,
|
|
33452
33515
|
todos,
|
|
33453
|
-
showModelReasoning
|
|
33516
|
+
showModelReasoning,
|
|
33517
|
+
showSageMemoryInject
|
|
33454
33518
|
}) {
|
|
33455
33519
|
const { stdout } = useStdout();
|
|
33456
33520
|
const [termSize, setTermSize] = useState39({
|
|
@@ -33525,7 +33589,8 @@ var History = memo2(function History2({
|
|
|
33525
33589
|
autonomyMode,
|
|
33526
33590
|
multiDiffSummaryThreshold,
|
|
33527
33591
|
todos,
|
|
33528
|
-
showModelReasoning
|
|
33592
|
+
showModelReasoning,
|
|
33593
|
+
showSageMemoryInject
|
|
33529
33594
|
}
|
|
33530
33595
|
) }, entry.id) }, staticKey),
|
|
33531
33596
|
/* @__PURE__ */ jsx71(Box, { flexGrow: 1 })
|
|
@@ -33675,6 +33740,7 @@ var ScrollableHistory = memo3(function ScrollableHistory2({
|
|
|
33675
33740
|
multiDiffSummaryThreshold,
|
|
33676
33741
|
todos,
|
|
33677
33742
|
showModelReasoning,
|
|
33743
|
+
showSageMemoryInject,
|
|
33678
33744
|
layoutStore,
|
|
33679
33745
|
copiedEntryId,
|
|
33680
33746
|
onRequestOlderEntries
|
|
@@ -33717,7 +33783,8 @@ var ScrollableHistory = memo3(function ScrollableHistory2({
|
|
|
33717
33783
|
const preparedGroupIdsRef = useRef37(null);
|
|
33718
33784
|
const preparedEstimateWidthRef = useRef37(null);
|
|
33719
33785
|
const reasoningKey = showModelReasoning === false ? "|r0" : "";
|
|
33720
|
-
const
|
|
33786
|
+
const sageKey = showSageMemoryInject === false ? "|s0" : "";
|
|
33787
|
+
const cacheKey = (layoutStore ? `${groupIdsKey}|w${termWidth}` : groupIdsKey) + reasoningKey + sageKey;
|
|
33721
33788
|
if (preparedGroupIdsRef.current !== cacheKey || preparedEstimateWidthRef.current !== termWidth) {
|
|
33722
33789
|
const widthChanged = preparedEstimateWidthRef.current !== null && preparedEstimateWidthRef.current !== termWidth;
|
|
33723
33790
|
if (widthChanged) {
|
|
@@ -33744,7 +33811,7 @@ var ScrollableHistory = memo3(function ScrollableHistory2({
|
|
|
33744
33811
|
}
|
|
33745
33812
|
if (stored.kind === "measured") measuredGroupIdsRef.current.add(id);
|
|
33746
33813
|
} else {
|
|
33747
|
-
const estimatedRows = estimateRenderGroupRows(group, termWidth);
|
|
33814
|
+
const estimatedRows = estimateRenderGroupRows(group, termWidth, showSageMemoryInject);
|
|
33748
33815
|
heightCache.record(id, estimatedRows);
|
|
33749
33816
|
const kind = group.type === "tool-group" ? "tool-group" : group.entry.kind;
|
|
33750
33817
|
const text = group.type === "tool-group" ? group.data.name : group.entry.text ?? "";
|
|
@@ -33763,7 +33830,10 @@ var ScrollableHistory = memo3(function ScrollableHistory2({
|
|
|
33763
33830
|
const id = renderGroupId(group);
|
|
33764
33831
|
const hidden = group.type !== "tool-group" && group.entry.kind === "thinking" && showModelReasoning === false;
|
|
33765
33832
|
if (hidden) hiddenIds.add(id);
|
|
33766
|
-
return [
|
|
33833
|
+
return [
|
|
33834
|
+
id,
|
|
33835
|
+
hidden ? 0 : estimateRenderGroupRows(group, termWidth, showSageMemoryInject)
|
|
33836
|
+
];
|
|
33767
33837
|
})
|
|
33768
33838
|
);
|
|
33769
33839
|
heightCache.recordMany(
|
|
@@ -33895,6 +33965,19 @@ var ScrollableHistory = memo3(function ScrollableHistory2({
|
|
|
33895
33965
|
const clip2 = effectiveAnchor?.clip ?? 0;
|
|
33896
33966
|
planStartIdxRef.current = plan.startIdx;
|
|
33897
33967
|
const totalRows = contentRows(geometry);
|
|
33968
|
+
setTuiHistoryMemoryGauges({
|
|
33969
|
+
historyRetainedEntries: entries.length,
|
|
33970
|
+
historyGroupedEntries: groupedEntries.length,
|
|
33971
|
+
historyMountedGroups: renderGroups.length,
|
|
33972
|
+
historyMountedEntries: renderGroups.reduce(
|
|
33973
|
+
(count, group) => count + (group.type === "tool-group" ? group.data.entries.length : 1),
|
|
33974
|
+
0
|
|
33975
|
+
),
|
|
33976
|
+
historyCachedGroups: heightCache.size,
|
|
33977
|
+
historyMeasuredGroups: measuredGroupIdsRef.current.size,
|
|
33978
|
+
historyViewportRows: vp,
|
|
33979
|
+
historyTotalRows: totalRows
|
|
33980
|
+
});
|
|
33898
33981
|
const offsetFromBottom = scrolled ? Math.max(0, maxTopRow(geometry) - anchorTopRow(geometry, effectiveAnchor)) : 0;
|
|
33899
33982
|
const copyRegistry = buildCopyRegistry({
|
|
33900
33983
|
renderGroups,
|
|
@@ -34012,7 +34095,8 @@ var ScrollableHistory = memo3(function ScrollableHistory2({
|
|
|
34012
34095
|
autonomyMode,
|
|
34013
34096
|
multiDiffSummaryThreshold,
|
|
34014
34097
|
todos,
|
|
34015
|
-
showModelReasoning
|
|
34098
|
+
showModelReasoning,
|
|
34099
|
+
showSageMemoryInject
|
|
34016
34100
|
}
|
|
34017
34101
|
)
|
|
34018
34102
|
}
|
|
@@ -34508,6 +34592,7 @@ function AppView({ host, runtime }) {
|
|
|
34508
34592
|
multiDiffSummaryThreshold: state.settingsPicker.multiDiffSummaryThreshold,
|
|
34509
34593
|
todos: liveTodos,
|
|
34510
34594
|
showModelReasoning: state.settingsPicker.open ? state.settingsPicker.showModelReasoning : liveSettings?.showModelReasoning ?? true,
|
|
34595
|
+
showSageMemoryInject: state.settingsPicker.open ? state.settingsPicker.showSageMemoryInject : liveSettings?.showSageMemoryInject ?? false,
|
|
34511
34596
|
layoutStore,
|
|
34512
34597
|
copiedEntryId: state.copiedEntryId,
|
|
34513
34598
|
onRequestOlderEntries: runtime.onRequestOlderEntries
|
|
@@ -34659,6 +34744,8 @@ function AppView({ host, runtime }) {
|
|
|
34659
34744
|
breakerAutoKillResetMs: state.settingsPicker.breakerAutoKillResetMs,
|
|
34660
34745
|
showModelReasoning: state.settingsPicker.showModelReasoning,
|
|
34661
34746
|
showAgentSwarmPanel: state.settingsPicker.showAgentSwarmPanel,
|
|
34747
|
+
showSageMemoryInject: state.settingsPicker.showSageMemoryInject,
|
|
34748
|
+
sageMemoryInjectThreshold: state.settingsPicker.sageMemoryInjectThreshold,
|
|
34662
34749
|
readSymbols: state.settingsPicker.readSymbols,
|
|
34663
34750
|
filter: state.settingsPicker.filter,
|
|
34664
34751
|
hint: state.settingsPicker.hint
|
|
@@ -35052,7 +35139,10 @@ function createRunBlocksController(host) {
|
|
|
35052
35139
|
}
|
|
35053
35140
|
dispatch({ type: "streamReset" });
|
|
35054
35141
|
if (result.status === "done" && result.finalText?.trim() && !refs.assistantCommitted.current) {
|
|
35055
|
-
dispatch({
|
|
35142
|
+
dispatch({
|
|
35143
|
+
type: "addEntry",
|
|
35144
|
+
entry: { kind: "assistant", text: result.finalText, final: true }
|
|
35145
|
+
});
|
|
35056
35146
|
}
|
|
35057
35147
|
if (result.status === "aborted") {
|
|
35058
35148
|
const reason = result.abortReason ? `Aborted (${result.abortReason}).` : "Aborted.";
|
|
@@ -36383,6 +36473,8 @@ function routeSettingsOverlayKey(host, input, key, isEnter) {
|
|
|
36383
36473
|
breakerAutoKillResetMs: config.breakerAutoKillResetMs ?? 6e4,
|
|
36384
36474
|
showModelReasoning: config.showModelReasoning ?? true,
|
|
36385
36475
|
showAgentSwarmPanel: config.showAgentSwarmPanel ?? true,
|
|
36476
|
+
showSageMemoryInject: config.showSageMemoryInject ?? false,
|
|
36477
|
+
sageMemoryInjectThreshold: config.sageMemoryInjectThreshold ?? 0.85,
|
|
36386
36478
|
readSymbols: config.readSymbols ?? false
|
|
36387
36479
|
});
|
|
36388
36480
|
return true;
|
|
@@ -37159,8 +37251,8 @@ function App(props) {
|
|
|
37159
37251
|
submitRef
|
|
37160
37252
|
} = useAppRuntimeRefs(attachments, state);
|
|
37161
37253
|
const projectName = React10.useMemo(() => {
|
|
37162
|
-
const base =
|
|
37163
|
-
return base && base !==
|
|
37254
|
+
const base = path7.basename(projectRoot);
|
|
37255
|
+
return base && base !== path7.sep ? base : void 0;
|
|
37164
37256
|
}, [projectRoot]);
|
|
37165
37257
|
const workingDirChip = useWorkingDirChip(agent.ctx, projectRoot);
|
|
37166
37258
|
const {
|
|
@@ -37896,9 +37988,9 @@ var BRACKETED_PASTE_OFF = "\x1B[?2004l";
|
|
|
37896
37988
|
|
|
37897
37989
|
// src/run-tui-client-registration.ts
|
|
37898
37990
|
import { randomUUID } from "node:crypto";
|
|
37899
|
-
import * as
|
|
37991
|
+
import * as path8 from "node:path";
|
|
37900
37992
|
import { RemoteMailbox, resolveProjectDir } from "@wrongstack/core/coordination";
|
|
37901
|
-
import { wstackGlobalRoot
|
|
37993
|
+
import { wstackGlobalRoot } from "@wrongstack/core/utils";
|
|
37902
37994
|
import {
|
|
37903
37995
|
createHqPublisherFromEnv,
|
|
37904
37996
|
startBrainTelemetryBridge,
|
|
@@ -37924,7 +38016,7 @@ function createRunTuiClientRegistration(opts) {
|
|
|
37924
38016
|
if (!opts.projectRoot) return null;
|
|
37925
38017
|
const generation = ++registrationGeneration;
|
|
37926
38018
|
try {
|
|
37927
|
-
const projectDir = resolveProjectDir(opts.projectRoot,
|
|
38019
|
+
const projectDir = resolveProjectDir(opts.projectRoot, wstackGlobalRoot());
|
|
37928
38020
|
const mailbox = new RemoteMailbox({ projectDir, events: opts.events });
|
|
37929
38021
|
const clientId = `tui@${randomUUID().slice(0, 8)}`;
|
|
37930
38022
|
await mailbox.initialize();
|
|
@@ -37983,7 +38075,7 @@ function createRunTuiClientRegistration(opts) {
|
|
|
37983
38075
|
await mailbox.registerClient({
|
|
37984
38076
|
clientId,
|
|
37985
38077
|
sessionId: opts.getSessionId?.() ?? opts.projectRoot,
|
|
37986
|
-
name: `TUI [${
|
|
38078
|
+
name: `TUI [${path8.basename(opts.projectRoot)}]`,
|
|
37987
38079
|
source: "tui",
|
|
37988
38080
|
pid: process.pid
|
|
37989
38081
|
});
|
|
@@ -37998,7 +38090,7 @@ function createRunTuiClientRegistration(opts) {
|
|
|
37998
38090
|
tuiHqPublisher = createHqPublisherFromEnv({
|
|
37999
38091
|
clientKind: "tui",
|
|
38000
38092
|
projectRoot: opts.projectRoot,
|
|
38001
|
-
projectName:
|
|
38093
|
+
projectName: path8.basename(opts.projectRoot),
|
|
38002
38094
|
appConfig: opts.appConfig
|
|
38003
38095
|
});
|
|
38004
38096
|
tuiHqPublisher?.connect();
|
|
@@ -38011,7 +38103,7 @@ function createRunTuiClientRegistration(opts) {
|
|
|
38011
38103
|
events: opts.events,
|
|
38012
38104
|
sessionId: tuiSessionId,
|
|
38013
38105
|
projectRoot: opts.projectRoot,
|
|
38014
|
-
projectName:
|
|
38106
|
+
projectName: path8.basename(opts.projectRoot)
|
|
38015
38107
|
})
|
|
38016
38108
|
);
|
|
38017
38109
|
} catch {
|
|
@@ -38136,7 +38228,7 @@ function createRunTuiClientRegistration(opts) {
|
|
|
38136
38228
|
}
|
|
38137
38229
|
|
|
38138
38230
|
// src/run-tui-title-controller.ts
|
|
38139
|
-
import * as
|
|
38231
|
+
import * as path9 from "node:path";
|
|
38140
38232
|
|
|
38141
38233
|
// src/terminal-title.ts
|
|
38142
38234
|
var SPINNER = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
|
|
@@ -38216,7 +38308,7 @@ function createRunTuiTitleController(opts) {
|
|
|
38216
38308
|
stdout: opts.stdout,
|
|
38217
38309
|
events: opts.events,
|
|
38218
38310
|
model: currentModel,
|
|
38219
|
-
appName: opts.projectRoot ?
|
|
38311
|
+
appName: opts.projectRoot ? path9.basename(opts.projectRoot) : void 0
|
|
38220
38312
|
});
|
|
38221
38313
|
};
|
|
38222
38314
|
const stop = () => {
|