Reduce remaining file, LSP, and XAA debug detail
This commit is contained in:
@@ -57,6 +57,47 @@ function debug(msg: string): void {
|
||||
logForDebugging(`[brief:upload] ${msg}`)
|
||||
}
|
||||
|
||||
function summarizeUploadError(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
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
function summarizeUploadResponse(data: unknown): string {
|
||||
if (data === undefined) return 'undefined'
|
||||
if (data === null) return 'null'
|
||||
if (Array.isArray(data)) return `array(${data.length})`
|
||||
if (typeof data === 'object') {
|
||||
return jsonStringify({
|
||||
responseType: 'object',
|
||||
keys: Object.keys(data as Record<string, unknown>)
|
||||
.sort()
|
||||
.slice(0, 10),
|
||||
})
|
||||
}
|
||||
return typeof data
|
||||
}
|
||||
|
||||
/**
|
||||
* Base URL for uploads. Must match the host the token is valid for.
|
||||
*
|
||||
@@ -100,7 +141,9 @@ export async function uploadBriefAttachment(
|
||||
if (!ctx.replBridgeEnabled) return undefined
|
||||
|
||||
if (size > MAX_UPLOAD_BYTES) {
|
||||
debug(`skip ${fullPath}: ${size} bytes exceeds ${MAX_UPLOAD_BYTES} limit`)
|
||||
debug(
|
||||
`skip attachment upload: ${size} bytes exceeds ${MAX_UPLOAD_BYTES} limit`,
|
||||
)
|
||||
return undefined
|
||||
}
|
||||
|
||||
@@ -114,7 +157,7 @@ export async function uploadBriefAttachment(
|
||||
try {
|
||||
content = await readFile(fullPath)
|
||||
} catch (e) {
|
||||
debug(`read failed for ${fullPath}: ${e}`)
|
||||
debug(`read failed before upload: ${summarizeUploadError(e)}`)
|
||||
return undefined
|
||||
}
|
||||
|
||||
@@ -150,23 +193,23 @@ export async function uploadBriefAttachment(
|
||||
|
||||
if (response.status !== 201) {
|
||||
debug(
|
||||
`upload failed for ${fullPath}: status=${response.status} body=${jsonStringify(response.data).slice(0, 200)}`,
|
||||
`upload failed: status=${response.status} response=${summarizeUploadResponse(
|
||||
response.data,
|
||||
)}`,
|
||||
)
|
||||
return undefined
|
||||
}
|
||||
|
||||
const parsed = uploadResponseSchema().safeParse(response.data)
|
||||
if (!parsed.success) {
|
||||
debug(
|
||||
`unexpected response shape for ${fullPath}: ${parsed.error.message}`,
|
||||
)
|
||||
debug('unexpected upload response shape')
|
||||
return undefined
|
||||
}
|
||||
|
||||
debug(`uploaded ${fullPath} → ${parsed.data.file_uuid} (${size} bytes)`)
|
||||
debug(`uploaded attachment (${size} bytes)`)
|
||||
return parsed.data.file_uuid
|
||||
} catch (e) {
|
||||
debug(`upload threw for ${fullPath}: ${e}`)
|
||||
debug(`upload threw: ${summarizeUploadError(e)}`)
|
||||
return undefined
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,7 +15,6 @@ import type {
|
||||
ScopedMcpServerConfig,
|
||||
} from '../../services/mcp/types.js'
|
||||
import type { Tool } from '../../Tool.js'
|
||||
import { errorMessage } from '../../utils/errors.js'
|
||||
import { lazySchema } from '../../utils/lazySchema.js'
|
||||
import { logMCPDebug, logMCPError } from '../../utils/log.js'
|
||||
import type { PermissionDecision } from '../../utils/permissions/PermissionResult.js'
|
||||
@@ -29,9 +28,11 @@ export type McpAuthOutput = {
|
||||
authUrl?: string
|
||||
}
|
||||
|
||||
function getConfigUrl(config: ScopedMcpServerConfig): string | undefined {
|
||||
if ('url' in config) return config.url
|
||||
return undefined
|
||||
function summarizeMcpAuthToolError(error: unknown): string {
|
||||
if (error instanceof Error) {
|
||||
return `${error.name} (hasMessage=${error.message.length > 0})`
|
||||
}
|
||||
return `non-Error (${typeof error})`
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -50,12 +51,10 @@ export function createMcpAuthTool(
|
||||
serverName: string,
|
||||
config: ScopedMcpServerConfig,
|
||||
): Tool<InputSchema, McpAuthOutput> {
|
||||
const url = getConfigUrl(config)
|
||||
const transport = config.type ?? 'stdio'
|
||||
const location = url ? `${transport} at ${url}` : transport
|
||||
|
||||
const description =
|
||||
`The \`${serverName}\` MCP server (${location}) is installed but requires authentication. ` +
|
||||
`The \`${serverName}\` MCP server (${transport}) is installed but requires authentication. ` +
|
||||
`Call this tool to start the OAuth flow — you'll receive an authorization URL to share with the user. ` +
|
||||
`Once the user completes authorization in their browser, the server's real tools will become available automatically.`
|
||||
|
||||
@@ -167,7 +166,9 @@ export function createMcpAuthTool(
|
||||
.catch(err => {
|
||||
logMCPError(
|
||||
serverName,
|
||||
`OAuth flow failed after tool-triggered start: ${errorMessage(err)}`,
|
||||
`OAuth flow failed after tool-triggered start: ${summarizeMcpAuthToolError(
|
||||
err,
|
||||
)}`,
|
||||
)
|
||||
})
|
||||
|
||||
@@ -199,7 +200,7 @@ export function createMcpAuthTool(
|
||||
return {
|
||||
data: {
|
||||
status: 'error' as const,
|
||||
message: `Failed to start OAuth flow for ${serverName}: ${errorMessage(err)}. Ask the user to run /mcp and authenticate manually.`,
|
||||
message: `Failed to start OAuth flow for ${serverName}. Ask the user to run /mcp and authenticate manually.`,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user