mirror of
https://github.com/claude-code-best/claude-code.git
synced 2026-06-18 22:35:51 +00:00
107 lines
3.1 KiB
TypeScript
107 lines
3.1 KiB
TypeScript
import * as React from 'react'
|
|
import { Box, Text } from '@anthropic/ink'
|
|
import {
|
|
type NetworkHostPattern,
|
|
shouldAllowManagedSandboxDomainsOnly,
|
|
} from 'src/utils/sandbox/sandbox-adapter.js'
|
|
import {
|
|
type AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS,
|
|
logEvent,
|
|
} from '../../services/analytics/index.js'
|
|
import { Select } from '../CustomSelect/select.js'
|
|
import { PermissionDialog } from './PermissionDialog.js'
|
|
|
|
export type SandboxPermissionRequestProps = {
|
|
hostPattern: NetworkHostPattern
|
|
onUserResponse: (response: {
|
|
allow: boolean
|
|
persistToSettings: boolean
|
|
}) => void
|
|
}
|
|
|
|
export function SandboxPermissionRequest({
|
|
hostPattern: { host },
|
|
onUserResponse,
|
|
}: SandboxPermissionRequestProps): React.ReactNode {
|
|
function onSelect(value: string) {
|
|
// We may want to better unify this dialog with other permission dialogs
|
|
// and use their logging, but this is slightly different and we don't have
|
|
// the tool context here. For now, just use basic logging for basic data.
|
|
if (process.env.USER_TYPE === 'ant') {
|
|
logEvent('tengu_sandbox_network_dialog_result', {
|
|
host: host as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS,
|
|
result:
|
|
value as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS,
|
|
})
|
|
}
|
|
|
|
switch (value) {
|
|
case 'yes':
|
|
onUserResponse({ allow: true, persistToSettings: false })
|
|
break
|
|
case 'yes-dont-ask-again':
|
|
onUserResponse({ allow: true, persistToSettings: true })
|
|
break
|
|
case 'no':
|
|
onUserResponse({ allow: false, persistToSettings: false })
|
|
break
|
|
}
|
|
}
|
|
|
|
const managedDomainsOnly = shouldAllowManagedSandboxDomainsOnly()
|
|
|
|
const options = [
|
|
{ label: 'Yes', value: 'yes' },
|
|
...(!managedDomainsOnly
|
|
? [
|
|
{
|
|
label: (
|
|
<Text>
|
|
Yes, and don't ask again for <Text bold>{host}</Text>
|
|
</Text>
|
|
),
|
|
value: 'yes-dont-ask-again',
|
|
},
|
|
]
|
|
: []),
|
|
{
|
|
label: (
|
|
<Text>
|
|
No, and tell Claude what to do differently <Text bold>(esc)</Text>
|
|
</Text>
|
|
),
|
|
value: 'no',
|
|
},
|
|
]
|
|
|
|
return (
|
|
<PermissionDialog title="Network request outside of sandbox">
|
|
<Box flexDirection="column" paddingX={2} paddingY={1}>
|
|
<Box>
|
|
<Text dimColor>Host:</Text>
|
|
<Text> {host}</Text>
|
|
</Box>
|
|
<Box marginTop={1}>
|
|
<Text>Do you want to allow this connection?</Text>
|
|
</Box>
|
|
<Box>
|
|
<Select
|
|
options={options}
|
|
onChange={onSelect}
|
|
onCancel={() => {
|
|
if (process.env.USER_TYPE === 'ant') {
|
|
logEvent('tengu_sandbox_network_dialog_result', {
|
|
host: host as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS,
|
|
result:
|
|
'cancel' as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS,
|
|
})
|
|
}
|
|
onUserResponse({ allow: false, persistToSettings: false })
|
|
}}
|
|
/>
|
|
</Box>
|
|
</Box>
|
|
</PermissionDialog>
|
|
)
|
|
}
|