All files / webview/hooks usePermissionState.ts

35.71% Statements 10/28
16.66% Branches 4/24
28.57% Functions 2/7
37.03% Lines 10/27

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91                                                515x 515x   515x 13x 13x         13x                                                                   515x         515x           515x       515x              
import type { Dispatch, SetStateAction } from 'react'
import { useState } from 'react'
import type { MessageEntry } from '../lib/types'
import type { MessageRouter } from './useMessageRouter'
 
export type PendingPermission = {
  requestId: string
  tool: string
  input: Record<string, unknown>
}
 
export type PendingInput = {
  requestId: string
  message: string
  questions: {
    question: string
    header?: string
    options?: { label: string; description?: string }[]
    multiSelect?: boolean
    freeText?: boolean
  }[]
}
 
export function usePermissionState(router: MessageRouter, setMessages: Dispatch<SetStateAction<MessageEntry[]>>) {
  const [pendingPermission, setPendingPermission] = useState<PendingPermission | null>(null)
  const [pendingInput, setPendingInput] = useState<PendingInput | null>(null)
 
  router.register('prompt', (msg) => {
    if (msg.subtype === 'permission') {
      setPendingPermission({
        requestId: msg.requestId as string,
        tool: msg.tool as string,
        input: msg.input as Record<string, unknown>,
      })
      Iif (msg.tool === 'FileEdit' || msg.tool === 'Edit') {
        const input = msg.input as Record<string, unknown>
        const file = String(input.file_path ?? '')
        const filename = file.split('/').pop() ?? file
        const oldString = String(input.old_string ?? '')
        const newString = String(input.new_string ?? '')
        const totalLines = oldString.split('\n').length + newString.split('\n').length
        const diffAutoOpened = totalLines > 6
        setMessages((prev) => [
          ...prev,
          {
            role: 'tool',
            name: msg.tool as string,
            summary: `Edit ${filename}`,
            filePath: file || undefined,
            diff: { oldString, newString },
            diffId: msg.requestId as string,
            diffAutoOpened,
          },
        ])
      }
    E} else if (msg.subtype === 'input') {
      const rawQuestions = (msg.questions as ({ multi_select?: boolean } & Record<string, unknown>)[]) ?? []
      setPendingInput({
        requestId: msg.requestId as string,
        message: (msg.message as string) ?? '',
        questions: rawQuestions.map((q) => ({
          ...(q as PendingInput['questions'][number]),
          multiSelect: q.multi_select ?? (q as PendingInput['questions'][number]).multiSelect,
        })),
      })
    }
  })
 
  router.register('conversationLoaded', () => {
    setPendingPermission(null)
    setPendingInput(null)
  })
 
  router.register('conversationSwitched', () => {
    setPendingPermission(null)
    setPendingInput(null)
  })
 
  // pushConfirm sets a synthetic permission
  router.register('pushConfirm', () => {
    setPendingPermission({ requestId: '__push__', tool: 'PushProject', input: {} })
  })
 
  return {
    pendingPermission,
    setPendingPermission,
    pendingInput,
    setPendingInput,
  }
}