Skip to content

Commit b46aae2

Browse files
committed
fix: more consistent indentations
1 parent 69f9391 commit b46aae2

File tree

1 file changed

+40
-50
lines changed

1 file changed

+40
-50
lines changed

npm-app/src/cli-handlers/chat.ts

Lines changed: 40 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -469,12 +469,8 @@ function finishStreamingMessage(messageId: string): void {
469469
}
470470
chatState.currentlyStreamingNodeId = undefined
471471

472-
// Collapse all subagent tree nodes when streaming finishes
473-
if (message.subagentUIState) {
474-
message.subagentUIState.expanded.clear()
475-
message.subagentUIState.focusNodeId = null
476-
message.subagentUIState.firstChildProgress.clear()
477-
}
472+
// Keep expansion state when streaming finishes
473+
// (no auto-collapse behavior)
478474

479475
updateContentLines()
480476
renderChat()
@@ -530,12 +526,7 @@ export function renderAssistantMessage(
530526
message.subagentTree && message.subagentTree.postContent
531527
const shouldShowOnlyPostContent = isFullyCollapsed && hasPostContentToShow
532528

533-
// Hide parent content when a child is processing in THIS message
534-
const isProcessingChildren =
535-
chatState.currentlyStreamingNodeId?.includes('/') &&
536-
chatState.currentStreamingMessageId === message.id
537-
538-
if (!shouldShowOnlyPostContent && !isProcessingChildren) {
529+
if (!shouldShowOnlyPostContent) {
539530
// Show preview or full content based on expansion state
540531
const shouldShowPreview = hasSubagents && !isMainExpanded
541532

@@ -554,8 +545,8 @@ export function renderAssistantMessage(
554545
const previewLines = wrappedLines.slice(0, PREVIEW_LINES)
555546

556547
previewLines.forEach((line) => {
557-
const indentedLine = ' ' + line // 4 spaces for assistant content with subagents
558-
appendWrappedLine(lines, indentedLine, 4, metrics, [], 0)
548+
const indentedLine = line // 0 spaces to match subagent indentation
549+
appendWrappedLine(lines, indentedLine, 0, metrics, [], 0)
559550
})
560551

561552
// Add "..." if content was truncated
@@ -568,8 +559,8 @@ export function renderAssistantMessage(
568559
const contentLines = message.content.split('\n')
569560

570561
contentLines.forEach((line) => {
571-
const indentedLine = hasSubagents ? ' ' + line : line // 4 spaces if has subagents, 0 if simple message
572-
const indentLevel = hasSubagents ? 4 : 0
562+
const indentedLine = line // 0 spaces to match subagent indentation
563+
const indentLevel = 0
573564
appendWrappedLine(lines, indentedLine, indentLevel, metrics, [], 0)
574565
})
575566
}
@@ -997,35 +988,13 @@ async function streamTextToNodeProperty(
997988
chatState.currentlyStreamingNodeId = node.id
998989
}
999990

1000-
let hasCollapsed = false
1001-
1002991
const words = text.split(' ')
1003992
for (let i = 0; i < words.length; i++) {
1004993
const word = words[i]
1005994
const isLastWord = i === words.length - 1
1006995

1007-
// If streaming postContent, automatically collapse this node ONLY on first word
1008-
// This prevents the delay by deferring the collapse until streaming actually begins
1009-
if (property === 'postContent' && !hasCollapsed) {
1010-
const currentStreamingMessage = chatState.messages.find(
1011-
(m) => m.id === chatState.currentStreamingMessageId,
1012-
)
1013-
if (currentStreamingMessage && currentStreamingMessage.subagentUIState) {
1014-
const uiState = currentStreamingMessage.subagentUIState
1015-
1016-
// Collapse this specific node
1017-
uiState.expanded.delete(node.id)
1018-
1019-
// Also collapse any child nodes of this node
1020-
const childPrefix = node.id + '/'
1021-
uiState.expanded.forEach((nodeId) => {
1022-
if (nodeId.startsWith(childPrefix)) {
1023-
uiState.expanded.delete(nodeId)
1024-
}
1025-
})
1026-
hasCollapsed = true
1027-
}
1028-
}
996+
// No auto-collapse behavior when streaming postContent
997+
// Keep expansion state as-is
1029998

1030999
const chunk = (i === 0 ? '' : ' ') + word
10311000
if (property === 'postContent') {
@@ -1539,16 +1508,11 @@ export function renderSubagentTree(
15391508
metrics,
15401509
)
15411510

1542-
// Content - 4 additional spaces beyond header indentation
1511+
// Content - indented to align with the header
15431512
// Only show content if expanded or has no children
1544-
// Also hide content if one of this node's descendants is currently processing in THIS message
1545-
const isProcessingChildren =
1546-
chatState.currentlyStreamingNodeId?.startsWith(nodeId + '/') &&
1547-
chatState.currentStreamingMessageId === messageId
1548-
1549-
if (node.content && (isExpanded || !hasChildren) && !isProcessingChildren) {
1513+
if (node.content && (isExpanded || !hasChildren)) {
15501514
const contentLines = node.content.split('\n')
1551-
const contentIndentSpaces = headerIndentSpaces + 4
1515+
const contentIndentSpaces = 4 * depth
15521516
const contentPrefix = ' '.repeat(contentIndentSpaces)
15531517
contentLines.forEach((line) => {
15541518
if (line.trim()) {
@@ -1572,7 +1536,7 @@ export function renderSubagentTree(
15721536
} else if (hasChildren && !isExpanded && node.postContent) {
15731537
// Show postContent for collapsed nodes with children
15741538
const postLines = node.postContent.split('\n')
1575-
const postIndentSpaces = 4 * depth + 4 // Same as header indentation + 4 extra spaces
1539+
const postIndentSpaces = 4 * depth // Same as header indentation
15761540
const postPrefix = ' '.repeat(postIndentSpaces)
15771541
postLines.forEach((line) => {
15781542
if (line.trim()) {
@@ -1600,7 +1564,7 @@ export function renderSubagentTree(
16001564
const rootNodeId = tree.id
16011565
if (tree.postContent && !uiState.expanded.has(rootNodeId)) {
16021566
const postLines = tree.postContent.split('\n')
1603-
const postPrefix = ' ' // 4 extra spaces for indentation
1567+
const postPrefix = '' // 0 spaces to match assistant indentation
16041568
postLines.forEach((line) => {
16051569
if (line.trim()) {
16061570
appendWrappedLine(
@@ -1718,6 +1682,11 @@ function handleToggleAction(key: any): boolean {
17181682
const isExpanded = uiState.expanded.has(actualNodeId)
17191683

17201684
if (isExpanded) {
1685+
// Check if any descendants are currently streaming - if so, don't allow collapse
1686+
if (isAnyDescendantStreaming(actualNodeId, focusedMessage.id)) {
1687+
return true // Consume the key press but don't collapse
1688+
}
1689+
17211690
// Collapse the node
17221691
uiState.expanded.delete(actualNodeId)
17231692
// Remove all descendant nodes from expanded set
@@ -1774,6 +1743,11 @@ function handleArrowToggleAction(key: any): boolean {
17741743
if (key.name === 'left') {
17751744
// Left arrow: close (collapse) if expanded, otherwise navigate to previous toggle
17761745
if (isExpanded) {
1746+
// Check if any descendants are currently streaming - if so, don't allow collapse
1747+
if (isAnyDescendantStreaming(actualNodeId, focusedMessage.id)) {
1748+
return true // Consume the key press but don't collapse
1749+
}
1750+
17771751
uiState.expanded.delete(actualNodeId)
17781752
// Remove all descendant nodes from expanded set
17791753
const descendantPrefix = actualNodeId + '/'
@@ -1987,6 +1961,22 @@ function clearAllToggleFocus(): boolean {
19871961
return hadFocus
19881962
}
19891963

1964+
function isAnyDescendantStreaming(nodeId: string, messageId: string): boolean {
1965+
// Check if the current streaming node is this node or any of its descendants
1966+
if (
1967+
chatState.currentlyStreamingNodeId &&
1968+
chatState.currentStreamingMessageId === messageId
1969+
) {
1970+
// If the streaming node starts with our nodeId followed by '/', it's a descendant
1971+
// Or if it's exactly our nodeId, we're streaming
1972+
return (
1973+
chatState.currentlyStreamingNodeId === nodeId ||
1974+
chatState.currentlyStreamingNodeId.startsWith(nodeId + '/')
1975+
)
1976+
}
1977+
return false
1978+
}
1979+
19901980
function autoFocusLatestToggle(): void {
19911981
const latestMessageId = findLatestAssistantMessageWithChildren()
19921982
if (!latestMessageId) return

0 commit comments

Comments
 (0)