/ src / components / binary-feedback / BinaryFeedbackOption.tsx
BinaryFeedbackOption.tsx
  1  import { FileEditTool } from '../../tools/FileEditTool/FileEditTool.js'
  2  import { FileEditToolDiff } from '../permissions/FileEditPermissionRequest/FileEditToolDiff.js'
  3  import { Message } from '../Message.js'
  4  import {
  5    normalizeMessages,
  6    type NormalizedMessage,
  7  } from '../../utils/messages.js'
  8  import type { Tool } from '../../Tool.js'
  9  import { useTerminalSize } from '../../hooks/useTerminalSize.js'
 10  import { FileWriteTool } from '../../tools/FileWriteTool/FileWriteTool.js'
 11  import { FileWriteToolDiff } from '../permissions/FileWritePermissionRequest/FileWriteToolDiff.js'
 12  import type { AssistantMessage } from '../../query.js'
 13  import * as React from 'react'
 14  import { Box } from 'ink'
 15  
 16  type Props = {
 17    debug: boolean
 18    erroredToolUseIDs: Set<string>
 19    inProgressToolUseIDs: Set<string>
 20    message: AssistantMessage
 21    normalizedMessages: NormalizedMessage[]
 22    tools: Tool[]
 23    unresolvedToolUseIDs: Set<string>
 24    verbose: boolean
 25  }
 26  
 27  export function BinaryFeedbackOption({
 28    debug,
 29    erroredToolUseIDs,
 30    inProgressToolUseIDs,
 31    message,
 32    normalizedMessages,
 33    tools,
 34    unresolvedToolUseIDs,
 35    verbose,
 36  }: Props): React.ReactNode {
 37    const { columns } = useTerminalSize()
 38    return normalizeMessages([message])
 39      .filter(_ => _.type !== 'progress')
 40      .map((_, index) => (
 41        <Box flexDirection="column" key={index}>
 42          <Message
 43            addMargin={false}
 44            erroredToolUseIDs={erroredToolUseIDs}
 45            debug={debug}
 46            inProgressToolUseIDs={inProgressToolUseIDs}
 47            message={_}
 48            messages={normalizedMessages}
 49            shouldAnimate={false}
 50            shouldShowDot={true}
 51            tools={tools}
 52            unresolvedToolUseIDs={unresolvedToolUseIDs}
 53            verbose={verbose}
 54            width={columns / 2 - 6}
 55          />
 56          <AdditionalContext message={_} verbose={verbose} />
 57        </Box>
 58      ))
 59  }
 60  
 61  function AdditionalContext({
 62    message,
 63    verbose,
 64  }: {
 65    message: NormalizedMessage
 66    verbose: boolean
 67  }) {
 68    const { columns } = useTerminalSize()
 69    if (message.type !== 'assistant') {
 70      return null
 71    }
 72    const content = message.message.content[0]!
 73    switch (content.type) {
 74      case 'tool_use':
 75        switch (content.name) {
 76          case FileEditTool.name: {
 77            const input = FileEditTool.inputSchema.safeParse(content.input)
 78            if (!input.success) {
 79              return null
 80            }
 81            return (
 82              <FileEditToolDiff
 83                file_path={input.data.file_path}
 84                new_string={input.data.new_string}
 85                old_string={input.data.old_string}
 86                verbose={verbose}
 87                width={columns / 2 - 12}
 88              />
 89            )
 90          }
 91          case FileWriteTool.name: {
 92            const input = FileWriteTool.inputSchema.safeParse(content.input)
 93            if (!input.success) {
 94              return null
 95            }
 96            return (
 97              <FileWriteToolDiff
 98                file_path={input.data.file_path}
 99                content={input.data.content}
100                verbose={verbose}
101                width={columns / 2 - 12}
102              />
103            )
104          }
105          default:
106            return null
107        }
108      default:
109        return null
110    }
111  }