(
filename: string,
toolUseContext: ToolUseContext,
successEventName: string,
errorEventName: string,
mode: 'compact' | 'at-mention',
options?: {
offset?: number
limit?: number
},
)
| 3018 | } |
| 3019 | |
| 3020 | export async function generateFileAttachment( |
| 3021 | filename: string, |
| 3022 | toolUseContext: ToolUseContext, |
| 3023 | successEventName: string, |
| 3024 | errorEventName: string, |
| 3025 | mode: 'compact' | 'at-mention', |
| 3026 | options?: { |
| 3027 | offset?: number |
| 3028 | limit?: number |
| 3029 | }, |
| 3030 | ): Promise< |
| 3031 | | FileAttachment |
| 3032 | | CompactFileReferenceAttachment |
| 3033 | | PDFReferenceAttachment |
| 3034 | | AlreadyReadFileAttachment |
| 3035 | | null |
| 3036 | > { |
| 3037 | const { offset, limit } = options ?? {} |
| 3038 | |
| 3039 | // Check if file has a deny rule configured |
| 3040 | const appState = toolUseContext.getAppState() |
| 3041 | if (isFileReadDenied(filename, appState.toolPermissionContext)) { |
| 3042 | return null |
| 3043 | } |
| 3044 | |
| 3045 | // Check file size before attempting to read (skip for PDFs — they have their own size/page handling below) |
| 3046 | if ( |
| 3047 | mode === 'at-mention' && |
| 3048 | !isFileWithinReadSizeLimit( |
| 3049 | filename, |
| 3050 | getDefaultFileReadingLimits().maxSizeBytes, |
| 3051 | ) |
| 3052 | ) { |
| 3053 | const ext = parse(filename).ext.toLowerCase() |
| 3054 | if (!isPDFExtension(ext)) { |
| 3055 | try { |
| 3056 | const stats = await getFsImplementation().stat(filename) |
| 3057 | logEvent('tengu_attachment_file_too_large', { |
| 3058 | size_bytes: stats.size, |
| 3059 | mode, |
| 3060 | } as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS) |
| 3061 | return null |
| 3062 | } catch { |
| 3063 | // If we can't stat the file, proceed with normal reading (will fail later if file doesn't exist) |
| 3064 | } |
| 3065 | } |
| 3066 | } |
| 3067 | |
| 3068 | // For large PDFs on @ mention, return a lightweight reference instead of inlining |
| 3069 | if (mode === 'at-mention') { |
| 3070 | const pdfRef = await tryGetPDFReference(filename) |
| 3071 | if (pdfRef) { |
| 3072 | return pdfRef |
| 3073 | } |
| 3074 | } |
| 3075 | |
| 3076 | // Check if file is already in context with latest version |
| 3077 | const existingFileState = toolUseContext.readFileState.get(filename) |
no test coverage detected