fix: pdf_read가 /api/files/ 채팅링크를 경로로 착각해 실패하던 문제
모델이 업로드 링크 URL을 그대로 path로 넘기면 path.isAbsolute()가 true로 판정돼 워크스페이스 상대경로 변환을 안 타고 "path escapes workspace"로 실패했음. 도구 설명에 부정 예시 명시 + execute()에서 /api/files/ 접두사 자동 제거로 이중 보강. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SUjjAwB2Cmjf4YFRZpobec
This commit is contained in:
@@ -1054,7 +1054,7 @@ export function createBuildTools(isOrchestrationSkillEnabled: () => boolean) {
|
||||
parameters: {
|
||||
type: 'object', required: ['path'],
|
||||
properties: {
|
||||
path: { type: 'string', description: 'Path to the PDF file (relative to workspace or absolute)' },
|
||||
path: { type: 'string', description: 'Workspace-relative path to the PDF file, e.g. "uploads/파일명.pdf". Do NOT pass the /api/files/... URL shown in chat links — strip that prefix and use the part after "uploads/".' },
|
||||
page_from: { type: 'number', description: 'First page (1-indexed)' },
|
||||
page_to: { type: 'number', description: 'Last page (inclusive)' },
|
||||
max_chars: { type: 'number', description: 'Max chars to return (default: 20000)' },
|
||||
|
||||
+3
-2
@@ -292,7 +292,7 @@ export const pdfReadTool = {
|
||||
name: 'pdf_read',
|
||||
description: 'Extract text from a PDF file. Returns markdown-formatted text: headings (##/###), bold (**), indentation, and bullet lists. Multi-column academic PDFs are handled correctly. Complex tables are skipped (use pdf_extract_images for table figures). For scanned/image PDFs falls back to Tesseract OCR.',
|
||||
schema: {
|
||||
path: 'Path to the PDF file (absolute, or relative to workspace)',
|
||||
path: 'Workspace-relative path to the PDF file (e.g. "uploads/파일명.pdf"), not the /api/files/... chat link',
|
||||
page_from: 'First page to extract, 1-indexed (default: 1)',
|
||||
page_to: 'Last page to extract, inclusive (default: last page)',
|
||||
max_chars: 'Maximum characters to return (default: 20000, max: 100000)',
|
||||
@@ -311,8 +311,9 @@ export const pdfReadTool = {
|
||||
additionalProperties: false,
|
||||
},
|
||||
execute: async (args: any): Promise<ToolResult> => {
|
||||
const filePath = String(args?.path || '').trim();
|
||||
let filePath = String(args?.path || '').trim();
|
||||
if (!filePath) return { success: false, error: 'path is required' };
|
||||
filePath = filePath.replace(/^\/api\/files\//, '');
|
||||
|
||||
const workspacePath = getWorkspacePath(args);
|
||||
const resolved = path.isAbsolute(filePath) ? filePath : path.resolve(workspacePath, filePath);
|
||||
|
||||
Reference in New Issue
Block a user