@wrongstack/tui 0.296.4 → 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/heap-watchdog.d.ts +6 -42
- package/dist/heap-watchdog.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 +335 -260
- 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
|
}
|
|
@@ -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
|
}
|
|
@@ -30204,8 +30241,8 @@ function FilePicker({ query, matches, selected }) {
|
|
|
30204
30241
|
] }, m))
|
|
30205
30242
|
] });
|
|
30206
30243
|
}
|
|
30207
|
-
function highlight(
|
|
30208
|
-
return
|
|
30244
|
+
function highlight(path10, _query) {
|
|
30245
|
+
return path10;
|
|
30209
30246
|
}
|
|
30210
30247
|
|
|
30211
30248
|
// src/components/help-panel.tsx
|
|
@@ -31553,14 +31590,14 @@ function estimateSageKvRows(cells, contentWidth) {
|
|
|
31553
31590
|
}
|
|
31554
31591
|
return rows;
|
|
31555
31592
|
}
|
|
31556
|
-
function estimateRenderGroupRows(group, contentWidth) {
|
|
31593
|
+
function estimateRenderGroupRows(group, contentWidth, showSageMemoryInject) {
|
|
31557
31594
|
if (group.type === "tool-group") return group.data.entries.length + 2;
|
|
31558
31595
|
const { entry } = group;
|
|
31559
31596
|
if (entry.kind === "tool") {
|
|
31560
31597
|
const { cleanOutput, sageLines } = resolveEntrySage(entry.output, entry.sageLines);
|
|
31561
31598
|
const memoryLines = sageLines.slice(1);
|
|
31562
31599
|
const panelContentWidth = Math.max(16, contentWidth - 4);
|
|
31563
|
-
const sagePanelRows = memoryLines.length
|
|
31600
|
+
const sagePanelRows = showSageMemoryInject === false || memoryLines.length === 0 ? 0 : 2 + estimateTextRows(
|
|
31564
31601
|
`\u{1F9E0} SAGE MEMORY INJECTED \xB7 ${entry.name} ${memoryLines.length} ${memoryLines.length === 1 ? "memory" : "memories"}${entry.sageStats ? ` \xB7 ${entry.sageStats}` : ""}`,
|
|
31565
31602
|
panelContentWidth,
|
|
31566
31603
|
MAX_TEXT_ESTIMATE_ROWS
|
|
@@ -31583,7 +31620,7 @@ function estimateRenderGroupRows(group, contentWidth) {
|
|
|
31583
31620
|
const kvRows = estimateSageKvRows(kvCells, panelContentWidth);
|
|
31584
31621
|
const gap = rows > 0 ? 1 : 0;
|
|
31585
31622
|
return rows + labelRow + bodyRow + kvRows + gap;
|
|
31586
|
-
}, 0)
|
|
31623
|
+
}, 0);
|
|
31587
31624
|
if (entry.resultRenderMode === "simple") return 3 + sagePanelRows;
|
|
31588
31625
|
if (STRUCTURED_DIFF_TOOLS.has(entry.name)) {
|
|
31589
31626
|
const previewCap = entry.name === "replace" || entry.name === "diff" || entry.name === "patch" ? MULTI_DIFF_MAX_ROWS : DIFF_MAX_LINES;
|
|
@@ -32842,9 +32879,11 @@ var Entry = React8.memo(function Entry2({
|
|
|
32842
32879
|
autonomyMode,
|
|
32843
32880
|
multiDiffSummaryThreshold,
|
|
32844
32881
|
todos,
|
|
32845
|
-
showModelReasoning
|
|
32882
|
+
showModelReasoning,
|
|
32883
|
+
showSageMemoryInject
|
|
32846
32884
|
}) {
|
|
32847
32885
|
const openTodos = hasOpenTodos(todos);
|
|
32886
|
+
const isFinalTurnEntry = entry.kind === "assistant" && entry.final === true;
|
|
32848
32887
|
const nextSteps = useMemo13(() => {
|
|
32849
32888
|
if (entry.kind !== "assistant") return { steps: [], stripped: "" };
|
|
32850
32889
|
return parseNextSteps(entry.text, true);
|
|
@@ -32853,10 +32892,17 @@ var Entry = React8.memo(function Entry2({
|
|
|
32853
32892
|
if (!setSuggestions) return;
|
|
32854
32893
|
if (entry.kind !== "assistant") return;
|
|
32855
32894
|
if (openTodos) return;
|
|
32895
|
+
if (!isFinalTurnEntry) return;
|
|
32856
32896
|
const text = entry.text ?? "";
|
|
32857
32897
|
const { texts } = parseNextSteps(text, true);
|
|
32858
32898
|
if (texts.length > 0) setSuggestions(texts);
|
|
32859
|
-
}, [
|
|
32899
|
+
}, [
|
|
32900
|
+
entry.kind,
|
|
32901
|
+
entry.text,
|
|
32902
|
+
openTodos,
|
|
32903
|
+
isFinalTurnEntry,
|
|
32904
|
+
setSuggestions
|
|
32905
|
+
]);
|
|
32860
32906
|
switch (entry.kind) {
|
|
32861
32907
|
case "user":
|
|
32862
32908
|
return /* @__PURE__ */ jsx70(
|
|
@@ -32911,7 +32957,7 @@ var Entry = React8.memo(function Entry2({
|
|
|
32911
32957
|
case "assistant": {
|
|
32912
32958
|
const contentWidth = assistantContentWidth(termWidth);
|
|
32913
32959
|
const { steps, stripped } = nextSteps;
|
|
32914
|
-
const hasNext = steps.length > 0 && !openTodos;
|
|
32960
|
+
const hasNext = steps.length > 0 && !openTodos && isFinalTurnEntry;
|
|
32915
32961
|
return /* @__PURE__ */ jsxs68(Box, { flexDirection: "column", children: [
|
|
32916
32962
|
/* @__PURE__ */ jsxs68(
|
|
32917
32963
|
Box,
|
|
@@ -33011,15 +33057,15 @@ var Entry = React8.memo(function Entry2({
|
|
|
33011
33057
|
const outObj = outJson && typeof outJson === "object" ? outJson : void 0;
|
|
33012
33058
|
const created = name === "write" && (outObj?.["created"] === true || /^[^\n]*\bcreated=true\b/.test(outputForFormatting));
|
|
33013
33059
|
const verb = created ? "Write" : "Update";
|
|
33014
|
-
const
|
|
33060
|
+
const path10 = stringOf(inputObj?.["path"]) ?? stringOf(outObj?.["path"]);
|
|
33015
33061
|
const agg = multiDiffs2 ? summarizeMultiFileDiffs(multiDiffs2) : void 0;
|
|
33016
|
-
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";
|
|
33017
33063
|
return {
|
|
33018
33064
|
verb,
|
|
33019
33065
|
target,
|
|
33020
33066
|
added: agg ? agg.added : diff2?.added ?? 0,
|
|
33021
33067
|
removed: agg ? agg.removed : diff2?.removed ?? 0,
|
|
33022
|
-
lang: langFromPath(multiDiffs2 ? "" :
|
|
33068
|
+
lang: langFromPath(multiDiffs2 ? "" : path10 ?? "")
|
|
33023
33069
|
};
|
|
33024
33070
|
})();
|
|
33025
33071
|
return {
|
|
@@ -33103,14 +33149,14 @@ var Entry = React8.memo(function Entry2({
|
|
|
33103
33149
|
]
|
|
33104
33150
|
}
|
|
33105
33151
|
),
|
|
33106
|
-
/* @__PURE__ */ jsx70(
|
|
33152
|
+
showSageMemoryInject !== false ? /* @__PURE__ */ jsx70(
|
|
33107
33153
|
SageMemoryBlock,
|
|
33108
33154
|
{
|
|
33109
33155
|
sageLines,
|
|
33110
33156
|
toolName: entry.name,
|
|
33111
33157
|
stats: entry.sageStats
|
|
33112
33158
|
}
|
|
33113
|
-
)
|
|
33159
|
+
) : null
|
|
33114
33160
|
] });
|
|
33115
33161
|
}
|
|
33116
33162
|
const toolContentWidth = Math.max(20, termWidth - 2);
|
|
@@ -33190,7 +33236,7 @@ var Entry = React8.memo(function Entry2({
|
|
|
33190
33236
|
]
|
|
33191
33237
|
}
|
|
33192
33238
|
),
|
|
33193
|
-
/* @__PURE__ */ jsx70(SageMemoryBlock, { sageLines, toolName: entry.name, stats: entry.sageStats })
|
|
33239
|
+
showSageMemoryInject !== false ? /* @__PURE__ */ jsx70(SageMemoryBlock, { sageLines, toolName: entry.name, stats: entry.sageStats }) : null
|
|
33194
33240
|
] });
|
|
33195
33241
|
}
|
|
33196
33242
|
case "memory-activation": {
|
|
@@ -33467,7 +33513,8 @@ var History = memo2(function History2({
|
|
|
33467
33513
|
autonomyMode,
|
|
33468
33514
|
multiDiffSummaryThreshold,
|
|
33469
33515
|
todos,
|
|
33470
|
-
showModelReasoning
|
|
33516
|
+
showModelReasoning,
|
|
33517
|
+
showSageMemoryInject
|
|
33471
33518
|
}) {
|
|
33472
33519
|
const { stdout } = useStdout();
|
|
33473
33520
|
const [termSize, setTermSize] = useState39({
|
|
@@ -33542,7 +33589,8 @@ var History = memo2(function History2({
|
|
|
33542
33589
|
autonomyMode,
|
|
33543
33590
|
multiDiffSummaryThreshold,
|
|
33544
33591
|
todos,
|
|
33545
|
-
showModelReasoning
|
|
33592
|
+
showModelReasoning,
|
|
33593
|
+
showSageMemoryInject
|
|
33546
33594
|
}
|
|
33547
33595
|
) }, entry.id) }, staticKey),
|
|
33548
33596
|
/* @__PURE__ */ jsx71(Box, { flexGrow: 1 })
|
|
@@ -33692,6 +33740,7 @@ var ScrollableHistory = memo3(function ScrollableHistory2({
|
|
|
33692
33740
|
multiDiffSummaryThreshold,
|
|
33693
33741
|
todos,
|
|
33694
33742
|
showModelReasoning,
|
|
33743
|
+
showSageMemoryInject,
|
|
33695
33744
|
layoutStore,
|
|
33696
33745
|
copiedEntryId,
|
|
33697
33746
|
onRequestOlderEntries
|
|
@@ -33734,7 +33783,8 @@ var ScrollableHistory = memo3(function ScrollableHistory2({
|
|
|
33734
33783
|
const preparedGroupIdsRef = useRef37(null);
|
|
33735
33784
|
const preparedEstimateWidthRef = useRef37(null);
|
|
33736
33785
|
const reasoningKey = showModelReasoning === false ? "|r0" : "";
|
|
33737
|
-
const
|
|
33786
|
+
const sageKey = showSageMemoryInject === false ? "|s0" : "";
|
|
33787
|
+
const cacheKey = (layoutStore ? `${groupIdsKey}|w${termWidth}` : groupIdsKey) + reasoningKey + sageKey;
|
|
33738
33788
|
if (preparedGroupIdsRef.current !== cacheKey || preparedEstimateWidthRef.current !== termWidth) {
|
|
33739
33789
|
const widthChanged = preparedEstimateWidthRef.current !== null && preparedEstimateWidthRef.current !== termWidth;
|
|
33740
33790
|
if (widthChanged) {
|
|
@@ -33761,7 +33811,7 @@ var ScrollableHistory = memo3(function ScrollableHistory2({
|
|
|
33761
33811
|
}
|
|
33762
33812
|
if (stored.kind === "measured") measuredGroupIdsRef.current.add(id);
|
|
33763
33813
|
} else {
|
|
33764
|
-
const estimatedRows = estimateRenderGroupRows(group, termWidth);
|
|
33814
|
+
const estimatedRows = estimateRenderGroupRows(group, termWidth, showSageMemoryInject);
|
|
33765
33815
|
heightCache.record(id, estimatedRows);
|
|
33766
33816
|
const kind = group.type === "tool-group" ? "tool-group" : group.entry.kind;
|
|
33767
33817
|
const text = group.type === "tool-group" ? group.data.name : group.entry.text ?? "";
|
|
@@ -33780,7 +33830,10 @@ var ScrollableHistory = memo3(function ScrollableHistory2({
|
|
|
33780
33830
|
const id = renderGroupId(group);
|
|
33781
33831
|
const hidden = group.type !== "tool-group" && group.entry.kind === "thinking" && showModelReasoning === false;
|
|
33782
33832
|
if (hidden) hiddenIds.add(id);
|
|
33783
|
-
return [
|
|
33833
|
+
return [
|
|
33834
|
+
id,
|
|
33835
|
+
hidden ? 0 : estimateRenderGroupRows(group, termWidth, showSageMemoryInject)
|
|
33836
|
+
];
|
|
33784
33837
|
})
|
|
33785
33838
|
);
|
|
33786
33839
|
heightCache.recordMany(
|
|
@@ -33912,6 +33965,19 @@ var ScrollableHistory = memo3(function ScrollableHistory2({
|
|
|
33912
33965
|
const clip2 = effectiveAnchor?.clip ?? 0;
|
|
33913
33966
|
planStartIdxRef.current = plan.startIdx;
|
|
33914
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
|
+
});
|
|
33915
33981
|
const offsetFromBottom = scrolled ? Math.max(0, maxTopRow(geometry) - anchorTopRow(geometry, effectiveAnchor)) : 0;
|
|
33916
33982
|
const copyRegistry = buildCopyRegistry({
|
|
33917
33983
|
renderGroups,
|
|
@@ -34029,7 +34095,8 @@ var ScrollableHistory = memo3(function ScrollableHistory2({
|
|
|
34029
34095
|
autonomyMode,
|
|
34030
34096
|
multiDiffSummaryThreshold,
|
|
34031
34097
|
todos,
|
|
34032
|
-
showModelReasoning
|
|
34098
|
+
showModelReasoning,
|
|
34099
|
+
showSageMemoryInject
|
|
34033
34100
|
}
|
|
34034
34101
|
)
|
|
34035
34102
|
}
|
|
@@ -34525,6 +34592,7 @@ function AppView({ host, runtime }) {
|
|
|
34525
34592
|
multiDiffSummaryThreshold: state.settingsPicker.multiDiffSummaryThreshold,
|
|
34526
34593
|
todos: liveTodos,
|
|
34527
34594
|
showModelReasoning: state.settingsPicker.open ? state.settingsPicker.showModelReasoning : liveSettings?.showModelReasoning ?? true,
|
|
34595
|
+
showSageMemoryInject: state.settingsPicker.open ? state.settingsPicker.showSageMemoryInject : liveSettings?.showSageMemoryInject ?? false,
|
|
34528
34596
|
layoutStore,
|
|
34529
34597
|
copiedEntryId: state.copiedEntryId,
|
|
34530
34598
|
onRequestOlderEntries: runtime.onRequestOlderEntries
|
|
@@ -34676,6 +34744,8 @@ function AppView({ host, runtime }) {
|
|
|
34676
34744
|
breakerAutoKillResetMs: state.settingsPicker.breakerAutoKillResetMs,
|
|
34677
34745
|
showModelReasoning: state.settingsPicker.showModelReasoning,
|
|
34678
34746
|
showAgentSwarmPanel: state.settingsPicker.showAgentSwarmPanel,
|
|
34747
|
+
showSageMemoryInject: state.settingsPicker.showSageMemoryInject,
|
|
34748
|
+
sageMemoryInjectThreshold: state.settingsPicker.sageMemoryInjectThreshold,
|
|
34679
34749
|
readSymbols: state.settingsPicker.readSymbols,
|
|
34680
34750
|
filter: state.settingsPicker.filter,
|
|
34681
34751
|
hint: state.settingsPicker.hint
|
|
@@ -35069,7 +35139,10 @@ function createRunBlocksController(host) {
|
|
|
35069
35139
|
}
|
|
35070
35140
|
dispatch({ type: "streamReset" });
|
|
35071
35141
|
if (result.status === "done" && result.finalText?.trim() && !refs.assistantCommitted.current) {
|
|
35072
|
-
dispatch({
|
|
35142
|
+
dispatch({
|
|
35143
|
+
type: "addEntry",
|
|
35144
|
+
entry: { kind: "assistant", text: result.finalText, final: true }
|
|
35145
|
+
});
|
|
35073
35146
|
}
|
|
35074
35147
|
if (result.status === "aborted") {
|
|
35075
35148
|
const reason = result.abortReason ? `Aborted (${result.abortReason}).` : "Aborted.";
|
|
@@ -36400,6 +36473,8 @@ function routeSettingsOverlayKey(host, input, key, isEnter) {
|
|
|
36400
36473
|
breakerAutoKillResetMs: config.breakerAutoKillResetMs ?? 6e4,
|
|
36401
36474
|
showModelReasoning: config.showModelReasoning ?? true,
|
|
36402
36475
|
showAgentSwarmPanel: config.showAgentSwarmPanel ?? true,
|
|
36476
|
+
showSageMemoryInject: config.showSageMemoryInject ?? false,
|
|
36477
|
+
sageMemoryInjectThreshold: config.sageMemoryInjectThreshold ?? 0.85,
|
|
36403
36478
|
readSymbols: config.readSymbols ?? false
|
|
36404
36479
|
});
|
|
36405
36480
|
return true;
|
|
@@ -37176,8 +37251,8 @@ function App(props) {
|
|
|
37176
37251
|
submitRef
|
|
37177
37252
|
} = useAppRuntimeRefs(attachments, state);
|
|
37178
37253
|
const projectName = React10.useMemo(() => {
|
|
37179
|
-
const base =
|
|
37180
|
-
return base && base !==
|
|
37254
|
+
const base = path7.basename(projectRoot);
|
|
37255
|
+
return base && base !== path7.sep ? base : void 0;
|
|
37181
37256
|
}, [projectRoot]);
|
|
37182
37257
|
const workingDirChip = useWorkingDirChip(agent.ctx, projectRoot);
|
|
37183
37258
|
const {
|
|
@@ -37913,9 +37988,9 @@ var BRACKETED_PASTE_OFF = "\x1B[?2004l";
|
|
|
37913
37988
|
|
|
37914
37989
|
// src/run-tui-client-registration.ts
|
|
37915
37990
|
import { randomUUID } from "node:crypto";
|
|
37916
|
-
import * as
|
|
37991
|
+
import * as path8 from "node:path";
|
|
37917
37992
|
import { RemoteMailbox, resolveProjectDir } from "@wrongstack/core/coordination";
|
|
37918
|
-
import { wstackGlobalRoot
|
|
37993
|
+
import { wstackGlobalRoot } from "@wrongstack/core/utils";
|
|
37919
37994
|
import {
|
|
37920
37995
|
createHqPublisherFromEnv,
|
|
37921
37996
|
startBrainTelemetryBridge,
|
|
@@ -37941,7 +38016,7 @@ function createRunTuiClientRegistration(opts) {
|
|
|
37941
38016
|
if (!opts.projectRoot) return null;
|
|
37942
38017
|
const generation = ++registrationGeneration;
|
|
37943
38018
|
try {
|
|
37944
|
-
const projectDir = resolveProjectDir(opts.projectRoot,
|
|
38019
|
+
const projectDir = resolveProjectDir(opts.projectRoot, wstackGlobalRoot());
|
|
37945
38020
|
const mailbox = new RemoteMailbox({ projectDir, events: opts.events });
|
|
37946
38021
|
const clientId = `tui@${randomUUID().slice(0, 8)}`;
|
|
37947
38022
|
await mailbox.initialize();
|
|
@@ -38000,7 +38075,7 @@ function createRunTuiClientRegistration(opts) {
|
|
|
38000
38075
|
await mailbox.registerClient({
|
|
38001
38076
|
clientId,
|
|
38002
38077
|
sessionId: opts.getSessionId?.() ?? opts.projectRoot,
|
|
38003
|
-
name: `TUI [${
|
|
38078
|
+
name: `TUI [${path8.basename(opts.projectRoot)}]`,
|
|
38004
38079
|
source: "tui",
|
|
38005
38080
|
pid: process.pid
|
|
38006
38081
|
});
|
|
@@ -38015,7 +38090,7 @@ function createRunTuiClientRegistration(opts) {
|
|
|
38015
38090
|
tuiHqPublisher = createHqPublisherFromEnv({
|
|
38016
38091
|
clientKind: "tui",
|
|
38017
38092
|
projectRoot: opts.projectRoot,
|
|
38018
|
-
projectName:
|
|
38093
|
+
projectName: path8.basename(opts.projectRoot),
|
|
38019
38094
|
appConfig: opts.appConfig
|
|
38020
38095
|
});
|
|
38021
38096
|
tuiHqPublisher?.connect();
|
|
@@ -38028,7 +38103,7 @@ function createRunTuiClientRegistration(opts) {
|
|
|
38028
38103
|
events: opts.events,
|
|
38029
38104
|
sessionId: tuiSessionId,
|
|
38030
38105
|
projectRoot: opts.projectRoot,
|
|
38031
|
-
projectName:
|
|
38106
|
+
projectName: path8.basename(opts.projectRoot)
|
|
38032
38107
|
})
|
|
38033
38108
|
);
|
|
38034
38109
|
} catch {
|
|
@@ -38153,7 +38228,7 @@ function createRunTuiClientRegistration(opts) {
|
|
|
38153
38228
|
}
|
|
38154
38229
|
|
|
38155
38230
|
// src/run-tui-title-controller.ts
|
|
38156
|
-
import * as
|
|
38231
|
+
import * as path9 from "node:path";
|
|
38157
38232
|
|
|
38158
38233
|
// src/terminal-title.ts
|
|
38159
38234
|
var SPINNER = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
|
|
@@ -38233,7 +38308,7 @@ function createRunTuiTitleController(opts) {
|
|
|
38233
38308
|
stdout: opts.stdout,
|
|
38234
38309
|
events: opts.events,
|
|
38235
38310
|
model: currentModel,
|
|
38236
|
-
appName: opts.projectRoot ?
|
|
38311
|
+
appName: opts.projectRoot ? path9.basename(opts.projectRoot) : void 0
|
|
38237
38312
|
});
|
|
38238
38313
|
};
|
|
38239
38314
|
const stop = () => {
|