[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M6HXQFADDKBKX2B57E0MB809":3,"skill-same:01M6HXQFADDKBKX2B57E0MB809":68},{"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":35,"linkOnly":36,"markdownContent":37,"markdownBody":38,"frontMatter":39,"refName":40,"commitSha":41,"skillDirectory":42,"forksCount":43,"repositoryHtmlUrl":44,"repositoryHomepageUrl":6,"ownerHtmlUrl":45,"ownerBlogUrl":46,"ownerDescription":6,"updatedAt":47,"install":48,"resources":61},"01M6HXQFADDKBKX2B57E0MB809","pdf-extraction-fallback",null,"Multi-stage fallback strategy for PDF\u002Fdocument extraction using sequential tool alternatives","HKUDS\u002FAgentPilot","HKUDS","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F118165258?v=4","01M6HW8VRNZP64G0P4MVJW2KKQ","✨Data Intelligence Lab@HKU✨","01M6HW8VWZVHBRHYH3T330PFWV",8029,"MIT","https:\u002F\u002Fgithub.com\u002FHKUDS\u002FAgentPilot\u002Fblob\u002Fmain\u002Fopenspace\u002Flegacy\u002Fv1\u002Fgdpval_bench\u002Fskills\u002Fpdf-extraction-fallback\u002FSKILL.md",[18],{"categoryNo":19,"categoryName":20,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000002","文档处理","SCENARIO","使用场景",[24,25,26,27,28,29,30,31,32,33,34],"PDF","extraction","fallback","pdf extraction","pdf extraction fallback","tool","strategy","document","stage","multi","for","2026-11-10 10:12:30",false,"---\nname: pdf-extraction-fallback\ndescription: Multi-stage fallback strategy for PDF\u002Fdocument extraction using sequential tool alternatives\n---\n\n# PDF Extraction Fallback Strategy\n\nWhen processing documents (especially PDFs), initial extraction attempts may fail due to formatting, encryption, or tool limitations. This skill provides a systematic fallback approach that tries multiple extraction methods before declaring failure.\n\n## Core Principle\n\n**Never declare completion after a single tool failure.** Instead, iterate through a hierarchy of extraction methods, each with different capabilities and limitations.\n\n## Fallback Hierarchy\n\nAttempt extraction methods in this order:\n\n### Stage 1: Direct PDF Reading\nTry native PDF libraries first (fastest, preserves structure):\n```python\nimport PyPDF2\nfrom pypdf import PdfReader\n\ndef extract_with_pypdf(pdf_path):\n    reader = PdfReader(pdf_path)\n    text = \"\"\n    for page in reader.pages:\n        text += page.extract_text() or \"\"\n    return text\n```\n\n### Stage 2: Shell-based Extraction (pdftotext)\nIf Stage 1 fails, use system tools:\n```bash\n# Install if needed: apt-get install poppler-utils\npdftotext -layout input.pdf output.txt\npdftotext -raw input.pdf output.txt  # Alternative layout\n```\n\n```python\nimport subprocess\n\ndef extract_with_pdftotext(pdf_path):\n    result = subprocess.run(\n        ['pdftotext', '-layout', pdf_path, '-'],\n        capture_output=True, text=True\n    )\n    if result.returncode == 0:\n        return result.stdout\n    raise Exception(\"pdftotext failed\")\n```\n\n### Stage 3: Alternative Python Parsers\nTry different Python libraries with varying capabilities:\n```python\n# pdfplumber - better for tables\nimport pdfplumber\ndef extract_with_pdfplumber(pdf_path):\n    text = \"\"\n    with pdfplumber.open(pdf_path) as pdf:\n        for page in pdf.pages:\n            text += page.extract_text() or \"\"\n    return text\n\n# pdfminer - handles complex layouts\nfrom pdfminer.high_level import extract_text\ndef extract_with_pdfminer(pdf_path):\n    return extract_text(pdf_path)\n```\n\n### Stage 4: OCR Fallback\nFor scanned images or when text extraction fails:\n```bash\n# Using tesseract\nconvert input.pdf output-%d.png  # Convert to images first\ntesseract output-0.png result --psm 6\n```\n\n```python\n# Using pytesseract\nfrom pdf2image import convert_from_path\nimport pytesseract\n\ndef extract_with_ocr(pdf_path):\n    images = convert_from_path(pdf_path, dpi=300)\n    text = \"\"\n    for image in images:\n        text += pytesseract.image_to_string(image)\n    return text\n```\n\n## Implementation Pattern\n\n```python\ndef robust_pdf_extraction(pdf_path):\n    \"\"\"Try multiple extraction methods until one succeeds.\"\"\"\n    \n    extraction_methods = [\n        (\"PyPDF2\", extract_with_pypdf),\n        (\"pdftotext\", extract_with_pdftotext),\n        (\"pdfplumber\", extract_with_pdfplumber),\n        (\"pdfminer\", extract_with_pdfminer),\n        (\"OCR\", extract_with_ocr),\n    ]\n    \n    errors = []\n    for method_name, method_func in extraction_methods:\n        try:\n            print(f\"Trying {method_name}...\")\n            text = method_func(pdf_path)\n            if text and text.strip():\n                print(f\"Success with {method_name}\")\n                return text\n            else:\n                errors.append(f\"{method_name}: empty result\")\n        except Exception as e:\n            errors.append(f\"{method_name}: {str(e)}\")\n            print(f\"{method_name} failed: {e}\")\n            continue\n    \n    # All methods failed\n    raise Exception(f\"All extraction methods failed:\\n\" + \"\\n\".join(errors))\n```\n\n## Success Criteria\n\nA method is considered successful when:\n1. **No exceptions** are raised during execution\n2. **Non-empty text** is returned (text.strip() has content)\n3. **Content quality** meets task requirements (check for expected keywords\u002Fpatterns)\n\n## Best Practices\n\n1. **Log each attempt** - Record which methods were tried and why they failed\n2. **Validate output** - Check extracted text contains expected content markers\n3. **Graceful degradation** - Proceed with partial data if full extraction isn't possible\n4. **Cache successful method** - Remember which method worked for similar files\n5. **Set timeouts** - Prevent OCR or complex parsing from hanging indefinitely\n\n## Common Failure Modes\n\n| Symptom | Likely Cause | Best Fallback |\n|---------|--------------|---------------|\n| Empty pages | Image-based PDF | OCR (Stage 4) |\n| Garbled text | Encoding issues | pdftotext (Stage 2) |\n| Missing tables | Simple parser | pdfplumber (Stage 3) |\n| Permission errors | Encrypted PDF | Check password\u002Fpermissions first |\n| Layout lost | Complex formatting | pdftotext -layout or pdfplumber |\n\n## When to Use\n\n- Processing unknown\u002Funtrusted PDF sources\n- Batch processing diverse document types\n- Critical tasks where extraction failure is not acceptable\n- Documents with mixed content (text + images + tables)","# PDF Extraction Fallback Strategy\n\nWhen processing documents (especially PDFs), initial extraction attempts may fail due to formatting, encryption, or tool limitations. This skill provides a systematic fallback approach that tries multiple extraction methods before declaring failure.\n\n## Core Principle\n\n**Never declare completion after a single tool failure.** Instead, iterate through a hierarchy of extraction methods, each with different capabilities and limitations.\n\n## Fallback Hierarchy\n\nAttempt extraction methods in this order:\n\n### Stage 1: Direct PDF Reading\nTry native PDF libraries first (fastest, preserves structure):\n```python\nimport PyPDF2\nfrom pypdf import PdfReader\n\ndef extract_with_pypdf(pdf_path):\n    reader = PdfReader(pdf_path)\n    text = \"\"\n    for page in reader.pages:\n        text += page.extract_text() or \"\"\n    return text\n```\n\n### Stage 2: Shell-based Extraction (pdftotext)\nIf Stage 1 fails, use system tools:\n```bash\n# Install if needed: apt-get install poppler-utils\npdftotext -layout input.pdf output.txt\npdftotext -raw input.pdf output.txt  # Alternative layout\n```\n\n```python\nimport subprocess\n\ndef extract_with_pdftotext(pdf_path):\n    result = subprocess.run(\n        ['pdftotext', '-layout', pdf_path, '-'],\n        capture_output=True, text=True\n    )\n    if result.returncode == 0:\n        return result.stdout\n    raise Exception(\"pdftotext failed\")\n```\n\n### Stage 3: Alternative Python Parsers\nTry different Python libraries with varying capabilities:\n```python\n# pdfplumber - better for tables\nimport pdfplumber\ndef extract_with_pdfplumber(pdf_path):\n    text = \"\"\n    with pdfplumber.open(pdf_path) as pdf:\n        for page in pdf.pages:\n            text += page.extract_text() or \"\"\n    return text\n\n# pdfminer - handles complex layouts\nfrom pdfminer.high_level import extract_text\ndef extract_with_pdfminer(pdf_path):\n    return extract_text(pdf_path)\n```\n\n### Stage 4: OCR Fallback\nFor scanned images or when text extraction fails:\n```bash\n# Using tesseract\nconvert input.pdf output-%d.png  # Convert to images first\ntesseract output-0.png result --psm 6\n```\n\n```python\n# Using pytesseract\nfrom pdf2image import convert_from_path\nimport pytesseract\n\ndef extract_with_ocr(pdf_path):\n    images = convert_from_path(pdf_path, dpi=300)\n    text = \"\"\n    for image in images:\n        text += pytesseract.image_to_string(image)\n    return text\n```\n\n## Implementation Pattern\n\n```python\ndef robust_pdf_extraction(pdf_path):\n    \"\"\"Try multiple extraction methods until one succeeds.\"\"\"\n    \n    extraction_methods = [\n        (\"PyPDF2\", extract_with_pypdf),\n        (\"pdftotext\", extract_with_pdftotext),\n        (\"pdfplumber\", extract_with_pdfplumber),\n        (\"pdfminer\", extract_with_pdfminer),\n        (\"OCR\", extract_with_ocr),\n    ]\n    \n    errors = []\n    for method_name, method_func in extraction_methods:\n        try:\n            print(f\"Trying {method_name}...\")\n            text = method_func(pdf_path)\n            if text and text.strip():\n                print(f\"Success with {method_name}\")\n                return text\n            else:\n                errors.append(f\"{method_name}: empty result\")\n        except Exception as e:\n            errors.append(f\"{method_name}: {str(e)}\")\n            print(f\"{method_name} failed: {e}\")\n            continue\n    \n    # All methods failed\n    raise Exception(f\"All extraction methods failed:\\n\" + \"\\n\".join(errors))\n```\n\n## Success Criteria\n\nA method is considered successful when:\n1. **No exceptions** are raised during execution\n2. **Non-empty text** is returned (text.strip() has content)\n3. **Content quality** meets task requirements (check for expected keywords\u002Fpatterns)\n\n## Best Practices\n\n1. **Log each attempt** - Record which methods were tried and why they failed\n2. **Validate output** - Check extracted text contains expected content markers\n3. **Graceful degradation** - Proceed with partial data if full extraction isn't possible\n4. **Cache successful method** - Remember which method worked for similar files\n5. **Set timeouts** - Prevent OCR or complex parsing from hanging indefinitely\n\n## Common Failure Modes\n\n| Symptom | Likely Cause | Best Fallback |\n|---------|--------------|---------------|\n| Empty pages | Image-based PDF | OCR (Stage 4) |\n| Garbled text | Encoding issues | pdftotext (Stage 2) |\n| Missing tables | Simple parser | pdfplumber (Stage 3) |\n| Permission errors | Encrypted PDF | Check password\u002Fpermissions first |\n| Layout lost | Complex formatting | pdftotext -layout or pdfplumber |\n\n## When to Use\n\n- Processing unknown\u002Funtrusted PDF sources\n- Batch processing diverse document types\n- Critical tasks where extraction failure is not acceptable\n- Documents with mixed content (text + images + tables)",{"name":5,"description":7},"main","6b84b0689ca0d9e7b1e4061188ff6b60758e0f8a","openspace\u002Flegacy\u002Fv1\u002Fgdpval_bench\u002Fskills\u002Fpdf-extraction-fallback",944,"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":49,"prompt":59,"zipAvailable":60},[50,53,56],{"tool":51,"command":52},"npx","npx skills add HKUDS\u002FAgentPilot --skill pdf-extraction-fallback",{"tool":54,"command":55},"bunx","bunx skills add HKUDS\u002FAgentPilot --skill pdf-extraction-fallback",{"tool":57,"command":58},"pnpm","pnpm dlx skills add HKUDS\u002FAgentPilot --skill pdf-extraction-fallback","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002FHKUDS\u002FAgentPilot\u002Fblob\u002Fmain\u002Fopenspace\u002Flegacy\u002Fv1\u002Fgdpval_bench\u002Fskills\u002Fpdf-extraction-fallback\u002FSKILL.md",true,[62],{"path":63,"resourceType":64,"resourceTypeDesc":65,"sizeBytes":66,"sourceHtmlUrl":67},".skill_id","OTHER","其他",37,"https:\u002F\u002Fgithub.com\u002FHKUDS\u002FAgentPilot\u002Fblob\u002Fmain\u002Fopenspace\u002Flegacy\u002Fv1\u002Fgdpval_bench\u002Fskills\u002Fpdf-extraction-fallback\u002F.skill_id",[69,89,108,131,153,176],{"skillNo":70,"name":71,"nameZh":6,"description":72,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":73,"categories":74,"keywords":75,"publishedAt":35},"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",[],[71,76,77,78,79,80,81,82,83,84,85,86,87,88],"prepare","requests","with","missing","installation","rsi","up","use","user","work","SET","run","experiments",{"skillNo":90,"name":91,"nameZh":6,"description":92,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":93,"categories":94,"keywords":95,"publishedAt":35},"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",[],[91,96,97,98,99,100,101,102,103,104,105,106,107],"memory","review","auto","openspace","changes","facts","detect","entries","local","conflicts","stale","duplicates",{"skillNo":109,"name":110,"nameZh":6,"description":111,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":112,"categories":113,"keywords":117,"publishedAt":35},"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",[114],{"categoryNo":115,"categoryName":116,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000023","Skill与智能体开发",[118,119,120,99,121,122,123,124,125,126,127,128,129,130],"skill discovery","discovery","reusable","step by step","tokens","packages","help","cloud","reliability","capabilities","browse","search","Tools",{"skillNo":132,"name":133,"nameZh":6,"description":134,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":135,"categories":136,"keywords":138,"publishedAt":35},"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",[137],{"categoryNo":115,"categoryName":116,"taxonomyType":21,"taxonomyTypeDesc":22},[139,140,141,99,142,143,144,145,146,120,98,83,147,29,148,34,149,150,151,152],"delegate","task","delegate task","time","improve","desktop automation","worker","community","autonomous","stack","share","tasks","automation","MCP",{"skillNo":154,"name":155,"nameZh":6,"description":156,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":157,"categories":158,"keywords":159,"publishedAt":35},"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",[],[160,161,162,163,164,165,166,167,168,169,170,171,172,173,34,174,175],"write special chars ts check","write","check","type","files","filters","only","template","file","python","typescript","output","Existing","type-checking","errors","script",{"skillNo":177,"name":178,"nameZh":6,"description":179,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":180,"categories":181,"keywords":182,"publishedAt":35},"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",[],[183,184,161,78,34,175,185,186,187,188,189,167,168,190,191,169],"write special chars readback","readback","helper","post","via","scripts","read","verification","cleanup"]