Reduce remaining file, LSP, and XAA debug detail

This commit is contained in:
2026-04-04 10:31:29 +08:00
parent 010ded8476
commit 4d506aabf7
6 changed files with 211 additions and 90 deletions

View File

@@ -14,9 +14,10 @@ import * as path from 'path'
import { count } from '../../utils/array.js'
import { getCwd } from '../../utils/cwd.js'
import { logForDebugging } from '../../utils/debug.js'
import { errorMessage } from '../../utils/errors.js'
import { errorMessage, getErrnoCode } from '../../utils/errors.js'
import { logError } from '../../utils/log.js'
import { sleep } from '../../utils/sleep.js'
import { jsonStringify } from '../../utils/slowOperations.js'
import {
type AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS,
logEvent,
@@ -45,6 +46,37 @@ function logDebug(message: string): void {
logForDebugging(`[files-api] ${message}`)
}
function summarizeFilesApiError(error: unknown): string {
const summary: Record<string, boolean | number | string> = {}
if (error instanceof Error) {
summary.errorType = error.constructor.name
summary.errorName = error.name
summary.hasMessage = error.message.length > 0
} else {
summary.errorType = typeof error
summary.hasValue = error !== undefined && error !== null
}
const errno = getErrnoCode(error)
if (errno) {
summary.errno = errno
}
if (axios.isAxiosError(error)) {
summary.errorType = 'AxiosError'
if (error.code) {
summary.axiosCode = error.code
}
if (typeof error.response?.status === 'number') {
summary.httpStatus = error.response.status
}
summary.hasResponseData = error.response?.data !== undefined
}
return jsonStringify(summary)
}
/**
* File specification parsed from CLI args
* Format: --file=<file_id>:<relative_path>
@@ -108,9 +140,7 @@ async function retryWithBackoff<T>(
}
lastError = result.error || `${operation} failed`
logDebug(
`${operation} attempt ${attempt}/${MAX_RETRIES} failed: ${lastError}`,
)
logDebug(`${operation} attempt ${attempt}/${MAX_RETRIES} failed`)
if (attempt < MAX_RETRIES) {
const delayMs = BASE_DELAY_MS * Math.pow(2, attempt - 1)
@@ -142,7 +172,7 @@ export async function downloadFile(
'anthropic-beta': FILES_API_BETA_HEADER,
}
logDebug(`Downloading file ${fileId} from ${url}`)
logDebug(`Downloading file ${fileId} from configured Files API endpoint`)
return retryWithBackoff(`Download file ${fileId}`, async () => {
try {
@@ -191,9 +221,7 @@ export function buildDownloadPath(
): string | null {
const normalized = path.normalize(relativePath)
if (normalized.startsWith('..')) {
logDebugError(
`Invalid file path: ${relativePath}. Path must not traverse above workspace`,
)
logDebugError('Invalid file path rejected: path traversal is not allowed')
return null
}
@@ -243,7 +271,7 @@ export async function downloadAndSaveFile(
// Write the file
await fs.writeFile(fullPath, content)
logDebug(`Saved file ${fileId} to ${fullPath} (${content.length} bytes)`)
logDebug(`Saved file ${fileId} (${content.length} bytes)`)
return {
fileId,
@@ -252,10 +280,16 @@ export async function downloadAndSaveFile(
bytesWritten: content.length,
}
} catch (error) {
logDebugError(`Failed to download file ${fileId}: ${errorMessage(error)}`)
if (error instanceof Error) {
logError(error)
}
logDebugError(
`Failed to download file ${fileId}: ${summarizeFilesApiError(error)}`,
)
logError(
new Error(
`Files API download failed for ${fileId}: ${summarizeFilesApiError(
error,
)}`,
),
)
return {
fileId,
@@ -390,7 +424,7 @@ export async function uploadFile(
'anthropic-beta': FILES_API_BETA_HEADER,
}
logDebug(`Uploading file ${filePath} as ${relativePath}`)
logDebug('Uploading file to configured Files API endpoint')
// Read file content first (outside retry loop since it's not a network operation)
let content: Buffer
@@ -455,7 +489,7 @@ export async function uploadFile(
const body = Buffer.concat(bodyParts)
try {
return await retryWithBackoff(`Upload file ${relativePath}`, async () => {
return await retryWithBackoff('Upload session file', async () => {
try {
const response = await axios.post(url, body, {
headers: {
@@ -476,7 +510,7 @@ export async function uploadFile(
error: 'Upload succeeded but no file ID returned',
}
}
logDebug(`Uploaded file ${filePath} -> ${fileId} (${fileSize} bytes)`)
logDebug(`Uploaded file (${fileSize} bytes)`)
return {
done: true,
value: {
@@ -735,9 +769,7 @@ export function parseFileSpecs(fileSpecs: string[]): File[] {
const relativePath = spec.substring(colonIndex + 1)
if (!fileId || !relativePath) {
logDebugError(
`Invalid file spec: ${spec}. Both file_id and path are required`,
)
logDebugError('Invalid file spec: missing file_id or relative path')
continue
}