[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M6HWNMFDMT789X8F2ZR60200":3,"skill-same:01M6HWNMFDMT789X8F2ZR60200":66},{"skillNo":4,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":16,"categories":17,"keywords":23,"publishedAt":33,"linkOnly":34,"markdownContent":35,"markdownBody":36,"frontMatter":37,"refName":38,"commitSha":39,"skillDirectory":40,"forksCount":41,"repositoryHtmlUrl":42,"repositoryHomepageUrl":6,"ownerHtmlUrl":43,"ownerBlogUrl":44,"ownerDescription":6,"updatedAt":45,"install":46,"resources":59},"01M6HWNMFDMT789X8F2ZR60200","pdf-extraction-fallback-7db3aa",null,"Resilient multi-tier PDF extraction with sequential fallback strategies when initial reading fails","HKUDS\u002FAgentPilot","HKUDS","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F118165258?v=4","01M6HW8VRNZP64G0P4MVJW2KKQ","✨Data Intelligence Lab@HKU✨","01M6HW8VWZVHBRHYH3T330PFWV",7996,"MIT","https:\u002F\u002Fgithub.com\u002FHKUDS\u002FAgentPilot\u002Fblob\u002Fmain\u002Fopenspace\u002Fbenchmarks\u002Fgdpval\u002Fskills\u002Fpdf-extraction-fallback-7db3aa\u002FSKILL.md",[18],{"categoryNo":19,"categoryName":20,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000002","文档处理","SCENARIO","使用场景",[24,25,26,27,28,29,30,31,32],"PDF","extraction","fallback","pdf extraction","pdf extraction fallback 7db3aa","strategies","multi","with","reading","2026-11-10 10:12:30",false,"---\nname: pdf-extraction-fallback-7db3aa\ndescription: Resilient multi-tier PDF extraction with sequential fallback strategies when initial reading fails\n---\n\n# PDF Extraction Fallback Strategy\n\n## Purpose\n\nWhen processing complex documents (tax forms, legal documents, scanned materials), PDF extraction often fails on the first attempt. This skill provides a systematic fallback approach that tries multiple extraction methods in sequence until one succeeds.\n\n## When to Use\n\n- Initial PDF reading tools return errors or empty content\n- Document appears to be scanned\u002Fimage-based rather than text-based\n- Previous extraction attempts produced incomplete or garbled output\n- Working with forms, tables, or structured documents that need reliable extraction\n\n## Fallback Sequence\n\n### Tier 1: Shell-Based Extraction (pdftotext)\n\nStart with command-line tools that often handle edge cases better:\n\n```bash\n# Extract text maintaining layout\npdftotext -layout input.pdf output.txt\n\n# Extract raw text (faster, less formatting)\npdftotext input.pdf output.txt\n\n# Extract specific page range\npdftotext -f 1 -l 3 input.pdf output.txt\n```\n\nCheck if output contains meaningful content before proceeding.\n\n### Tier 2: Python-Based Parsing\n\nIf shell tools fail, use Python libraries with different extraction approaches:\n\n```python\n# Using PyPDF2 for basic text extraction\nimport PyPDF2\nwith open('document.pdf', 'rb') as f:\n    reader = PyPDF2.PdfReader(f)\n    text = ''.join(page.extract_text() for page in reader.pages)\n\n# Using pdfplumber for tables and structured content\nimport pdfplumber\nwith pdfplumber.open('document.pdf') as pdf:\n    for page in pdf.pages:\n        text = page.extract_text()\n        tables = page.extract_tables()\n\n# Using pypdf for newer PDF features\nfrom pypdf import PdfReader\nreader = PdfReader('document.pdf')\ntext = ''.join(page.extract_text() for page in reader.pages)\n```\n\n### Tier 3: OCR Tools (for Scanned Documents)\n\nIf the PDF contains images or scanned content, use OCR:\n\n```bash\n# Using tesseract via command line\ntesseract input.pdf output --psm 6\n\n# Using Python with pytesseract\nimport pytesseract\nfrom pdf2image import convert_from_path\n\nimages = convert_from_path('document.pdf')\ntext = ''.join(pytesseract.image_to_string(img) for img in images)\n```\n\n## Implementation Pattern\n\n```python\ndef extract_pdf_resilient(pdf_path):\n    \"\"\"Try multiple extraction methods until one succeeds.\"\"\"\n    \n    # Tier 1: Shell extraction\n    result = run_shell(f'pdftotext -layout \"{pdf_path}\" -')\n    if result.stdout and len(result.stdout.strip()) > 100:\n        return result.stdout, 'pdftotext'\n    \n    # Tier 2: Python libraries\n    try:\n        import pdfplumber\n        with pdfplumber.open(pdf_path) as pdf:\n            text = ''.join(page.extract_text() or '' for page in pdf.pages)\n        if text.strip():\n            return text, 'pdfplumber'\n    except Exception:\n        pass\n    \n    # Tier 3: OCR fallback\n    try:\n        from pdf2image import convert_from_path\n        import pytesseract\n        images = convert_from_path(pdf_path)\n        text = ''.join(pytesseract.image_to_string(img) for img in images)\n        if text.strip():\n            return text, 'tesseract-ocr'\n    except Exception:\n        pass\n    \n    raise ExtractionError(\"All extraction methods failed\")\n```\n\n## Decision Criteria\n\n| Indicator | Action |\n|-----------|--------|\n| Empty output | Proceed to next tier |\n| Garbled\u002Fspecial characters | Try next tier |\n| Partial content | Accept if meets minimum threshold |\n| Tool not available | Skip to next tier |\n| Format-specific errors | Try alternative library |\n\n## Best Practices\n\n1. **Validate each attempt** - Check output length and quality before accepting\n2. **Log which method succeeded** - Track which tier worked for future reference\n3. **Set minimum content thresholds** - Don't accept trivial results (e.g., \u003C50 chars)\n4. **Combine methods if needed** - Some documents need multiple approaches for different sections\n5. **Preserve original file** - Never modify the source PDF during extraction attempts\n\n## Error Handling\n\n- Catch exceptions at each tier, don't fail immediately\n- Log detailed error messages for debugging\n- Continue to next tier even if current tier partially succeeds but produces poor quality\n- After all tiers fail, provide clear summary of what was tried\n\n## Output Quality Check\n\nBefore declaring extraction complete:\n\n```python\ndef validate_extraction(text):\n    if not text or len(text.strip()) \u003C 50:\n        return False\n    if text.count('') > len(text) * 0.1:  # Too many replacement chars\n        return False\n    if len(set(text)) \u003C 10:  # Too little character variety\n        return False\n    return True\n```","# PDF Extraction Fallback Strategy\n\n## Purpose\n\nWhen processing complex documents (tax forms, legal documents, scanned materials), PDF extraction often fails on the first attempt. This skill provides a systematic fallback approach that tries multiple extraction methods in sequence until one succeeds.\n\n## When to Use\n\n- Initial PDF reading tools return errors or empty content\n- Document appears to be scanned\u002Fimage-based rather than text-based\n- Previous extraction attempts produced incomplete or garbled output\n- Working with forms, tables, or structured documents that need reliable extraction\n\n## Fallback Sequence\n\n### Tier 1: Shell-Based Extraction (pdftotext)\n\nStart with command-line tools that often handle edge cases better:\n\n```bash\n# Extract text maintaining layout\npdftotext -layout input.pdf output.txt\n\n# Extract raw text (faster, less formatting)\npdftotext input.pdf output.txt\n\n# Extract specific page range\npdftotext -f 1 -l 3 input.pdf output.txt\n```\n\nCheck if output contains meaningful content before proceeding.\n\n### Tier 2: Python-Based Parsing\n\nIf shell tools fail, use Python libraries with different extraction approaches:\n\n```python\n# Using PyPDF2 for basic text extraction\nimport PyPDF2\nwith open('document.pdf', 'rb') as f:\n    reader = PyPDF2.PdfReader(f)\n    text = ''.join(page.extract_text() for page in reader.pages)\n\n# Using pdfplumber for tables and structured content\nimport pdfplumber\nwith pdfplumber.open('document.pdf') as pdf:\n    for page in pdf.pages:\n        text = page.extract_text()\n        tables = page.extract_tables()\n\n# Using pypdf for newer PDF features\nfrom pypdf import PdfReader\nreader = PdfReader('document.pdf')\ntext = ''.join(page.extract_text() for page in reader.pages)\n```\n\n### Tier 3: OCR Tools (for Scanned Documents)\n\nIf the PDF contains images or scanned content, use OCR:\n\n```bash\n# Using tesseract via command line\ntesseract input.pdf output --psm 6\n\n# Using Python with pytesseract\nimport pytesseract\nfrom pdf2image import convert_from_path\n\nimages = convert_from_path('document.pdf')\ntext = ''.join(pytesseract.image_to_string(img) for img in images)\n```\n\n## Implementation Pattern\n\n```python\ndef extract_pdf_resilient(pdf_path):\n    \"\"\"Try multiple extraction methods until one succeeds.\"\"\"\n    \n    # Tier 1: Shell extraction\n    result = run_shell(f'pdftotext -layout \"{pdf_path}\" -')\n    if result.stdout and len(result.stdout.strip()) > 100:\n        return result.stdout, 'pdftotext'\n    \n    # Tier 2: Python libraries\n    try:\n        import pdfplumber\n        with pdfplumber.open(pdf_path) as pdf:\n            text = ''.join(page.extract_text() or '' for page in pdf.pages)\n        if text.strip():\n            return text, 'pdfplumber'\n    except Exception:\n        pass\n    \n    # Tier 3: OCR fallback\n    try:\n        from pdf2image import convert_from_path\n        import pytesseract\n        images = convert_from_path(pdf_path)\n        text = ''.join(pytesseract.image_to_string(img) for img in images)\n        if text.strip():\n            return text, 'tesseract-ocr'\n    except Exception:\n        pass\n    \n    raise ExtractionError(\"All extraction methods failed\")\n```\n\n## Decision Criteria\n\n| Indicator | Action |\n|-----------|--------|\n| Empty output | Proceed to next tier |\n| Garbled\u002Fspecial characters | Try next tier |\n| Partial content | Accept if meets minimum threshold |\n| Tool not available | Skip to next tier |\n| Format-specific errors | Try alternative library |\n\n## Best Practices\n\n1. **Validate each attempt** - Check output length and quality before accepting\n2. **Log which method succeeded** - Track which tier worked for future reference\n3. **Set minimum content thresholds** - Don't accept trivial results (e.g., \u003C50 chars)\n4. **Combine methods if needed** - Some documents need multiple approaches for different sections\n5. **Preserve original file** - Never modify the source PDF during extraction attempts\n\n## Error Handling\n\n- Catch exceptions at each tier, don't fail immediately\n- Log detailed error messages for debugging\n- Continue to next tier even if current tier partially succeeds but produces poor quality\n- After all tiers fail, provide clear summary of what was tried\n\n## Output Quality Check\n\nBefore declaring extraction complete:\n\n```python\ndef validate_extraction(text):\n    if not text or len(text.strip()) \u003C 50:\n        return False\n    if text.count('') > len(text) * 0.1:  # Too many replacement chars\n        return False\n    if len(set(text)) \u003C 10:  # Too little character variety\n        return False\n    return True\n```",{"name":5,"description":7},"main","6b84b0689ca0d9e7b1e4061188ff6b60758e0f8a","openspace\u002Fbenchmarks\u002Fgdpval\u002Fskills\u002Fpdf-extraction-fallback-7db3aa",941,"https:\u002F\u002Fgithub.com\u002FHKUDS\u002FAgentPilot","https:\u002F\u002Fgithub.com\u002FHKUDS","https:\u002F\u002Fsites.google.com\u002Fview\u002Fchaoh","2026-11-12 22:26:39",{"source":8,"skillName":5,"commands":47,"prompt":57,"zipAvailable":58},[48,51,54],{"tool":49,"command":50},"npx","npx skills add HKUDS\u002FAgentPilot --skill pdf-extraction-fallback-7db3aa",{"tool":52,"command":53},"bunx","bunx skills add HKUDS\u002FAgentPilot --skill pdf-extraction-fallback-7db3aa",{"tool":55,"command":56},"pnpm","pnpm dlx skills add HKUDS\u002FAgentPilot --skill pdf-extraction-fallback-7db3aa","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002FHKUDS\u002FAgentPilot\u002Fblob\u002Fmain\u002Fopenspace\u002Fbenchmarks\u002Fgdpval\u002Fskills\u002Fpdf-extraction-fallback-7db3aa\u002FSKILL.md",true,[60],{"path":61,"resourceType":62,"resourceTypeDesc":63,"sizeBytes":64,"sourceHtmlUrl":65},".skill_id","OTHER","其他",44,"https:\u002F\u002Fgithub.com\u002FHKUDS\u002FAgentPilot\u002Fblob\u002Fmain\u002Fopenspace\u002Fbenchmarks\u002Fgdpval\u002Fskills\u002Fpdf-extraction-fallback-7db3aa\u002F.skill_id",[67,86,105,128,152,175],{"skillNo":68,"name":69,"nameZh":6,"description":70,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":71,"categories":72,"keywords":73,"publishedAt":33},"01M6HYB297NDABRERJRVG0K8R0","agentpilot","Set up AgentPilot and use its single entry to prepare missing inputs and run configured RSI experiments. Use when the user requests AgentPilot installation or work with AgentPilot.","https:\u002F\u002Fgithub.com\u002FHKUDS\u002FAgentPilot\u002Fblob\u002Fmain\u002Fplugins\u002Fagentpilot\u002Fskills\u002Fagentpilot\u002FSKILL.md",[],[69,74,75,31,76,77,78,79,80,81,82,83,84,85],"prepare","requests","missing","installation","rsi","up","use","user","work","SET","run","experiments",{"skillNo":87,"name":88,"nameZh":6,"description":89,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":90,"categories":91,"keywords":92,"publishedAt":33},"01M6HYAYWXTTE1J7DJM0MFNQ4H","remember","Review auto-memory entries and propose promotions to OPENSPACE.md, OPENSPACE.local.md, or retained auto-memory topics; detect duplicates, stale facts, conflicts, and ambiguous entries before making changes.","https:\u002F\u002Fgithub.com\u002FHKUDS\u002FAgentPilot\u002Fblob\u002Fmain\u002Fopenspace\u002Fopenspace\u002Fskills\u002Fremember\u002FSKILL.md",[],[88,93,94,95,96,97,98,99,100,101,102,103,104],"memory","review","auto","openspace","changes","facts","detect","entries","local","conflicts","stale","duplicates",{"skillNo":106,"name":107,"nameZh":6,"description":108,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":109,"categories":110,"keywords":114,"publishedAt":33},"01M6HYAVMPM4SBDV60R2B5HPV8","skill-discovery","Search reusable OpenSpace skills locally, and browse cloud packages step by step when a cloud skill may help. Reusing proven skills saves tokens, improves reliability, and extends your capabilities beyond built-in tools.","https:\u002F\u002Fgithub.com\u002FHKUDS\u002FAgentPilot\u002Fblob\u002Fmain\u002Fopenspace\u002Fopenspace\u002Fhost_skills\u002Fskill-discovery\u002FSKILL.md",[111],{"categoryNo":112,"categoryName":113,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000023","Skill与智能体开发",[115,116,117,96,118,119,120,121,122,123,124,125,126,127],"skill discovery","discovery","reusable","step by step","tokens","packages","help","cloud","reliability","capabilities","browse","search","Tools",{"skillNo":129,"name":130,"nameZh":6,"description":131,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":132,"categories":133,"keywords":135,"publishedAt":33},"01M6HYAR811B3RB0M50RBEDGN6","delegate-task","Delegate tasks to OpenSpace — a full-stack autonomous worker for coding, DevOps, web research, and desktop automation, backed by an extensive MCP tool and skill library. Skills auto-improve through use, reducing token consumption over time. A cloud community lets agents share and collectively evolve reusable skills.","https:\u002F\u002Fgithub.com\u002FHKUDS\u002FAgentPilot\u002Fblob\u002Fmain\u002Fopenspace\u002Fopenspace\u002Fhost_skills\u002Fdelegate-task\u002FSKILL.md",[134],{"categoryNo":112,"categoryName":113,"taxonomyType":21,"taxonomyTypeDesc":22},[136,137,138,96,139,140,141,142,143,117,95,80,144,145,146,147,148,149,150,151],"delegate","task","delegate task","time","improve","desktop automation","worker","community","autonomous","tool","stack","for","share","tasks","automation","MCP",{"skillNo":153,"name":154,"nameZh":6,"description":155,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":156,"categories":157,"keywords":158,"publishedAt":33},"01M6HYAM9FSGV6E52AYENDQXYH","write-special-chars-ts-check","Workaround for write_file failures caused by special characters (apostrophes, backticks, template literals) using a Python heredoc script, plus a reliable TypeScript type-checking step that filters output to only the newly-written files to avoid being misled by pre-existing errors.","https:\u002F\u002Fgithub.com\u002FHKUDS\u002FAgentPilot\u002Fblob\u002Fmain\u002Fopenspace\u002Flegacy\u002Fv1\u002Fshowcase\u002Fskills\u002Fwrite-special-chars-ts-check\u002FSKILL.md",[],[159,160,161,162,163,164,165,166,167,168,169,170,171,172,147,173,174],"write special chars ts check","write","check","type","files","filters","only","template","file","python","typescript","output","Existing","type-checking","errors","script",{"skillNo":176,"name":177,"nameZh":6,"description":178,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":179,"categories":180,"keywords":181,"publishedAt":33},"01M6HYAH05HGV7SVWSVR8PJRQD","write-special-chars-readback","Workaround for write_file failures caused by special characters (apostrophes, backticks, template literals) using a Python heredoc script, with mandatory post-write verification via read_file and cleanup of \u002Ftmp helper scripts.","https:\u002F\u002Fgithub.com\u002FHKUDS\u002FAgentPilot\u002Fblob\u002Fmain\u002Fopenspace\u002Flegacy\u002Fv1\u002Fshowcase\u002Fskills\u002Fwrite-special-chars-readback\u002FSKILL.md",[],[182,183,160,31,147,174,184,185,186,187,188,166,167,189,190,168],"write special chars readback","readback","helper","post","via","scripts","read","verification","cleanup"]