import { Box, Text } from 'ink'
import React, { useMemo } from 'react'
import { Select } from '../../CustomSelect/select'
import { getTheme } from '../../../utils/theme'
import {
PermissionRequestTitle,
textColorForRiskScore,
} from '../PermissionRequestTitle.js'
import { logUnaryEvent } from '../../../utils/unaryLogging'
import { env } from '../../../utils/env'
import {
type PermissionRequestProps,
type ToolUseConfirm,
} from '../PermissionRequest.js'
import chalk from 'chalk'
import {
UnaryEvent,
usePermissionRequestLogging,
} from '../../../hooks/usePermissionRequestLogging.js'
import { FileEditTool } from '../../../tools/FileEditTool/FileEditTool'
import { FileWriteTool } from '../../../tools/FileWriteTool/FileWriteTool'
import { GrepTool } from '../../../tools/GrepTool/GrepTool'
import { GlobTool } from '../../../tools/GlobTool/GlobTool'
import { LSTool } from '../../../tools/lsTool/lsTool'
import { FileReadTool } from '../../../tools/FileReadTool/FileReadTool'
import { NotebookEditTool } from '../../../tools/NotebookEditTool/NotebookEditTool'
import { NotebookReadTool } from '../../../tools/NotebookReadTool/NotebookReadTool'
import { FallbackPermissionRequest } from '../FallbackPermissionRequest'
import {
grantWritePermissionForOriginalDir,
pathInOriginalCwd,
toAbsolutePath,
} from '../../../utils/permissions/filesystem.js'
import { getCwd } from '../../../utils/state'
function pathArgNameForToolUse(toolUseConfirm: ToolUseConfirm): string | null {
switch (toolUseConfirm.tool) {
case FileWriteTool:
case FileEditTool:
case FileReadTool: {
return 'file_path'
}
case GlobTool:
case GrepTool:
case LSTool: {
return 'path'
}
case NotebookEditTool:
case NotebookReadTool: {
return 'notebook_path'
}
}
return null
}
function isMultiFile(toolUseConfirm: ToolUseConfirm): boolean {
switch (toolUseConfirm.tool) {
case GlobTool:
case GrepTool:
case LSTool: {
return true
}
}
return false
}
function pathFromToolUse(toolUseConfirm: ToolUseConfirm): string | null {
const pathArgName = pathArgNameForToolUse(toolUseConfirm)
const input = toolUseConfirm.input
if (pathArgName && pathArgName in input) {
if (typeof input[pathArgName] === 'string') {
return toAbsolutePath(input[pathArgName])
} else {
return toAbsolutePath(getCwd())
}
}
return null
}
export function FilesystemPermissionRequest({
toolUseConfirm,
onDone,
verbose,
}: PermissionRequestProps): React.ReactNode {
const path = pathFromToolUse(toolUseConfirm)
if (!path) {
// Fall back to generic permission request if no path is found
return (
)
}
return (
)
}
function getDontAskAgainOptions(toolUseConfirm: ToolUseConfirm, path: string) {
if (toolUseConfirm.tool.isReadOnly()) {
// "Always allow" is not an option for read-only tools,
// because they always have write permission in the project directory.
return []
}
// Only show don't ask again option for edits in original working directory
return pathInOriginalCwd(path)
? [
{
label: "Yes, and don't ask again for file edits this session",
value: 'yes-dont-ask-again',
},
]
: []
}
type Props = {
toolUseConfirm: ToolUseConfirm
path: string
onDone(): void
verbose: boolean
}
function FilesystemPermissionRequestImpl({
toolUseConfirm,
path,
onDone,
verbose,
}: Props): React.ReactNode {
const userFacingName = toolUseConfirm.tool.userFacingName()
const userFacingReadOrWrite = toolUseConfirm.tool.isReadOnly()
? 'Read'
: 'Edit'
const title = `${userFacingReadOrWrite} ${isMultiFile(toolUseConfirm) ? 'files' : 'file'}`
const unaryEvent = useMemo(
() => ({
completion_type: 'tool_use_single',
language_name: 'none',
}),
[],
)
usePermissionRequestLogging(toolUseConfirm, unaryEvent)
return (
{userFacingName}(
{toolUseConfirm.tool.renderToolUseMessage(
toolUseConfirm.input as never,
{ verbose },
)}
)
Do you want to proceed?
)
}