@markusylisiurunen/tau 0.1.38 → 0.1.40
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.js +164 -85
- package/dist/app.js.map +1 -1
- package/dist/tools/bash.js +12 -6
- package/dist/tools/bash.js.map +1 -1
- package/dist/tools/registry.js.map +1 -1
- package/dist/ui/bash_execution.js +160 -95
- package/dist/ui/bash_execution.js.map +1 -1
- package/dist/ui/chat_container.js +63 -38
- package/dist/ui/chat_container.js.map +1 -1
- package/dist/ui/chat_message_model.js +57 -0
- package/dist/ui/chat_message_model.js.map +1 -0
- package/dist/ui/components/header_line.js +17 -0
- package/dist/ui/components/header_line.js.map +1 -0
- package/dist/ui/components/one_line_segments.js +22 -2
- package/dist/ui/components/one_line_segments.js.map +1 -1
- package/dist/ui/custom_editor.js +126 -1
- package/dist/ui/custom_editor.js.map +1 -1
- package/dist/ui/file_execution.js +204 -151
- package/dist/ui/file_execution.js.map +1 -1
- package/dist/ui/footer.js +7 -31
- package/dist/ui/footer.js.map +1 -1
- package/dist/ui/restricted_execution.js +224 -194
- package/dist/ui/restricted_execution.js.map +1 -1
- package/dist/ui/task_execution.js +90 -80
- package/dist/ui/task_execution.js.map +1 -1
- package/dist/ui/tool_output_layout.js +75 -0
- package/dist/ui/tool_output_layout.js.map +1 -0
- package/dist/ui/tool_output_preview.js +26 -0
- package/dist/ui/tool_output_preview.js.map +1 -0
- package/dist/version.js +1 -1
- package/package.json +2 -1
package/dist/app.js
CHANGED
|
@@ -20,22 +20,16 @@ import { ToolRegistry } from "./tools/registry.js";
|
|
|
20
20
|
import { createTaskToolDefinition } from "./tools/task.js";
|
|
21
21
|
import { createWriteToolDefinition } from "./tools/write.js";
|
|
22
22
|
import { REASONING_LEVELS, } from "./types.js";
|
|
23
|
-
import {
|
|
24
|
-
import { AssistantMessageComponent } from "./ui/assistant_message.js";
|
|
25
|
-
import { renderBashAborted, renderBashBlocked, renderBashExecution, renderBashRunning, } from "./ui/bash_execution.js";
|
|
23
|
+
import { buildBashAbortedView, buildBashBlockedView, buildBashExecutionView, buildBashRunningView, } from "./ui/bash_execution.js";
|
|
26
24
|
import { ChatContainerComponent } from "./ui/chat_container.js";
|
|
27
25
|
import { CustomEditor } from "./ui/custom_editor.js";
|
|
28
|
-
import {
|
|
26
|
+
import { buildEditBlockedView, buildEditSuccessView, buildWriteBlockedView, buildWriteSuccessView, } from "./ui/file_execution.js";
|
|
29
27
|
import { FooterComponent } from "./ui/footer.js";
|
|
30
28
|
import { QueuedMessagesComponent } from "./ui/queued_messages.js";
|
|
31
|
-
import {
|
|
32
|
-
import { SessionDividerComponent } from "./ui/session_divider.js";
|
|
33
|
-
import { SessionSummaryComponent } from "./ui/session_summary.js";
|
|
29
|
+
import { buildGrepBlockedView, buildGrepFinishedView, buildGrepRunningView, buildListBlockedView, buildListSuccessView, buildReadBlockedView, buildReadSuccessView, } from "./ui/restricted_execution.js";
|
|
34
30
|
import { getFileAutocompleteToken, SlashAutocompleteProvider } from "./ui/slash_autocomplete.js";
|
|
35
|
-
import {
|
|
36
|
-
import { renderTaskBlocked, renderTaskFinished, renderTaskRunning } from "./ui/task_execution.js";
|
|
31
|
+
import { buildTaskBlockedView, buildTaskFinishedView, buildTaskRunningView, } from "./ui/task_execution.js";
|
|
37
32
|
import { createUiTheme } from "./ui/theme.js";
|
|
38
|
-
import { UserMessageComponent } from "./ui/user_message.js";
|
|
39
33
|
import { buildBaseSystemPrompt, buildEnvironmentTag, buildProjectContextBlock, buildSkillsIndexBlock, findAgentsFilesFromCwdToHome, formatRiskLevelChangeNotice, } from "./utils/context.js";
|
|
40
34
|
import { formatHistoryForCompression } from "./utils/fork.js";
|
|
41
35
|
import { formatAdaptiveNumber, formatCwd, formatTokenWindow } from "./utils/format.js";
|
|
@@ -58,7 +52,6 @@ export class ChatApp {
|
|
|
58
52
|
repoRoot;
|
|
59
53
|
initialUserMessage;
|
|
60
54
|
config;
|
|
61
|
-
assistantComponents = [];
|
|
62
55
|
engine;
|
|
63
56
|
runningBashComponents = new Map();
|
|
64
57
|
runningTaskComponents = new Map();
|
|
@@ -142,11 +135,11 @@ export class ChatApp {
|
|
|
142
135
|
});
|
|
143
136
|
this.uiTheme = createUiTheme("ansi");
|
|
144
137
|
this.ui = new TUI(createAppTerminal());
|
|
145
|
-
this.chatContainer = new ChatContainerComponent();
|
|
138
|
+
this.chatContainer = new ChatContainerComponent(this.uiTheme);
|
|
146
139
|
this.chatContainer.setCompactToolUi(this.compactToolUi);
|
|
147
140
|
this.footer = new FooterComponent(this.uiTheme, this.ui);
|
|
148
141
|
this.queuedMessages = new QueuedMessagesComponent(this.uiTheme, this.queuedUserMessages);
|
|
149
|
-
this.editor = new CustomEditor(this.uiTheme
|
|
142
|
+
this.editor = new CustomEditor(this.uiTheme);
|
|
150
143
|
this.setupUI();
|
|
151
144
|
this.setupEditor();
|
|
152
145
|
}
|
|
@@ -156,7 +149,12 @@ export class ChatApp {
|
|
|
156
149
|
this.ui.addChild(this.queuedMessages);
|
|
157
150
|
this.ui.addChild(this.editor);
|
|
158
151
|
this.ui.addChild(this.footer);
|
|
159
|
-
this.chatContainer.addMessage(
|
|
152
|
+
this.chatContainer.addMessage({
|
|
153
|
+
type: "app_intro",
|
|
154
|
+
appName: "tau",
|
|
155
|
+
version: APP_VERSION,
|
|
156
|
+
helpText: buildHelpText(this.agentsFiles, this.skills),
|
|
157
|
+
});
|
|
160
158
|
this.ui.setFocus(this.editor);
|
|
161
159
|
this.updateFooter();
|
|
162
160
|
this.updateEditorBorderColor();
|
|
@@ -244,13 +242,11 @@ export class ChatApp {
|
|
|
244
242
|
const cwd = formatCwd(process.cwd());
|
|
245
243
|
const personaName = this.currentPersona.label || this.currentPersona.id;
|
|
246
244
|
this.footer.setStatus({
|
|
247
|
-
cwd,
|
|
248
245
|
contextUsage,
|
|
249
246
|
sessionCost,
|
|
250
|
-
personaLabel: personaName,
|
|
251
|
-
reasoningLabel,
|
|
252
247
|
riskLevel: this.riskLevel,
|
|
253
248
|
});
|
|
249
|
+
this.updateEditorHeader(cwd, personaName, reasoningLabel);
|
|
254
250
|
this.ui.requestRender();
|
|
255
251
|
}
|
|
256
252
|
updateEditorBorderColor() {
|
|
@@ -264,19 +260,30 @@ export class ChatApp {
|
|
|
264
260
|
else {
|
|
265
261
|
this.editor.borderColor = this.uiTheme.editorBorderForReasoning(this.currentPersona.settings.reasoning);
|
|
266
262
|
}
|
|
263
|
+
this.updateEditorHeader();
|
|
267
264
|
this.ui.requestRender();
|
|
268
265
|
}
|
|
266
|
+
updateEditorHeader(cwd = formatCwd(process.cwd()), personaName = this.currentPersona.label || this.currentPersona.id, reasoningLabel = this.currentPersona.settings.reasoning ?? "none") {
|
|
267
|
+
if (this.isBashMode) {
|
|
268
|
+
this.editor.setHeader("bash", "", { leftStyle: this.editor.borderColor });
|
|
269
|
+
return;
|
|
270
|
+
}
|
|
271
|
+
if (this.isMemoryMode) {
|
|
272
|
+
this.editor.setHeader("memoize", "", { leftStyle: this.editor.borderColor });
|
|
273
|
+
return;
|
|
274
|
+
}
|
|
275
|
+
this.editor.setHeader(cwd, `${personaName} (${reasoningLabel})`);
|
|
276
|
+
}
|
|
269
277
|
addSystemMessage(text, kind) {
|
|
270
|
-
this.chatContainer.addMessage(
|
|
278
|
+
this.chatContainer.addMessage({ type: "system", text, kind });
|
|
271
279
|
this.ui.requestRender();
|
|
272
280
|
}
|
|
273
281
|
addUserMessage(text, opts) {
|
|
274
|
-
this.chatContainer.addMessage(
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
this.assistantComponents.push(component);
|
|
282
|
+
this.chatContainer.addMessage({
|
|
283
|
+
type: "user",
|
|
284
|
+
text,
|
|
285
|
+
isMemoryMode: opts?.isMemoryMode,
|
|
286
|
+
});
|
|
280
287
|
this.ui.requestRender();
|
|
281
288
|
}
|
|
282
289
|
// Context & Cost Tracking -----------------------------------------------------------------------
|
|
@@ -286,13 +293,13 @@ export class ChatApp {
|
|
|
286
293
|
? this.getContextWindowForLastTurn(last)
|
|
287
294
|
: this.currentPersona.model.contextWindow;
|
|
288
295
|
const { input, read, write, output } = this.getSessionTotals();
|
|
289
|
-
const stats =
|
|
296
|
+
const stats = `↑${formatTokenWindow(input)} ↓${formatTokenWindow(output)} cache ${formatTokenWindow(read)}/${formatTokenWindow(write)}`;
|
|
290
297
|
const promptTokensSent = last
|
|
291
298
|
? (last.usage?.input ?? 0) + (last.usage?.cacheRead ?? 0) + (last.usage?.cacheWrite ?? 0)
|
|
292
299
|
: 0;
|
|
293
300
|
const percent = windowTokens > 0 ? (promptTokensSent / windowTokens) * 100 : 0;
|
|
294
301
|
const percentStr = `${formatAdaptiveNumber(percent, 1, 3)}%`;
|
|
295
|
-
return `${stats} ${percentStr}/${formatTokenWindow(windowTokens)}`;
|
|
302
|
+
return `${stats} · ${percentStr}/${formatTokenWindow(windowTokens)}`;
|
|
296
303
|
}
|
|
297
304
|
getSessionCostString() {
|
|
298
305
|
let total = 0;
|
|
@@ -442,9 +449,6 @@ export class ChatApp {
|
|
|
442
449
|
// User Actions ----------------------------------------------------------------------------------
|
|
443
450
|
toggleThinkingVisibility() {
|
|
444
451
|
this.showThinking = !this.showThinking;
|
|
445
|
-
this.assistantComponents.forEach((c) => {
|
|
446
|
-
c.setThinkingVisibility(this.showThinking);
|
|
447
|
-
});
|
|
448
452
|
this.chatContainer.setThinkingVisibility(this.showThinking);
|
|
449
453
|
const message = this.showThinking
|
|
450
454
|
? "thoughts visible (ctrl+t to hide)"
|
|
@@ -699,13 +703,12 @@ export class ChatApp {
|
|
|
699
703
|
}
|
|
700
704
|
clearSession() {
|
|
701
705
|
this.engine.reset();
|
|
702
|
-
this.assistantComponents = [];
|
|
703
706
|
this.runningBashComponents.clear();
|
|
704
707
|
this.runningTaskComponents.clear();
|
|
705
708
|
this.taskEvents.clear();
|
|
706
709
|
this.subagentCostTotal = 0;
|
|
707
710
|
this.expandedFilesInCurrentPrompt.clear();
|
|
708
|
-
this.chatContainer.addMessage(
|
|
711
|
+
this.chatContainer.addMessage({ type: "session_divider", label: "new session" });
|
|
709
712
|
this.isBashMode = false;
|
|
710
713
|
this.isMemoryMode = false;
|
|
711
714
|
this.previousSessionSummary = undefined;
|
|
@@ -835,14 +838,16 @@ Write plain prose, no formatting. Be thorough enough that the reader can resume
|
|
|
835
838
|
this.previousSessionSummary = previousSessionContext;
|
|
836
839
|
// Reset the session state but preserve history with divider and summary
|
|
837
840
|
this.engine.reset();
|
|
838
|
-
this.assistantComponents = [];
|
|
839
841
|
this.runningBashComponents.clear();
|
|
840
842
|
this.runningTaskComponents.clear();
|
|
841
843
|
this.taskEvents.clear();
|
|
842
844
|
this.subagentCostTotal = 0;
|
|
843
845
|
this.expandedFilesInCurrentPrompt.clear();
|
|
844
|
-
this.chatContainer.addMessage(
|
|
845
|
-
this.chatContainer.addMessage(
|
|
846
|
+
this.chatContainer.addMessage({ type: "session_divider", label: "new session" });
|
|
847
|
+
this.chatContainer.addMessage({
|
|
848
|
+
type: "session_summary",
|
|
849
|
+
summary: this.previousSessionSummary,
|
|
850
|
+
});
|
|
846
851
|
this.isBashMode = false;
|
|
847
852
|
this.isMemoryMode = false;
|
|
848
853
|
// Rebuild environment tag and system prompt with the new summary and current risk level
|
|
@@ -1045,18 +1050,16 @@ Write plain prose, no formatting. Be thorough enough that the reader can resume
|
|
|
1045
1050
|
if (currentAssistant)
|
|
1046
1051
|
return currentAssistant;
|
|
1047
1052
|
currentAssistant = {
|
|
1048
|
-
component: new AssistantMessageComponent(this.uiTheme, undefined, this.showThinking),
|
|
1049
1053
|
inserted: false,
|
|
1054
|
+
model: { type: "assistant_partial", text: "", thinking: "" },
|
|
1050
1055
|
};
|
|
1051
1056
|
return currentAssistant;
|
|
1052
1057
|
};
|
|
1053
|
-
const ensureAssistantInserted = () => {
|
|
1054
|
-
const state = ensureCurrentAssistant();
|
|
1058
|
+
const ensureAssistantInserted = (state) => {
|
|
1055
1059
|
if (state.inserted)
|
|
1056
1060
|
return;
|
|
1057
1061
|
state.inserted = true;
|
|
1058
|
-
this.
|
|
1059
|
-
state.component.setThinkingVisibility(this.showThinking);
|
|
1062
|
+
state.id = this.chatContainer.addMessage(state.model);
|
|
1060
1063
|
};
|
|
1061
1064
|
for await (const event of this.engine.processTurn(this.currentTurnAbort.signal)) {
|
|
1062
1065
|
if (this.currentTurnAbort.signal.aborted)
|
|
@@ -1064,34 +1067,39 @@ Write plain prose, no formatting. Be thorough enough that the reader can resume
|
|
|
1064
1067
|
switch (event.type) {
|
|
1065
1068
|
case "assistant_start":
|
|
1066
1069
|
currentAssistant = {
|
|
1067
|
-
component: new AssistantMessageComponent(this.uiTheme, undefined, this.showThinking),
|
|
1068
1070
|
inserted: false,
|
|
1071
|
+
model: { type: "assistant_partial", text: "", thinking: "" },
|
|
1069
1072
|
};
|
|
1070
1073
|
break;
|
|
1071
1074
|
case "assistant_partial": {
|
|
1072
1075
|
const state = ensureCurrentAssistant();
|
|
1073
1076
|
const { snapshot } = event;
|
|
1077
|
+
const model = {
|
|
1078
|
+
type: "assistant_partial",
|
|
1079
|
+
text: snapshot.hasTextStarted ? snapshot.text : "",
|
|
1080
|
+
thinking: snapshot.thinking,
|
|
1081
|
+
};
|
|
1082
|
+
state.model = model;
|
|
1074
1083
|
const shouldInsert = snapshot.hasTextStarted || (this.showThinking && snapshot.hasAnyThinking);
|
|
1075
1084
|
if (shouldInsert && !state.inserted) {
|
|
1076
|
-
ensureAssistantInserted();
|
|
1085
|
+
ensureAssistantInserted(state);
|
|
1077
1086
|
}
|
|
1078
|
-
if (state.inserted) {
|
|
1079
|
-
|
|
1080
|
-
const wasVisible = state.component.hasVisibleText;
|
|
1081
|
-
state.component.updatePartial(snapshot.hasTextStarted ? snapshot.text : "", snapshot.thinking);
|
|
1082
|
-
// If component became visible (e.g. text started after thoughts were hidden),
|
|
1083
|
-
// rebuild the container to show it
|
|
1084
|
-
if (!wasVisible && state.component.hasVisibleText) {
|
|
1085
|
-
this.chatContainer.rebuild();
|
|
1086
|
-
}
|
|
1087
|
+
if (state.inserted && state.id) {
|
|
1088
|
+
this.chatContainer.updateMessage(state.id, model);
|
|
1087
1089
|
this.ui.requestRender();
|
|
1088
1090
|
}
|
|
1089
1091
|
break;
|
|
1090
1092
|
}
|
|
1091
1093
|
case "assistant_final": {
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1094
|
+
const state = ensureCurrentAssistant();
|
|
1095
|
+
const model = { type: "assistant", message: event.message };
|
|
1096
|
+
state.model = model;
|
|
1097
|
+
if (!state.inserted) {
|
|
1098
|
+
ensureAssistantInserted(state);
|
|
1099
|
+
}
|
|
1100
|
+
if (state.id) {
|
|
1101
|
+
this.chatContainer.updateMessage(state.id, model);
|
|
1102
|
+
}
|
|
1095
1103
|
this.updateFooter();
|
|
1096
1104
|
this.ui.requestRender();
|
|
1097
1105
|
currentAssistant = undefined;
|
|
@@ -1100,7 +1108,10 @@ Write plain prose, no formatting. Be thorough enough that the reader can resume
|
|
|
1100
1108
|
case "tool_ui": {
|
|
1101
1109
|
const uiEvent = event.uiEvent;
|
|
1102
1110
|
if (uiEvent.type === "bash_started") {
|
|
1103
|
-
this.chatContainer.
|
|
1111
|
+
this.chatContainer.addMessage({
|
|
1112
|
+
type: "tool",
|
|
1113
|
+
view: buildBashRunningView(this.uiTheme, uiEvent.command),
|
|
1114
|
+
}, uiEvent.toolCallId);
|
|
1104
1115
|
this.runningBashComponents.set(uiEvent.toolCallId, {
|
|
1105
1116
|
command: uiEvent.command,
|
|
1106
1117
|
});
|
|
@@ -1108,7 +1119,10 @@ Write plain prose, no formatting. Be thorough enough that the reader can resume
|
|
|
1108
1119
|
}
|
|
1109
1120
|
else if (uiEvent.type === "bash_execution") {
|
|
1110
1121
|
const running = this.runningBashComponents.get(uiEvent.toolCallId);
|
|
1111
|
-
this.chatContainer.
|
|
1122
|
+
this.chatContainer.replaceMessage(uiEvent.toolCallId, {
|
|
1123
|
+
type: "tool",
|
|
1124
|
+
view: buildBashExecutionView(this.uiTheme, uiEvent.command, uiEvent.exitCode, uiEvent.truncationInfo, uiEvent.durationMs),
|
|
1125
|
+
});
|
|
1112
1126
|
if (running) {
|
|
1113
1127
|
this.runningBashComponents.delete(uiEvent.toolCallId);
|
|
1114
1128
|
}
|
|
@@ -1117,13 +1131,19 @@ Write plain prose, no formatting. Be thorough enough that the reader can resume
|
|
|
1117
1131
|
else if (uiEvent.type === "bash_blocked") {
|
|
1118
1132
|
if (uiEvent.toolCallId) {
|
|
1119
1133
|
const running = this.runningBashComponents.get(uiEvent.toolCallId);
|
|
1120
|
-
this.chatContainer.
|
|
1134
|
+
this.chatContainer.replaceMessage(uiEvent.toolCallId, {
|
|
1135
|
+
type: "tool",
|
|
1136
|
+
view: buildBashBlockedView(this.uiTheme, uiEvent.command, uiEvent.reason),
|
|
1137
|
+
});
|
|
1121
1138
|
if (running) {
|
|
1122
1139
|
this.runningBashComponents.delete(uiEvent.toolCallId);
|
|
1123
1140
|
}
|
|
1124
1141
|
}
|
|
1125
1142
|
else {
|
|
1126
|
-
this.chatContainer.
|
|
1143
|
+
this.chatContainer.addMessage({
|
|
1144
|
+
type: "tool",
|
|
1145
|
+
view: buildBashBlockedView(this.uiTheme, uiEvent.command, uiEvent.reason),
|
|
1146
|
+
});
|
|
1127
1147
|
}
|
|
1128
1148
|
this.ui.requestRender();
|
|
1129
1149
|
}
|
|
@@ -1133,10 +1153,13 @@ Write plain prose, no formatting. Be thorough enough that the reader can resume
|
|
|
1133
1153
|
}
|
|
1134
1154
|
const kind = uiEvent.kind ?? "task";
|
|
1135
1155
|
const subagentName = uiEvent.name.trim() || undefined;
|
|
1136
|
-
this.chatContainer.
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1156
|
+
this.chatContainer.addMessage({
|
|
1157
|
+
type: "tool",
|
|
1158
|
+
view: buildTaskRunningView(this.uiTheme, uiEvent.title, [], 0, 0, 0, {
|
|
1159
|
+
kind,
|
|
1160
|
+
subagentName,
|
|
1161
|
+
}),
|
|
1162
|
+
}, uiEvent.toolCallId);
|
|
1140
1163
|
this.runningTaskComponents.set(uiEvent.toolCallId, {
|
|
1141
1164
|
kind,
|
|
1142
1165
|
name: subagentName,
|
|
@@ -1165,14 +1188,20 @@ Write plain prose, no formatting. Be thorough enough that the reader can resume
|
|
|
1165
1188
|
running.turns = uiEvent.turns;
|
|
1166
1189
|
running.toolCalls = uiEvent.toolCalls;
|
|
1167
1190
|
}
|
|
1168
|
-
this.chatContainer.
|
|
1191
|
+
this.chatContainer.replaceMessage(uiEvent.toolCallId, {
|
|
1192
|
+
type: "tool",
|
|
1193
|
+
view: buildTaskRunningView(this.uiTheme, uiEvent.title, events, uiEvent.costTotal, uiEvent.turns, uiEvent.toolCalls, { kind, subagentName }),
|
|
1194
|
+
});
|
|
1169
1195
|
this.ui.requestRender();
|
|
1170
1196
|
}
|
|
1171
1197
|
else if (uiEvent.type === "task_finished") {
|
|
1172
1198
|
const running = this.runningTaskComponents.get(uiEvent.toolCallId);
|
|
1173
1199
|
const kind = uiEvent.kind ?? running?.kind ?? "task";
|
|
1174
1200
|
const subagentName = uiEvent.name.trim() || undefined;
|
|
1175
|
-
this.chatContainer.
|
|
1201
|
+
this.chatContainer.replaceMessage(uiEvent.toolCallId, {
|
|
1202
|
+
type: "tool",
|
|
1203
|
+
view: buildTaskFinishedView(this.uiTheme, uiEvent.title, uiEvent.costTotal, uiEvent.turns, uiEvent.toolCalls, uiEvent.status, uiEvent.finalOutput, { kind, subagentName }),
|
|
1204
|
+
});
|
|
1176
1205
|
this.runningTaskComponents.delete(uiEvent.toolCallId);
|
|
1177
1206
|
this.taskEvents.delete(uiEvent.toolCallId);
|
|
1178
1207
|
this.subagentCostTotal += uiEvent.costTotal;
|
|
@@ -1184,63 +1213,102 @@ Write plain prose, no formatting. Be thorough enough that the reader can resume
|
|
|
1184
1213
|
const kind = uiEvent.kind ?? running?.kind ?? "task";
|
|
1185
1214
|
const subagentName = uiEvent.name?.trim() || undefined;
|
|
1186
1215
|
if (running) {
|
|
1187
|
-
this.chatContainer.
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1216
|
+
this.chatContainer.replaceMessage(uiEvent.toolCallId, {
|
|
1217
|
+
type: "tool",
|
|
1218
|
+
view: buildTaskBlockedView(this.uiTheme, uiEvent.title, uiEvent.reason, {
|
|
1219
|
+
kind,
|
|
1220
|
+
subagentName,
|
|
1221
|
+
}),
|
|
1222
|
+
});
|
|
1191
1223
|
}
|
|
1192
1224
|
else {
|
|
1193
|
-
this.chatContainer.
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1225
|
+
this.chatContainer.addMessage({
|
|
1226
|
+
type: "tool",
|
|
1227
|
+
view: buildTaskBlockedView(this.uiTheme, uiEvent.title, uiEvent.reason, {
|
|
1228
|
+
kind,
|
|
1229
|
+
subagentName,
|
|
1230
|
+
}),
|
|
1231
|
+
}, uiEvent.toolCallId);
|
|
1197
1232
|
}
|
|
1198
1233
|
this.runningTaskComponents.delete(uiEvent.toolCallId);
|
|
1199
1234
|
this.taskEvents.delete(uiEvent.toolCallId);
|
|
1200
1235
|
this.ui.requestRender();
|
|
1201
1236
|
}
|
|
1202
1237
|
else if (uiEvent.type === "write_success") {
|
|
1203
|
-
this.chatContainer.
|
|
1238
|
+
this.chatContainer.addMessage({
|
|
1239
|
+
type: "tool",
|
|
1240
|
+
view: buildWriteSuccessView(this.uiTheme, uiEvent.path, uiEvent.bytes, uiEvent.lines, uiEvent.content),
|
|
1241
|
+
});
|
|
1204
1242
|
this.ui.requestRender();
|
|
1205
1243
|
}
|
|
1206
1244
|
else if (uiEvent.type === "write_blocked") {
|
|
1207
|
-
this.chatContainer.
|
|
1245
|
+
this.chatContainer.addMessage({
|
|
1246
|
+
type: "tool",
|
|
1247
|
+
view: buildWriteBlockedView(this.uiTheme, uiEvent.path, uiEvent.reason),
|
|
1248
|
+
});
|
|
1208
1249
|
this.ui.requestRender();
|
|
1209
1250
|
}
|
|
1210
1251
|
else if (uiEvent.type === "edit_success") {
|
|
1211
|
-
this.chatContainer.
|
|
1252
|
+
this.chatContainer.addMessage({
|
|
1253
|
+
type: "tool",
|
|
1254
|
+
view: buildEditSuccessView(this.uiTheme, uiEvent.path, uiEvent.oldLength, uiEvent.newLength, uiEvent.oldText, uiEvent.newText),
|
|
1255
|
+
});
|
|
1212
1256
|
this.ui.requestRender();
|
|
1213
1257
|
}
|
|
1214
1258
|
else if (uiEvent.type === "edit_blocked") {
|
|
1215
|
-
this.chatContainer.
|
|
1259
|
+
this.chatContainer.addMessage({
|
|
1260
|
+
type: "tool",
|
|
1261
|
+
view: buildEditBlockedView(this.uiTheme, uiEvent.path, uiEvent.reason),
|
|
1262
|
+
});
|
|
1216
1263
|
this.ui.requestRender();
|
|
1217
1264
|
}
|
|
1218
1265
|
else if (uiEvent.type === "read_success") {
|
|
1219
|
-
this.chatContainer.
|
|
1266
|
+
this.chatContainer.addMessage({
|
|
1267
|
+
type: "tool",
|
|
1268
|
+
view: buildReadSuccessView(this.uiTheme, uiEvent.path, uiEvent.startLine, uiEvent.endLine, uiEvent.content, uiEvent.modelTruncation),
|
|
1269
|
+
});
|
|
1220
1270
|
this.ui.requestRender();
|
|
1221
1271
|
}
|
|
1222
1272
|
else if (uiEvent.type === "read_blocked") {
|
|
1223
|
-
this.chatContainer.
|
|
1273
|
+
this.chatContainer.addMessage({
|
|
1274
|
+
type: "tool",
|
|
1275
|
+
view: buildReadBlockedView(this.uiTheme, uiEvent.path, uiEvent.reason),
|
|
1276
|
+
});
|
|
1224
1277
|
this.ui.requestRender();
|
|
1225
1278
|
}
|
|
1226
1279
|
else if (uiEvent.type === "list_success") {
|
|
1227
|
-
this.chatContainer.
|
|
1280
|
+
this.chatContainer.addMessage({
|
|
1281
|
+
type: "tool",
|
|
1282
|
+
view: buildListSuccessView(this.uiTheme, uiEvent.path, uiEvent.offset, uiEvent.limit, uiEvent.total, uiEvent.returned, uiEvent.entries),
|
|
1283
|
+
});
|
|
1228
1284
|
this.ui.requestRender();
|
|
1229
1285
|
}
|
|
1230
1286
|
else if (uiEvent.type === "list_blocked") {
|
|
1231
|
-
this.chatContainer.
|
|
1287
|
+
this.chatContainer.addMessage({
|
|
1288
|
+
type: "tool",
|
|
1289
|
+
view: buildListBlockedView(this.uiTheme, uiEvent.path, uiEvent.reason),
|
|
1290
|
+
});
|
|
1232
1291
|
this.ui.requestRender();
|
|
1233
1292
|
}
|
|
1234
1293
|
else if (uiEvent.type === "grep_started") {
|
|
1235
|
-
this.chatContainer.
|
|
1294
|
+
this.chatContainer.addMessage({
|
|
1295
|
+
type: "tool",
|
|
1296
|
+
view: buildGrepRunningView(this.uiTheme, uiEvent.pattern),
|
|
1297
|
+
}, uiEvent.toolCallId);
|
|
1236
1298
|
this.ui.requestRender();
|
|
1237
1299
|
}
|
|
1238
1300
|
else if (uiEvent.type === "grep_finished") {
|
|
1239
|
-
this.chatContainer.
|
|
1301
|
+
this.chatContainer.replaceMessage(uiEvent.toolCallId, {
|
|
1302
|
+
type: "tool",
|
|
1303
|
+
view: buildGrepFinishedView(this.uiTheme, uiEvent.pattern, uiEvent.status, uiEvent.exitCode, uiEvent.stdout, uiEvent.stderr, uiEvent.captureTruncated),
|
|
1304
|
+
});
|
|
1240
1305
|
this.ui.requestRender();
|
|
1241
1306
|
}
|
|
1242
1307
|
else if (uiEvent.type === "grep_blocked") {
|
|
1243
|
-
this.chatContainer.
|
|
1308
|
+
this.chatContainer.addMessage({
|
|
1309
|
+
type: "tool",
|
|
1310
|
+
view: buildGrepBlockedView(this.uiTheme, uiEvent.pattern, uiEvent.reason),
|
|
1311
|
+
}, uiEvent.toolCallId);
|
|
1244
1312
|
this.ui.requestRender();
|
|
1245
1313
|
}
|
|
1246
1314
|
break;
|
|
@@ -1262,11 +1330,17 @@ Write plain prose, no formatting. Be thorough enough that the reader can resume
|
|
|
1262
1330
|
const wasAborted = this.currentTurnAbort?.signal.aborted ?? false;
|
|
1263
1331
|
const reason = wasAborted ? "aborted" : "interrupted";
|
|
1264
1332
|
for (const [id, running] of this.runningBashComponents.entries()) {
|
|
1265
|
-
this.chatContainer.
|
|
1333
|
+
this.chatContainer.replaceMessage(id, {
|
|
1334
|
+
type: "tool",
|
|
1335
|
+
view: buildBashAbortedView(this.uiTheme, running.command, reason),
|
|
1336
|
+
});
|
|
1266
1337
|
}
|
|
1267
1338
|
const taskStatus = wasAborted ? "aborted" : "error";
|
|
1268
1339
|
for (const [id, running] of this.runningTaskComponents.entries()) {
|
|
1269
|
-
this.chatContainer.
|
|
1340
|
+
this.chatContainer.replaceMessage(id, {
|
|
1341
|
+
type: "tool",
|
|
1342
|
+
view: buildTaskFinishedView(this.uiTheme, running.title, running.costTotal, running.turns, running.toolCalls, taskStatus, reason, { kind: running.kind, subagentName: running.name }),
|
|
1343
|
+
});
|
|
1270
1344
|
}
|
|
1271
1345
|
this.footer.stop();
|
|
1272
1346
|
this.isStreaming = false;
|
|
@@ -1283,12 +1357,17 @@ Write plain prose, no formatting. Be thorough enough that the reader can resume
|
|
|
1283
1357
|
async runBashCommand(command, opts) {
|
|
1284
1358
|
this.isStreaming = true;
|
|
1285
1359
|
try {
|
|
1360
|
+
const startedAt = Date.now();
|
|
1286
1361
|
const { stdout, stderr, exitCode, truncated: captureTruncated, } = await executeBashTool(command, { cwd: opts?.cwd });
|
|
1362
|
+
const durationMs = Math.max(0, Date.now() - startedAt);
|
|
1287
1363
|
const truncationInfo = prepareBashOutput(stdout, stderr, captureTruncated, {
|
|
1288
1364
|
stdout: { maxLines: BASH_USER_MAX_STDOUT_LINES, maxTokens: BASH_USER_MAX_STDOUT_TOKENS },
|
|
1289
1365
|
stderr: { maxLines: BASH_USER_MAX_STDERR_LINES, maxTokens: BASH_USER_MAX_STDERR_TOKENS },
|
|
1290
1366
|
});
|
|
1291
|
-
this.chatContainer.addMessage(
|
|
1367
|
+
this.chatContainer.addMessage({
|
|
1368
|
+
type: "tool",
|
|
1369
|
+
view: buildBashExecutionView(this.uiTheme, command, exitCode, truncationInfo, durationMs, "you ran", 12, 12),
|
|
1370
|
+
});
|
|
1292
1371
|
this.engine.addUserText(formatBashUserMessageText({ command, truncationInfo }));
|
|
1293
1372
|
this.ui.requestRender();
|
|
1294
1373
|
}
|