Repository: humanlayer/humanlayer
File: humanlayer-wui/src/components/internal/SessionDetail/eventToDisplayObject.tsx (TypeScript)

Code before:
              </Button>
              {!isApproving && (
                <Button
                  className="cursor-pointer"
                  size="sm"
                  variant="destructive"
                  onClick={e => {
                    e.stopPropagation()
                    onStartDeny?.(event.approvalId!)
                  }}
                >
                  Deny <kbd className="ml-1 px-1 py-0.5 text-xs bg-muted/50 rounded">D</kbd>
                </Button>
              )}
            </>
          ) : (
            <DenyButtons onCancel={onCancelDeny} isDenying={isDenying} />
          )}
        </div>
      )
    }
  }

  if (event.eventType === ConversationEventType.Thinking) {
    // Thinking messages are always from assistant
    const fullContent = (event.content || '').trim()

    subject = (
      <div className="text-muted-foreground italic">
        <MarkdownRenderer content={fullContent} />
      </div>
    )
    body = null // Everything is in subject for thinking messages
  }

  if (event.eventType === ConversationEventType.Message) {
    // For assistant messages, show full content without truncation
    if (event.role === 'assistant') {
      const fullContent = event.content || ''

      subject = (
        <div className={isThinking ? 'text-muted-foreground' : ''}>
          <MarkdownRenderer content={fullContent} />
        </div>
      )
      body = null // Everything is in subject for assistant messages
    } else {
      // For user messages, keep the existing split behavior
      const subjectText = event.content?.split('\n')[0] || ''
      const bodyText = event.content?.split('\n').slice(1).join('\n') || ''


Review comment (suggestion):
This will work, but an alternate: We're calling `responseEditor.getText()` to check for whether the responseEditor has content, but `responseEditor` also has an `isEmpty` boolean we can check against that might be use-case appropriate for this.  

Code after:
                <kbd className="ml-1 px-1 py-0.5 text-xs bg-muted/50 rounded">A</kbd>
              </Button>
              {!isApproving && (
                <Button
                  className="cursor-pointer"
                  size="sm"
                  variant="destructive"
                  onClick={e => {
                    e.stopPropagation()
                    onStartDeny?.(event.approvalId!)
                  }}
                >
                  Deny <kbd className="ml-1 px-1 py-0.5 text-xs bg-muted/50 rounded">D</kbd>
                </Button>
              )}
            </>
          ) : (
            <DenyButtons
              onCancel={onCancelDeny}
              onDeny={() => {
                if (event.approvalId && onDeny) {
                  onDeny(event.approvalId, responseText?.trim() || '')
                }
              }}
              isDenying={isDenying}
              isDisabled={!responseText?.trim()}
            />
          )}
        </div>
      )
    }
  }

  if (event.eventType === ConversationEventType.Thinking) {
    // Thinking messages are always from assistant
    const fullContent = (event.content || '').trim()

    subject = (
      <div className="text-muted-foreground italic">
        <MarkdownRenderer content={fullContent} />
      </div>
    )
    body = null // Everything is in subject for thinking messages
  }

  if (event.eventType === ConversationEventType.Message) {
    // For assistant messages, show full content without truncation
    if (event.role === 'assistant') {
      const fullContent = event.content || ''

      subject = (