diff --git a/paperforge/plugin/main.js b/paperforge/plugin/main.js
index a4376856..8b02390e 100644
--- a/paperforge/plugin/main.js
+++ b/paperforge/plugin/main.js
@@ -1,11 +1,11 @@
-"use strict";var Dt=Object.create;var ze=Object.defineProperty;var Rt=Object.getOwnPropertyDescriptor;var Bt=Object.getOwnPropertyNames;var At=Object.getPrototypeOf,Ot=Object.prototype.hasOwnProperty;var Lt=(g,u)=>()=>(u||g((u={exports:{}}).exports,u),u.exports),Mt=(g,u)=>{for(var e in u)ze(g,e,{get:u[e],enumerable:!0})},pt=(g,u,e,t)=>{if(u&&typeof u=="object"||typeof u=="function")for(let r of Bt(u))!Ot.call(g,r)&&r!==e&&ze(g,r,{get:()=>u[r],enumerable:!(t=Rt(u,r))||t.enumerable});return g};var q=(g,u,e)=>(e=g!=null?Dt(At(g)):{},pt(u||!g||!g.__esModule?ze(e,"default",{value:g,enumerable:!0}):e,g)),It=g=>pt(ze({},"__esModule",{value:!0}),g);var Xe=Lt((Wt,zt)=>{zt.exports={versions:[{version:"1.5.15",date:"2026-06-01",title:"\u5168\u6587\u5B58\u50A8\u91CD\u6784 + OCR \u9605\u8BFB\u987A\u5E8F\u4FEE\u590D + Redo \u4E00\u952E\u91CD\u505A",breaking_or_migration:["\u5168\u6587\u6587\u4EF6\u73B0\u5728\u7EDF\u4E00\u5B58\u653E\u4E8E System/PaperForge/ocr/ \u4E0B\uFF0C\u4E0D\u518D\u5728\u5DE5\u4F5C\u533A\u4FDD\u7559\u526F\u672C","Redo OCR \u73B0\u5728\u4F1A\u7ACB\u5373\u6267\u884C\uFF08\u4E00\u952E\u5B8C\u6210\uFF09\uFF0C\u4E0D\u518D\u9700\u8981\u624B\u52A8\u518D\u8DD1\u4E00\u6B21"],new_features:["Redo OCR \u4E00\u952E\u95ED\u73AF\uFF1A\u52FE\u9009 \u2192 \u70B9\u6309\u94AE \u2192 \u81EA\u52A8\u5B8C\u6210\u5168\u90E8\u6D41\u7A0B","\u8BBE\u7F6E\u9875\u65B0\u589E\u300C\u66F4\u65B0\u4E0E\u624B\u518C\u300D\u6807\u7B7E\u9875\uFF0C\u53EF\u968F\u65F6\u67E5\u770B\u7248\u672C\u66F4\u65B0\u8BB0\u5F55\u548C\u4F7F\u7528\u624B\u518C","\u63D2\u4EF6\u66F4\u65B0\u540E\u81EA\u52A8\u5F39\u51FA\u66F4\u65B0\u8BF4\u660E"],fixes:["\u4FEE\u590D\u5168\u6587\u9605\u8BFB\u987A\u5E8F\u6DF7\u4E71\uFF0C\u4F18\u5316\u6574\u4F53\u6392\u7248\u4F53\u9A8C","\u4FEE\u590D\u7AE0\u8282\u6807\u9898\u548C\u6B63\u6587\u6BB5\u843D\u9519\u4F4D\u65AD\u5F00\u7684\u95EE\u9898","\u4FEE\u590D\u56FE\u8868\u548C\u5BF9\u5E94\u56FE\u6CE8\u88AB\u5206\u5F00\u7684\u95EE\u9898","\u4FEE\u590D\u9996\u9875\u6458\u8981\u533A\u5757\u6392\u5E8F\u5F02\u5E38","\u4FEE\u590D\u5E76\u6392\u56FE\u7247\u672A\u80FD\u81EA\u52A8\u5408\u5E76\u7684\u95EE\u9898","Dashboard \u73B0\u5728\u80FD\u6B63\u786E\u8BC6\u522B\u65B0\u7684\u5168\u6587\u6587\u4EF6\u4F4D\u7F6E"],recommended_actions:["\u65E7\u7248 OCR \u5168\u6587\u53EF\u80FD\u5B58\u5728\u9605\u8BFB\u987A\u5E8F\u95EE\u9898\uFF0C\u5EFA\u8BAE\u5BF9\u91CD\u8981\u8BBA\u6587\u6267\u884C\u4E00\u6B21 Redo OCR","\u6253\u5F00\u5168\u6587\u8BF7\u76F4\u63A5\u4F7F\u7528 Dashboard \u7684\u300C\u6253\u5F00\u5168\u6587\u300D\u6309\u94AE"]}]}});var Ht={};Mt(Ht,{default:()=>Ze});module.exports=It(Ht);var H=require("obsidian"),j=q(require("fs")),Se=q(require("path")),ce=require("child_process");var ye="paperforge-status",Be="paperforge",dt='',X=[{id:"paperforge-sync",title:"Sync Library",desc:"Pull new references from Zotero and generate literature notes",icon:"\u21BB",cmd:"sync",okMsg:"Sync complete"},{id:"paperforge-ocr",title:"Run OCR",desc:"Extract full text and figures from PDFs via PaddleOCR",icon:"\u229E",cmd:"ocr",okMsg:"OCR started"},{id:"paperforge-doctor",title:"Run Doctor",desc:"Verify PaperForge setup \u2014 check configs, Zotero, paths, and index health",icon:"\u2695",cmd:"doctor",okMsg:"Doctor complete"},{id:"paperforge-repair",title:"Repair Issues",desc:"Fix three-way state divergence, path errors, and rebuild index",icon:"\u21BA",cmd:"repair",args:["--fix","--fix-paths"],okMsg:"Repair complete"},{id:"paperforge-ocr-redo",title:"Redo OCR",desc:"Re-run OCR for papers marked ocr_redo: true",icon:"\u21BA",cmd:"ocr",args:["redo"],okMsg:"OCR redo started"}],Ae={vault_path:"",setup_complete:!1,auto_update:!0,auto_update_on_startup:!0,agent_platform:"opencode",language:"",paddleocr_api_key:"",zotero_data_dir:"",python_path:"",features:{memory_layer:!0,vector_db:!1},selected_skill_platform:"opencode",vector_db_api_key:"",vector_db_api_base:"",vector_db_api_model:"text-embedding-3-small",frozen_skills:{},system_dir:"",resources_dir:"",literature_dir:"",base_dir:"",last_seen_version:""};function ut(g,u){if(!u||!u.note_path)return u;let e=g.vault.getAbstractFileByPath(u.note_path);if(!e)return u;let t=g.metadataCache.getFileCache(e),r=t&&t.frontmatter;if(!r)return u;let n={...u};for(let a of["do_ocr","analyze","ocr_status","ocr_redo","deep_reading_status"])Object.prototype.hasOwnProperty.call(r,a)&&(n[a]=r[a]);return n}function Je(g,u){return g&&{...g,...u}}var Ue={en:{action_running:"Running ",api_key_missing:"Missing",api_key_set:"Entered",btn_install:"Open Setup Wizard",btn_install_desc:"Check whether the environment is ready, then open the step-by-step setup wizard",btn_reconfig:"Reconfigure",btn_reconfig_desc:"Open the setup wizard again to change directories, platform, or API keys",btn_validate:"Validate",check_bbt_fail:"Not detected",check_bbt_ok:"Installed",check_python_fail:"Not found",check_python_ok:"Ready",check_zotero_fail:"Not detected",check_zotero_ok:"Found",complete_export_path:"Save Better BibTeX JSON exports into:",complete_next:"Recommended next steps",complete_step1:"Open Dashboard",complete_step1_desc:'Press Ctrl+P and run "PaperForge: Open Main Panel", or click the PaperForge icon in the left sidebar.',complete_step2:"Sync Literature",complete_step2_desc:"In the main panel, click Sync Library to bring papers from Zotero into Obsidian and generate notes.",complete_step3:"Run OCR",complete_step3_desc:"In the Obsidian Base view, mark do_ocr:true on papers, then run OCR in the main panel.",complete_step4:"Configure Better BibTeX Auto-export",complete_step4_desc:'In Zotero, right-click the library or collection you want to sync -> Export -> Better BibTeX JSON -> enable "Keep updated".',complete_summary:"Saved Configuration",complete_title:"Setup Complete",copied:"Copied!",copy_pf_deep_cmd:"Copy /pf-deep Command",dashboard_drift_warning:"PaperForge CLI (v{0}) differs from plugin (v{1}). Open Settings \u2192 Runtime Health to sync.",deep_reading_not_found:"Deep reading file not found",desc:"Obsidian + Zotero literature pipeline. Sync papers, generate notes, run OCR, and read deeply in one place.",dir_base:"Base Dir",dir_index:"Index Dir",dir_notes:"Notes Dir",dir_resources:"Resource Dir",dir_system:"System Dir",dir_vault:"Vault Path",error_copied:"Copied!",error_copy_diagnostic:"Copy diagnostic",feat_agent_platform:"Agent Platform",feat_agent_platform_desc:"Select which agent platform to manage skills for.",feat_api_base_url:"API Base URL",feat_api_base_url_desc:"Custom OpenAI-compatible API endpoint. Leave empty for default.",feat_api_model:"API Model",feat_api_model_desc:"Embedding model name for this endpoint.",feat_build_btn:"Build",feat_build_complete:"Vector build complete.",feat_build_failed:"Build failed. See terminal output.",feat_building:"Building...",feat_cache_remove_failed:"Failed: {0}",feat_cache_removed:"Model cache removed.",feat_checking:"Checking...",feat_checking_btn:"Checking...",feat_deps_checking:"Checking dependencies...",feat_deps_missing:"Dependencies not installed. Required: chromadb, openai.",feat_enter_key:"Enter a valid OpenAI API key.",feat_install_btn:"Install",feat_install_deps:"Install Dependencies",feat_install_deps_desc:"pip install chromadb openai (~35MB).",feat_install_done:"Dependencies installed. Building vectors...",feat_install_failed:"Install failed: ",feat_installing:"Installing...",feat_installing_pkgs:"Installing {pkgs}...",feat_key_rejected:"API key rejected.",feat_memory_desc:"The Memory Layer is the core data engine of PaperForge, powered by SQLite. It integrates literature metadata (papers, assets, aliases, reading events), provides FTS5 metadata search across titles, abstracts, authors, domains, and collections, and powers agent-context and paper-status. Always active \u2014 no toggle needed.",feat_memory_rebuild_btn:"Rebuild",feat_memory_rebuild_done:"Memory DB rebuilt.",feat_memory_rebuild_failed:"Rebuild failed.",feat_memory_rebuilding:"Rebuilding...",feat_model_changed_warn:"Model changed ({0} -> {1}). Existing vectors are incompatible \u2014 rebuild required.",feat_network_error:"Network error: ",feat_no_python:"No Python found. Check Installation tab.",feat_not_cached:"Not cached",feat_openai_key:"OpenAI API Key",feat_openai_key_desc:"Used for API embedding calls. Model is defined below.",feat_output_copied:"Output copied to clipboard.",feat_rebuild_btn:"Rebuild",feat_rebuild_vectors:"Rebuild Vectors",feat_rebuild_vectors_changed:"Model changed \u2014 rebuild to update all vectors.",feat_rebuild_vectors_desc:"Rebuild all OCR fulltext vectors. Required after model or mode change.",feat_removing:"Removing...",feat_retry_btn:"Retry",feat_skills_desc:"Manage and enable/disable agent skills installed in your vault. Each row corresponds to a SKILL.md file \u2014 toggle off to prevent the agent from auto-invoking that skill.",feat_skills_system:"System Skills ship with PaperForge and are updated alongside PaperForge.",feat_skills_user:"User Skills are custom skills you install from community or create yourself.",feat_uninstall_btn:"Uninstall",feat_valid_key:"API key valid.",feat_vector_config_label:"Vector Settings",feat_vector_corrupted:"Vector index corrupted \u2014 needs force rebuild.",feat_vector_desc:"Vector Database enables semantic search across OCR-extracted fulltext via API embedding. Documents are split into chunks, embedded via OpenAI-compatible API, and stored in ChromaDB.",feat_vector_enable:"Enable Vector Retrieval",feat_vector_enable_desc:"Semantic search across OCR fulltext. Requires: pip install openai chromadb (~35MB).",feat_vector_rebuild_force_btn:"Force Rebuild",feat_verify:"Verify",feat_verify_btn:"Verify",field_paddleocr:"PaddleOCR API Key",field_python_custom:"Custom Path",field_python_interp:"Python Interpreter",field_zotero_data:"Zotero Data Dir",field_zotero_placeholder:"Required. Path to Zotero data directory for PDF attachment resolution.",guide_ocr:"Run OCR",guide_ocr_desc:"In the main panel, click Run OCR to extract full text and figures from PDFs for later reading and analysis.",guide_open:"Open Main Panel",guide_open_desc:'Press Ctrl+P and run "PaperForge: Open Main Panel", or click the PaperForge icon in the left sidebar.',guide_sync:"Sync Literature",guide_sync_desc:"After Better BibTeX JSON export is configured, click Sync Library to import papers from Zotero into Obsidian and generate notes automatically.",header_title:"PaperForge",install_bootstrapping:"PaperForge Python package not found. Installing automatically...",install_btn:"Start Install",install_btn_retry:"Retry",install_btn_running:"Installing...",install_complete:"Installation complete!",install_failed:"Installation failed: ",install_validating:"Validating setup...",jump_to_deep_reading:"Open Deep Reading",label_agent:"Agent Platform",nav_close:"Close",nav_next:"Next",nav_prev:"Back",not_set:"Not entered",notice_check_fail:"Missing: ",notice_python_missing:"Python was not detected. Install Python 3.10+ and add it to PATH.",ocr_privacy_title:"OCR Privacy Notice",ocr_privacy_warning:"OCR will upload PDFs to the PaddleOCR API. Do not upload sensitive or confidential documents.",ocr_queue_add:"Add to OCR Queue",ocr_queue_added:"Added to OCR queue",ocr_queue_remove:"Remove from OCR Queue",ocr_queue_removed:"Removed from OCR queue",ocr_understand:"I understand, continue",optional_later:"(can be set later in Settings)",orphan_delete_failed:"Prune failed",orphan_delete_selected:"Delete {count} selected",orphan_deleted:"Deleted {count} orphan workspace(s)",orphan_desc:"These papers are no longer in your Zotero library.",orphan_deselect_all:"Deselect all",orphan_explain:"Removed from Zotero. Workspace files remain on disk.",orphan_keep_all:"Keep all",orphan_none_selected:"No papers selected for deletion",orphan_select_all:"Select all",orphan_title:"Found {count} orphan paper(s)",panel_actions:"Quick Actions",prep_bbt:"Better BibTeX",prep_bbt_desc:"In Zotero: Tools -> Add-ons -> install Better BibTeX.",prep_export:"Better BibTeX Auto-export",prep_export_desc:'In Zotero, right-click the collection you want to sync -> Export Collection -> BetterBibTeX JSON -> enable "Keep updated" -> save the JSON file into the exports folder shown below. Obsidian Base views will use the JSON filename as the Base name:',prep_export_path_label:"Save the exported JSON file into this folder:",prep_key:"PaddleOCR Key",prep_key_desc:"Get your API key from https://aistudio.baidu.com/paddleocr",prep_python:"Python 3.10+",prep_python_desc:"Python must be available from the command line. If you are not sure, click below to auto-detect.",prep_zotero:"Zotero Desktop",prep_zotero_desc:"Install Zotero from https://www.zotero.org",run_in_agent:"Run in {0}",runtime_health:"Runtime Health",runtime_health_checking:"Checking...",runtime_health_desc:"Check whether the installed paperforge Python package matches the plugin version and whether the deployed skill contract is current.",runtime_health_match:"Match",runtime_health_mismatch:"Mismatch",runtime_health_package_ver:"Python package v{0}",runtime_health_plugin_ver:"Plugin v{0}",runtime_health_sync:"Sync Runtime",runtime_health_sync_done:"Runtime synced to v{0}",runtime_health_sync_fail:"Sync failed: {0}",runtime_health_syncing:"Syncing...",section_config:"Current Configuration",section_guide:"How To Use",section_prep:"Preparation",section_prep_desc:"Before first use, finish these 4 preparation items. Better BibTeX auto-export is configured after setup:",setup_done:"PaperForge environment is ready",setup_pending:"Not installed yet. Finish the preparation items below, then open the wizard.",tab_features:"Features",tab_setup:"Installation",tab_maintenance:"Maintenance",validate_base:"Base directory is required",validate_fail:"Please complete the required fields below",validate_index:"Index directory is required",validate_key:"PaddleOCR API key (optional, needed for OCR)",validate_notes:"Notes directory is required",validate_resources:"Resources directory is required",validate_system:"System directory is required",validate_vault:"Vault path is required",validate_zotero:"Zotero data directory (optional, needed for PDF linking)",wizard_agent_hint:"Choose the AI agent platform you use most often. PaperForge will place the matching command and skill files in the correct location.",wizard_dir_hint:"PaperForge stores user-facing literature data under the resources directory. These folders will live there:",wizard_dir_sub_hint:"Resolved folder preview based on the names below:",wizard_intro:"This wizard walks you through the full setup. In most cases, the default values are fine to keep.",wizard_keys_hint:"Enter your PaddleOCR API key below. If you want PaperForge to auto-locate Zotero PDFs, you can also fill in the Zotero data directory.",wizard_preview:"After installation, system files stay at the vault root while literature data stays under the resources directory.",wizard_safety:"Safety: if the selected folders already contain files, setup preserves existing files and only creates missing PaperForge folders and files.",wizard_step1:"Overview",wizard_step2:"Directory Setup",wizard_step3:"Platform & Keys",wizard_step4:"Install",wizard_step5:"Done",wizard_skip_ocr_desc:"OCR will not be available until you configure a valid PaddleOCR API key. You can continue setup now and configure it later in Settings.",wizard_skip_ocr_continue:"Continue without OCR key",wizard_skip_ocr_back:"Back to configure",wizard_api_hint_skip:"OCR key is optional \u2014 you may skip it and configure later.",wizard_sys_hint:"These folders live at the vault root, outside the resources directory:",wizard_title:"PaperForge Setup Wizard",ocr_maint_no_action:"No Action Needed",ocr_maint_rebuild:"Rebuild Recommended",ocr_maint_failed:"OCR Failed",ocr_maint_limited:"Result Limited",ocr_maint_needs_attention:"Needs Attention",ocr_maint_limitations:"Result Limitations",ocr_maint_hero_ok:"OCR looks usable overall.",ocr_maint_hero_warn:"OCR needs attention: {rebuild} rebuild recommended, {failed} failed.",ocr_maint_hero_note:"This page only promotes issues where maintenance is likely to help. Some papers may have limitations that maintenance will not improve.",ocr_maint_limitations_intro:"These papers look less certain, but PaperForge does not currently have a high-confidence maintenance action to recommend.",ocr_maint_all_papers:"All Papers",ocr_maint_rebuild_btn:"Rebuild results",ocr_maint_redo_btn:"Rerun OCR"},zh:{action_running:"\u6B63\u5728\u6267\u884C ",api_key_missing:"\u672A\u914D\u7F6E \u2717",api_key_set:"\u5DF2\u914D\u7F6E \u2713",btn_install:"\u6253\u5F00\u5B89\u88C5\u5411\u5BFC",btn_install_desc:"\u81EA\u52A8\u68C0\u6D4B Python + \u524D\u7F6E\u73AF\u5883\uFF0C\u901A\u8FC7\u540E\u6253\u5F00\u5206\u6B65\u5B89\u88C5\u5411\u5BFC",btn_reconfig:"\u91CD\u65B0\u914D\u7F6E",btn_reconfig_desc:"\u91CD\u65B0\u8FD0\u884C\u5B89\u88C5\u5411\u5BFC\uFF0C\u4FEE\u6539\u76EE\u5F55\u6216\u5BC6\u94A5\u914D\u7F6E",btn_validate:"\u9A8C\u8BC1",check_bbt_fail:"\u672A\u68C0\u6D4B\u5230",check_bbt_ok:"\u5DF2\u5B89\u88C5",check_python_fail:"\u672A\u5B89\u88C5",check_python_ok:"\u5DF2\u5C31\u7EEA",check_zotero_fail:"\u672A\u68C0\u6D4B\u5230",check_zotero_ok:"\u5DF2\u5B89\u88C5",complete_next:"\u4E0B\u4E00\u6B65\u64CD\u4F5C",complete_step1:"\u6253\u5F00 PaperForge Dashboard",complete_step1_desc:"Ctrl+P \u2192 \u8F93\u5165 PaperForge: Open Dashboard\uFF0C\u6216\u70B9\u5DE6\u4FA7\u4E66\u672C\u56FE\u6807",complete_step2:"\u540C\u6B65\u6587\u732E",complete_step2_desc:"Dashboard \u4E2D\u70B9 Sync Library\uFF0C\u4ECE Zotero \u62C9\u53D6\u6587\u732E\u751F\u6210\u7B14\u8BB0",complete_step3:"\u8FD0\u884C OCR",complete_step3_desc:"Dashboard \u4E2D\u70B9 Run OCR\uFF0C\u63D0\u53D6 PDF \u5168\u6587\u4E0E\u56FE\u8868",complete_step4:"\u914D\u7F6E BBT \u81EA\u52A8\u5BFC\u51FA",complete_summary:"\u5F53\u524D\u5B8C\u6574\u914D\u7F6E",complete_title:"\u2713 PaperForge \u5B89\u88C5\u5B8C\u6210",copied:"\u5DF2\u590D\u5236\uFF01",copy_pf_deep_cmd:"\u590D\u5236 /pf-deep \u547D\u4EE4",dashboard_drift_warning:'\u63D2\u4EF6\u7248\u672C\u4E0E Python \u8FD0\u884C\u65F6\u7248\u672C\u4E0D\u5339\u914D\u3002\u8BF7\u5728\u8BBE\u7F6E\u4E2D\u70B9\u51FB"\u540C\u6B65\u8FD0\u884C\u65F6"\u3002',deep_reading_not_found:"\u7CBE\u8BFB\u6587\u4EF6\u672A\u627E\u5230",desc:"Obsidian + Zotero \u6587\u732E\u7BA1\u7406\u6D41\u6C34\u7EBF\u3002\u81EA\u52A8\u540C\u6B65\u6587\u732E\u3001\u751F\u6210\u7B14\u8BB0\u3001OCR \u63D0\u53D6\u5168\u6587\uFF0C\u4E00\u7AD9\u5F0F\u6587\u732E\u7CBE\u8BFB\u5DE5\u4F5C\u6D41\u3002",dir_base:"Base \u76EE\u5F55",dir_index:"\u7D22\u5F15\u76EE\u5F55",dir_notes:"\u6B63\u6587\u76EE\u5F55",dir_resources:"\u8D44\u6E90\u76EE\u5F55",dir_system:"\u7CFB\u7EDF\u76EE\u5F55",dir_vault:"Vault \u8DEF\u5F84",error_copied:"\u5DF2\u590D\u5236\uFF01",error_copy_diagnostic:"\u590D\u5236\u8BCA\u65AD\u4FE1\u606F",feat_agent_platform:"Agent \u5E73\u53F0",feat_agent_platform_desc:"\u9009\u62E9\u8981\u7BA1\u7406\u7684 Agent \u5E73\u53F0\u3002",feat_api_base_url:"API \u5730\u5740",feat_api_base_url_desc:"\u81EA\u5B9A\u4E49 OpenAI \u517C\u5BB9 API \u7AEF\u70B9\u3002\u7559\u7A7A\u4F7F\u7528\u9ED8\u8BA4\u5730\u5740\u3002",feat_api_model:"API \u6A21\u578B",feat_api_model_desc:"\u8BE5\u7AEF\u70B9\u4F7F\u7528\u7684\u5D4C\u5165\u6A21\u578B\u540D\u79F0\u3002",feat_build_btn:"\u6784\u5EFA",feat_build_complete:"\u5411\u91CF\u6784\u5EFA\u5B8C\u6210\u3002",feat_build_failed:"\u6784\u5EFA\u5931\u8D25\u3002\u8BF7\u67E5\u770B\u7EC8\u7AEF\u8F93\u51FA\u3002",feat_building:"\u6784\u5EFA\u4E2D\u2026",feat_cache_remove_failed:"\u5931\u8D25\uFF1A{0}",feat_cache_removed:"\u6A21\u578B\u7F13\u5B58\u5DF2\u6E05\u9664\u3002",feat_checking:"\u68C0\u6D4B\u4E2D\u2026",feat_checking_btn:"\u68C0\u6D4B\u4E2D\u2026",feat_deps_checking:"\u6B63\u5728\u68C0\u6D4B\u4F9D\u8D56\u2026",feat_deps_missing:"\u4F9D\u8D56\u672A\u5B89\u88C5\u3002\u9700\u8981\uFF1Achromadb, openai\u3002",feat_enter_key:"\u8BF7\u8F93\u5165\u6709\u6548\u7684 OpenAI API Key\u3002",feat_install_btn:"\u5B89\u88C5",feat_install_deps:"\u5B89\u88C5\u4F9D\u8D56",feat_install_done:"\u4F9D\u8D56\u5DF2\u5B89\u88C5\u3002\u6B63\u5728\u6784\u5EFA\u5411\u91CF\u2026",feat_install_failed:"\u5B89\u88C5\u5931\u8D25\uFF1A",feat_installing:"\u5B89\u88C5\u4E2D\u2026",feat_installing_pkgs:"\u6B63\u5728\u5B89\u88C5 {pkgs}...",feat_key_rejected:"API Key \u88AB\u62D2\u7EDD\u3002",feat_memory_desc:"\u8BB0\u5FC6\u5C42\u662F PaperForge \u7684\u6838\u5FC3\u6570\u636E\u5F15\u64CE\uFF0C\u57FA\u4E8E SQLite \u6784\u5EFA\u3002\u5B83\u6574\u5408\u4E86\u6587\u732E\u5143\u6570\u636E\uFF08\u8BBA\u6587\u3001\u8D44\u6E90\u6587\u4EF6\u3001\u522B\u540D\u3001\u9605\u8BFB\u4E8B\u4EF6\uFF09\uFF0C\u652F\u6301 FTS5 \u5143\u6570\u636E\u68C0\u7D22\uFF08\u6807\u9898\u3001\u6458\u8981\u3001\u4F5C\u8005\u3001domain\u3001collection\uFF09\uFF0C\u5E76\u4E3A agent-context \u548C paper-status \u547D\u4EE4\u63D0\u4F9B\u6570\u636E\u652F\u6491\u3002\u59CB\u7EC8\u8FD0\u884C\uFF0C\u65E0\u9700\u624B\u52A8\u5F00\u542F\u3002",feat_memory_rebuild_btn:"\u91CD\u5EFA\u6570\u636E\u5E93",feat_memory_rebuild_done:"\u8BB0\u5FC6\u6570\u636E\u5E93\u91CD\u5EFA\u5B8C\u6210\u3002",feat_memory_rebuild_failed:"\u91CD\u5EFA\u5931\u8D25\u3002",feat_memory_rebuilding:"\u91CD\u5EFA\u4E2D\u2026",feat_model:"\u6A21\u578B",feat_model_changed_warn:"\u6A21\u578B\u5DF2\u66F4\u6362\uFF08{0} -> {1}\uFF09\u3002\u5DF2\u6709\u5411\u91CF\u4E0D\u517C\u5BB9\u2014\u2014\u9700\u8981\u91CD\u5EFA\u3002",feat_network_error:"\u7F51\u7EDC\u9519\u8BEF\uFF1A",feat_no_python:"\u672A\u627E\u5230 Python\u3002\u8BF7\u67E5\u770B\u5B89\u88C5\u6807\u7B7E\u9875\u3002",feat_not_cached:"\u672A\u7F13\u5B58",feat_openai_key:"OpenAI API Key",feat_openai_key_desc:"\u7528\u4E8E API \u5D4C\u5165\u8C03\u7528\uFF0C\u6A21\u578B\u5728\u4E0B\u65B9\u5B9A\u4E49\u3002",feat_output_copied:"\u8F93\u51FA\u5DF2\u590D\u5236\u5230\u526A\u8D34\u677F\u3002",feat_rebuild_btn:"\u91CD\u5EFA",feat_rebuild_vectors:"\u91CD\u5EFA\u5411\u91CF",feat_rebuild_vectors_changed:"\u6A21\u578B\u5DF2\u66F4\u6362 \u2014 \u9700\u8981\u91CD\u5EFA\u5411\u91CF\u3002",feat_rebuild_vectors_desc:"\u91CD\u5EFA\u6240\u6709 OCR \u5168\u6587\u5411\u91CF\u3002\u66F4\u6362\u6A21\u578B\u6216\u6A21\u5F0F\u540E\u9700\u8981\u91CD\u5EFA\u3002",feat_removing:"\u5220\u9664\u4E2D\u2026",feat_retry_btn:"\u91CD\u8BD5",feat_skills_desc:"\u7BA1\u7406 Vault \u4E2D\u5DF2\u5B89\u88C5\u7684 Agent \u6280\u80FD\u3002\u6BCF\u884C\u5BF9\u5E94\u4E00\u4E2A SKILL.md \u6587\u4EF6\uFF0C\u5173\u95ED\u5F00\u5173\u53EF\u963B\u6B62 Agent \u81EA\u52A8\u8C03\u7528\u8BE5\u6280\u80FD\u3002",feat_skills_system:"\u7CFB\u7EDF\u6280\u80FD\u968F PaperForge \u4E00\u540C\u53D1\u5E03\uFF0C\u4F1A\u8DDF\u968F PaperForge \u7248\u672C\u66F4\u65B0\u3002",feat_skills_user:"\u7528\u6237\u6280\u80FD\u662F\u4F60\u81EA\u884C\u5B89\u88C5\u6216\u521B\u5EFA\u7684\u81EA\u5B9A\u4E49\u6280\u80FD\u3002",feat_uninstall_btn:"\u5378\u8F7D",feat_valid_key:"API Key \u6709\u6548\u3002",feat_vector_config_label:"\u5411\u91CF\u5E93\u914D\u7F6E",feat_vector_corrupted:"\u5411\u91CF\u7D22\u5F15\u5DF2\u635F\u574F \u2014 \u9700\u8981\u5F3A\u5236\u91CD\u5EFA\u3002",feat_vector_desc:"\u5411\u91CF\u6570\u636E\u5E93\u901A\u8FC7\u5D4C\u5165\u6A21\u578B\u5B9E\u73B0 OCR \u5168\u6587\u7684\u8BED\u4E49\u641C\u7D22\u3002\u6587\u6863\u88AB\u5207\u5206\u4E3A\u6587\u672C\u5757\uFF08chunk\uFF09\uFF0C\u7F16\u7801\u4E3A\u5411\u91CF\u5B58\u5165 ChromaDB\u3002\u652F\u6301\u672C\u5730\u6A21\u578B\uFF08\u514D\u8D39\uFF0CCPU \u8FD0\u884C\uFF09\u6216 OpenAI API\uFF08\u4ED8\u8D39\uFF0C\u66F4\u5FEB\u901F\uFF09\u3002",feat_vector_enable:"\u542F\u7528\u5411\u91CF\u68C0\u7D22",feat_vector_enable_desc:"\u5BF9 OCR \u5168\u6587\u8FDB\u884C\u8BED\u4E49\u641C\u7D22\u3002\u9700\u5B89\u88C5: pip install chromadb sentence-transformers openai (~500MB)\u3002",feat_vector_rebuild_force_btn:"\u5F3A\u5236\u91CD\u5EFA",feat_verify:"\u9A8C\u8BC1",feat_verify_btn:"\u9A8C\u8BC1",field_paddleocr:"PaddleOCR API \u5BC6\u94A5",field_python_custom:"\u81EA\u5B9A\u4E49 Python \u8DEF\u5F84",field_python_interp:"\u5F53\u524D Python \u89E3\u91CA\u5668",field_zotero_data:"Zotero \u6570\u636E\u76EE\u5F55",field_zotero_placeholder:"\u53EF\u9009\uFF0C\u7528\u4E8E\u81EA\u52A8\u68C0\u6D4B PDF",guide_ocr:"\u8FD0\u884C OCR",guide_ocr_desc:"Dashboard \u4E2D\u70B9 Run OCR\uFF0C\u63D0\u53D6 PDF \u5168\u6587\u4E0E\u56FE\u8868",guide_open:"\u6253\u5F00 Dashboard",guide_open_desc:"Ctrl+P \u2192 \u8F93\u5165 PaperForge: Open Dashboard\uFF0C\u6216\u70B9\u5DE6\u4FA7\u4E66\u672C\u56FE\u6807",guide_sync:"\u540C\u6B65\u6587\u732E",guide_sync_desc:"Dashboard \u4E2D\u70B9 Sync Library\uFF0C\u4ECE Zotero \u62C9\u53D6\u6587\u732E\u751F\u6210\u7B14\u8BB0",header_title:"PaperForge",install_bootstrapping:"\u672A\u68C0\u6D4B\u5230 PaperForge Python \u5305\uFF0C\u6B63\u5728\u81EA\u52A8\u5B89\u88C5\u2026",install_btn:"\u5F00\u59CB\u5B89\u88C5",install_btn_retry:"\u91CD\u8BD5",install_btn_running:"\u6B63\u5728\u5B89\u88C5...",install_complete:"\u2713 \u5B89\u88C5\u5B8C\u6210\uFF01",install_failed:"\u2717 \u5B89\u88C5\u5931\u8D25\uFF1A",install_validating:"\u6B63\u5728\u6821\u9A8C\u5B89\u88C5\u73AF\u5883\u2026",jump_to_deep_reading:"\u8DF3\u8F6C\u5230\u7CBE\u8BFB",label_agent:"Agent \u5E73\u53F0",nav_close:"\u5173\u95ED",nav_next:"\u4E0B\u4E00\u6B65 \u2192",nav_prev:"\u2190 \u4E0A\u4E00\u6B65",no_pending_ocr:"\u6240\u6709 OCR \u4EFB\u52A1\u5DF2\u5B8C\u6210",not_set:"\u672A\u8BBE\u7F6E",notice_check_fail:"\u672A\u901A\u8FC7: ",notice_python_missing:"Python \u672A\u68C0\u6D4B\u5230\uFF0C\u8BF7\u5148\u5B89\u88C5 Python 3.10+ \u5E76\u52A0\u5165 PATH",ocr_privacy_title:"OCR \u9690\u79C1\u63D0\u793A",ocr_privacy_warning:"OCR \u4F1A\u5C06 PDF \u4E0A\u4F20\u5230 PaddleOCR API \u8FDB\u884C\u5904\u7406\u3002\u8BF7\u4E0D\u8981\u4E0A\u4F20\u5305\u542B\u654F\u611F\u4FE1\u606F\u6216\u65E0\u6CD5\u5916\u4F20\u7684\u6587\u732E\u3002",ocr_queue_add:"\u52A0\u5165 OCR \u961F\u5217",ocr_queue_added:"\u5DF2\u52A0\u5165 OCR \u961F\u5217",ocr_queue_remove:"\u79FB\u51FA OCR \u961F\u5217",ocr_queue_removed:"\u5DF2\u79FB\u51FA OCR \u961F\u5217",ocr_understand:"\u6211\u4E86\u89E3\uFF0C\u7EE7\u7EED",optional_later:"\uFF08\u7A0D\u540E\u53EF\u5728\u8BBE\u7F6E\u4E2D\u8865\u5145\uFF09",orphan_delete_failed:"\u6E05\u7406\u5931\u8D25",orphan_delete_selected:"\u5220\u9664 {count} \u7BC7",orphan_deleted:"\u5DF2\u5220\u9664 {count} \u7BC7\u6B8B\u7559\u6587\u732E",orphan_desc:"\u8FD9\u4E9B\u6587\u732E\u5DF2\u4ECE Zotero \u4E2D\u79FB\u9664\u3002",orphan_deselect_all:"\u53D6\u6D88\u5168\u9009",orphan_explain:"\u5DF2\u4ECE Zotero \u4E2D\u79FB\u9664\u3002\u5DE5\u4F5C\u533A\u6587\u4EF6\u4ECD\u4FDD\u7559\u5728\u78C1\u76D8\u4E0A\u3002",orphan_keep_all:"\u4FDD\u7559\u5168\u90E8",orphan_none_selected:"\u672A\u9009\u62E9\u4EFB\u4F55\u6587\u732E",orphan_select_all:"\u5168\u9009",orphan_title:"\u53D1\u73B0 {count} \u7BC7\u6B8B\u7559\u6587\u732E",panel_actions:"\u5FEB\u6377\u64CD\u4F5C",prep_bbt:"Better BibTeX",prep_bbt_desc:"Zotero \u2192 \u5DE5\u5177 \u2192 \u63D2\u4EF6 \u2192 \u5B89\u88C5 Better BibTeX",prep_export:"BBT \u81EA\u52A8\u5BFC\u51FA",prep_export_desc:"\u53F3\u952E\u6587\u732E\u5B50\u5206\u7C7B \u2192 \u5BFC\u51FA\u5206\u7C7B \u2192 BetterBibTeX JSON \u2192 \u52FE\u9009\u4FDD\u6301\u66F4\u65B0 \u2192 \u5BFC\u51FA\u5230\uFF08JSON \u6587\u4EF6\u540D\u5373\u4E3A Base \u540D\uFF09\uFF1A",prep_key:"PaddleOCR Key",prep_key_desc:"\u5728 https://aistudio.baidu.com/paddleocr \u83B7\u53D6 API Key",prep_python:"Python 3.10+",prep_python_desc:"\u786E\u4FDD Python \u53EF\u547D\u4EE4\u884C\u8C03\u7528\u3002\u70B9\u51FB\u4E0B\u65B9\u6309\u94AE\u81EA\u52A8\u68C0\u6D4B\u3002",prep_zotero:"Zotero \u684C\u9762\u7248",prep_zotero_desc:"\u5B89\u88C5 Zotero (https://www.zotero.org)",run_in_agent:"\u5728 {0} \u4E2D\u8FD0\u884C",runtime_health:"\u8FD0\u884C\u65F6\u72B6\u6001",runtime_health_checking:"\u6B63\u5728\u68C0\u6D4B\u2026",runtime_health_desc:"\u68C0\u67E5\u63D2\u4EF6\u4E0E Python \u8FD0\u884C\u65F6\u7248\u672C\u7684\u5339\u914D\u60C5\u51B5\uFF0C\u5E76\u786E\u8BA4\u5DF2\u90E8\u7F72\u7684 skill contract \u662F\u5426\u4E3A\u5F53\u524D\u7248\u672C\u3002",runtime_health_match:"\u5339\u914D",runtime_health_mismatch:"\u4E0D\u5339\u914D",runtime_health_package_ver:"Python \u5305 v{0}",runtime_health_plugin_ver:"\u63D2\u4EF6 v{0}",runtime_health_sync:"\u540C\u6B65\u8FD0\u884C\u65F6",runtime_health_sync_done:"\u8FD0\u884C\u65F6\u5DF2\u540C\u6B65\u81F3 v{0}",runtime_health_sync_fail:"\u8FD0\u884C\u65F6\u540C\u6B65\u5931\u8D25\uFF1A{0}",runtime_health_syncing:"\u6B63\u5728\u540C\u6B65\u2026",section_config:"\u5F53\u524D\u914D\u7F6E",section_guide:"\u64CD\u4F5C\u65B9\u5F0F",section_prep:"\u5B89\u88C5\u51C6\u5907",section_prep_desc:"\u9996\u6B21\u4F7F\u7528\u524D\uFF0C\u8BF7\u4F9D\u6B21\u5B8C\u6210\u4EE5\u4E0B\u51C6\u5907\uFF1A",setup_done:"\u2713 PaperForge \u73AF\u5883\u5DF2\u914D\u7F6E\u5B8C\u6210",setup_pending:"\u5C1A\u672A\u5B89\u88C5\uFF0C\u5B8C\u6210\u5B89\u88C5\u51C6\u5907\u540E\u70B9\u51FB\u5B89\u88C5\u5411\u5BFC",tab_features:"\u529F\u80FD",tab_setup:"\u5B89\u88C5",tab_maintenance:"\u7EF4\u62A4",validate_base:"Base \u76EE\u5F55\u672A\u586B\u5199",validate_fail:"\u914D\u7F6E\u9A8C\u8BC1\u5931\u8D25",validate_index:"\u7D22\u5F15\u76EE\u5F55\u672A\u586B\u5199",validate_key:"PaddleOCR API \u5BC6\u94A5\u672A\u586B\u5199",validate_notes:"\u6B63\u6587\u76EE\u5F55\u672A\u586B\u5199",validate_resources:"\u8D44\u6E90\u76EE\u5F55\u672A\u586B\u5199",validate_system:"\u7CFB\u7EDF\u76EE\u5F55\u672A\u586B\u5199",validate_vault:"Vault \u8DEF\u5F84\u672A\u586B\u5199",validate_zotero:"Zotero \u6570\u636E\u76EE\u5F55\u4E3A\u5FC5\u586B\u9879",wizard_agent_hint:"\u9009\u62E9\u4F60\u4F7F\u7528\u7684 AI Agent \u5E73\u53F0\uFF0C\u5B89\u88C5\u65F6\u5C06\u6309\u5BF9\u5E94\u683C\u5F0F\u90E8\u7F72\u6280\u80FD\u6587\u4EF6\uFF1A",wizard_dir_hint:"\u8D44\u6E90\u76EE\u5F55\u662F\u6587\u732E\u6570\u636E\u7684\u7EDF\u4E00\u6839\u76EE\u5F55\uFF0C\u4EE5\u4E0B\u5B50\u76EE\u5F55\u5C06\u521B\u5EFA\u5728\u5176\u5185\u90E8\uFF1A",wizard_dir_sub_hint:"\u8D44\u6E90\u76EE\u5F55\u5185\u7684\u4E24\u4E2A\u5B50\u76EE\u5F55\uFF1A",wizard_intro:"\u672C\u5411\u5BFC\u5C06\u5F15\u5BFC\u60A8\u5B8C\u6210 PaperForge \u73AF\u5883\u7684\u5B8C\u6574\u914D\u7F6E\u3002\u5B89\u88C5\u8FC7\u7A0B\u4F1A\u81EA\u52A8\u521B\u5EFA\u6240\u6709\u76EE\u5F55\u7ED3\u6784\uFF0C\u65E0\u9700\u624B\u52A8\u64CD\u4F5C\u3002",wizard_keys_hint:"\u4EE5\u4E0B\u4E3A API \u5BC6\u94A5\u4E0E Zotero \u914D\u7F6E\uFF1A",wizard_preview:"\u7CFB\u7EDF\u6587\u4EF6\u548C Agent \u914D\u7F6E\u4F4D\u4E8E Vault \u6839\u76EE\u5F55\u4E0B\u3002\u6587\u732E\u6570\u636E\uFF08\u6B63\u6587\u3001\u7D22\u5F15\uFF09\u7EDF\u4E00\u5B58\u653E\u5728\u8D44\u6E90\u76EE\u5F55\u5185\u3002\u5B89\u88C5\u540E\u4ECD\u53EF\u5728\u8BBE\u7F6E\u4E2D\u4FEE\u6539\u3002",wizard_safety:"\u5B89\u5168\u8BF4\u660E\uFF1A\u5982\u679C\u4F60\u9009\u62E9\u7684\u76EE\u5F55\u91CC\u5DF2\u7ECF\u6709\u6587\u4EF6\uFF0C\u5B89\u88C5\u5411\u5BFC\u4F1A\u4FDD\u7559\u5DF2\u6709\u5185\u5BB9\uFF0C\u53EA\u8865\u5145\u7F3A\u5931\u7684 PaperForge \u6587\u4EF6\u548C\u76EE\u5F55\u3002",wizard_step1:"\u6982\u89C8",wizard_step2:"\u76EE\u5F55",wizard_step3:"Agent",wizard_step4:"\u5B89\u88C5",wizard_step5:"\u5B8C\u6210",wizard_skip_ocr_desc:"OCR \u529F\u80FD\u5728\u914D\u7F6E\u6709\u6548\u7684 PaddleOCR API \u5BC6\u94A5\u4E4B\u524D\u4E0D\u53EF\u7528\u3002\u60A8\u53EF\u4EE5\u7EE7\u7EED\u5B8C\u6210\u8BBE\u7F6E\uFF0C\u7A0D\u540E\u5728\u8BBE\u7F6E\u4E2D\u914D\u7F6E\u3002",wizard_skip_ocr_continue:"\u7EE7\u7EED\uFF0C\u7A0D\u540E\u914D\u7F6E\u5BC6\u94A5",wizard_skip_ocr_back:"\u8FD4\u56DE\u914D\u7F6E",wizard_api_hint_skip:"OCR \u5BC6\u94A5\u4E3A\u9009\u586B\u9879 \u2014 \u53EF\u8DF3\u8FC7\uFF0C\u7A0D\u540E\u5728\u8BBE\u7F6E\u4E2D\u914D\u7F6E\u3002",wizard_sys_hint:"\u72EC\u7ACB\u4E8E\u8D44\u6E90\u76EE\u5F55\u7684\u7CFB\u7EDF\u6587\u4EF6\uFF1A",wizard_title:"PaperForge \u5B89\u88C5\u5411\u5BFC",ocr_maint_no_action:"\u65E0\u9700\u5904\u7406",ocr_maint_rebuild:"\u5EFA\u8BAE\u91CD\u5EFA",ocr_maint_failed:"OCR \u5931\u8D25",ocr_maint_limited:"\u7ED3\u679C\u4E00\u822C",ocr_maint_needs_attention:"\u9700\u8981\u5904\u7406",ocr_maint_limitations:"\u7ED3\u679C\u8BF4\u660E",ocr_maint_hero_ok:"OCR \u6574\u4F53\u6B63\u5E38\u3002",ocr_maint_hero_warn:"OCR \u9700\u8981\u5173\u6CE8\uFF1A{rebuild} \u7BC7\u5EFA\u8BAE\u91CD\u5EFA\uFF0C{failed} \u7BC7\u5904\u7406\u5931\u8D25\u3002",ocr_maint_hero_note:"\u672C\u9875\u53EA\u63D0\u793A\u7EF4\u62A4\u540E\u5927\u6982\u7387\u4F1A\u6539\u5584\u7684\u95EE\u9898\u3002\u90E8\u5206\u8BBA\u6587\u6548\u679C\u4E00\u822C\uFF0C\u7EF4\u62A4\u672A\u5FC5\u80FD\u6539\u5584\u3002",ocr_maint_limitations_intro:"\u8FD9\u7C7B\u8BBA\u6587\u901A\u5E38\u8868\u793A\u7248\u5F0F\u590D\u6742\u6216\u4FE1\u53F7\u504F\u5F31\uFF0CPaperForge \u76EE\u524D\u6CA1\u6709\u9AD8\u7F6E\u4FE1\u5EA6\u7684\u7EF4\u62A4\u5EFA\u8BAE\u3002",ocr_maint_all_papers:"\u5168\u90E8\u8BBA\u6587",ocr_maint_rebuild_btn:"\u91CD\u5EFA\u7ED3\u679C",ocr_maint_redo_btn:"\u91CD\u65B0 OCR"}},Ge=null;function Nt(g){try{let u=g.vault;if(typeof u.getConfig=="function"){let e=u.getConfig("language");if(e&&String(e).startsWith("zh"))return"zh"}}catch(u){}try{if(typeof localStorage!="undefined"){let u=localStorage.getItem("language");if(u&&String(u).startsWith("zh"))return"zh"}}catch(u){}return"en"}function gt(g){Ge=Nt(g)==="zh"?Ue.zh:Ue.en}function i(g){return Ge&&Ge[g]||Ue.en[g]||g}var F=require("obsidian"),L=q(require("fs")),Z=q(require("path")),Ke=q(require("os")),$=require("child_process");var Ft=q(Xe());var ie=q(require("fs")),ae=q(require("path")),ft=q(require("os")),pe=require("child_process"),Ye=null,ht=!1;function N(g,u,e,t){let r=e||ie,n=t||pe.execFileSync;if(u&&u.python_path&&u.python_path.trim()){let l=u.python_path.trim();if(r.existsSync(l))return{path:l,source:"manual",extraArgs:[]}}let a=[ae.join(g,".paperforge-test-venv","Scripts","python.exe"),ae.join(g,".venv","Scripts","python.exe"),ae.join(g,"venv","Scripts","python.exe")];for(let l of a)try{if(r.existsSync(l))return{path:l,source:"auto-detected",extraArgs:[]}}catch(o){}let s=[{path:"py",extraArgs:["-3"]},{path:"python",extraArgs:[]},{path:"python3",extraArgs:[]}];for(let l of s)try{let o=n(l.path,[...l.extraArgs,"--version"],{encoding:"utf-8",timeout:5e3,windowsHide:!0});if(o&&o.toLowerCase().includes("python"))return{path:l.path,source:"auto-detected",extraArgs:l.extraArgs}}catch(o){}return{path:"python",source:"auto-detected",extraArgs:[]}}function _t(g,u,e,t,r){t===void 0&&(t=1e4);let n=r||pe.execFile;return new Promise(a=>{n(g,["-c","import paperforge; print(paperforge.__version__)"],{cwd:e,timeout:t},(s,l)=>{if(s){a({status:"not-installed",pyVersion:null,pluginVersion:u,error:s.message});return}let o=l&&l.trim()||null;a(o===u?{status:"match",pyVersion:o,pluginVersion:u,error:null}:{status:"mismatch",pyVersion:o,pluginVersion:u,error:null})})})}function mt(g,u,e){e===void 0&&(e=[]);let t=`paperforge==${u}`,r=`git+https://github.com/LLLin000/PaperForge.git@${u}`,n=[...e,"-m","pip","install","--upgrade",t],a=[...e,"-m","pip","install","--upgrade",r];return{cmd:g,url:r,args:a,pypiArgs:n,gitArgs:a,timeout:12e4}}function yt(g,u,e,t,r,n){let a=r||pe.spawn;return new Promise(s=>{let l=Date.now(),o={cwd:e,timeout:t,windowsHide:!0};n&&(o.env=n);let c=a(g,u,o),p=[],h=[];c.stdout.on("data",d=>{p.push(d.toString("utf-8"))}),c.stderr.on("data",d=>{h.push(d.toString("utf-8"))}),c.on("close",d=>{s({stdout:p.join(""),stderr:h.join(""),exitCode:d,elapsed:Date.now()-l})}),c.on("error",d=>{s({stdout:p.join(""),stderr:h.join("")+`
+"use strict";var Dt=Object.create;var ze=Object.defineProperty;var Rt=Object.getOwnPropertyDescriptor;var Bt=Object.getOwnPropertyNames;var At=Object.getPrototypeOf,Ot=Object.prototype.hasOwnProperty;var Lt=(g,u)=>()=>(u||g((u={exports:{}}).exports,u),u.exports),Mt=(g,u)=>{for(var e in u)ze(g,e,{get:u[e],enumerable:!0})},pt=(g,u,e,t)=>{if(u&&typeof u=="object"||typeof u=="function")for(let r of Bt(u))!Ot.call(g,r)&&r!==e&&ze(g,r,{get:()=>u[r],enumerable:!(t=Rt(u,r))||t.enumerable});return g};var q=(g,u,e)=>(e=g!=null?Dt(At(g)):{},pt(u||!g||!g.__esModule?ze(e,"default",{value:g,enumerable:!0}):e,g)),It=g=>pt(ze({},"__esModule",{value:!0}),g);var Xe=Lt((Wt,zt)=>{zt.exports={versions:[{version:"1.5.15",date:"2026-06-01",title:"\u5168\u6587\u5B58\u50A8\u91CD\u6784 + OCR \u9605\u8BFB\u987A\u5E8F\u4FEE\u590D + Redo \u4E00\u952E\u91CD\u505A",breaking_or_migration:["\u5168\u6587\u6587\u4EF6\u73B0\u5728\u7EDF\u4E00\u5B58\u653E\u4E8E System/PaperForge/ocr/ \u4E0B\uFF0C\u4E0D\u518D\u5728\u5DE5\u4F5C\u533A\u4FDD\u7559\u526F\u672C","Redo OCR \u73B0\u5728\u4F1A\u7ACB\u5373\u6267\u884C\uFF08\u4E00\u952E\u5B8C\u6210\uFF09\uFF0C\u4E0D\u518D\u9700\u8981\u624B\u52A8\u518D\u8DD1\u4E00\u6B21"],new_features:["Redo OCR \u4E00\u952E\u95ED\u73AF\uFF1A\u52FE\u9009 \u2192 \u70B9\u6309\u94AE \u2192 \u81EA\u52A8\u5B8C\u6210\u5168\u90E8\u6D41\u7A0B","\u8BBE\u7F6E\u9875\u65B0\u589E\u300C\u66F4\u65B0\u4E0E\u624B\u518C\u300D\u6807\u7B7E\u9875\uFF0C\u53EF\u968F\u65F6\u67E5\u770B\u7248\u672C\u66F4\u65B0\u8BB0\u5F55\u548C\u4F7F\u7528\u624B\u518C","\u63D2\u4EF6\u66F4\u65B0\u540E\u81EA\u52A8\u5F39\u51FA\u66F4\u65B0\u8BF4\u660E"],fixes:["\u4FEE\u590D\u5168\u6587\u9605\u8BFB\u987A\u5E8F\u6DF7\u4E71\uFF0C\u4F18\u5316\u6574\u4F53\u6392\u7248\u4F53\u9A8C","\u4FEE\u590D\u7AE0\u8282\u6807\u9898\u548C\u6B63\u6587\u6BB5\u843D\u9519\u4F4D\u65AD\u5F00\u7684\u95EE\u9898","\u4FEE\u590D\u56FE\u8868\u548C\u5BF9\u5E94\u56FE\u6CE8\u88AB\u5206\u5F00\u7684\u95EE\u9898","\u4FEE\u590D\u9996\u9875\u6458\u8981\u533A\u5757\u6392\u5E8F\u5F02\u5E38","\u4FEE\u590D\u5E76\u6392\u56FE\u7247\u672A\u80FD\u81EA\u52A8\u5408\u5E76\u7684\u95EE\u9898","Dashboard \u73B0\u5728\u80FD\u6B63\u786E\u8BC6\u522B\u65B0\u7684\u5168\u6587\u6587\u4EF6\u4F4D\u7F6E"],recommended_actions:["\u65E7\u7248 OCR \u5168\u6587\u53EF\u80FD\u5B58\u5728\u9605\u8BFB\u987A\u5E8F\u95EE\u9898\uFF0C\u5EFA\u8BAE\u5BF9\u91CD\u8981\u8BBA\u6587\u6267\u884C\u4E00\u6B21 Redo OCR","\u6253\u5F00\u5168\u6587\u8BF7\u76F4\u63A5\u4F7F\u7528 Dashboard \u7684\u300C\u6253\u5F00\u5168\u6587\u300D\u6309\u94AE"]}]}});var Ht={};Mt(Ht,{default:()=>Ze});module.exports=It(Ht);var H=require("obsidian"),j=q(require("fs")),Se=q(require("path")),ce=require("child_process");var ye="paperforge-status",Be="paperforge",dt='',X=[{id:"paperforge-sync",title:"Sync Library",desc:"Pull new references from Zotero and generate literature notes",icon:"\u21BB",cmd:"sync",okMsg:"Sync complete"},{id:"paperforge-ocr",title:"Run OCR",desc:"Extract full text and figures from PDFs via PaddleOCR",icon:"\u229E",cmd:"ocr",okMsg:"OCR started"},{id:"paperforge-doctor",title:"Run Doctor",desc:"Verify PaperForge setup \u2014 check configs, Zotero, paths, and index health",icon:"\u2695",cmd:"doctor",okMsg:"Doctor complete"},{id:"paperforge-repair",title:"Repair Issues",desc:"Fix three-way state divergence, path errors, and rebuild index",icon:"\u21BA",cmd:"repair",args:["--fix","--fix-paths"],okMsg:"Repair complete"},{id:"paperforge-ocr-redo",title:"Redo OCR",desc:"Re-run OCR for papers marked ocr_redo: true",icon:"\u21BA",cmd:"ocr",args:["redo"],okMsg:"OCR redo started"}],Ae={vault_path:"",setup_complete:!1,auto_update:!0,auto_update_on_startup:!0,agent_platform:"opencode",language:"",paddleocr_api_key:"",zotero_data_dir:"",python_path:"",features:{memory_layer:!0,vector_db:!1},selected_skill_platform:"opencode",vector_db_api_key:"",vector_db_api_base:"",vector_db_api_model:"text-embedding-3-small",frozen_skills:{},system_dir:"",resources_dir:"",literature_dir:"",base_dir:"",last_seen_version:""};function ut(g,u){if(!u||!u.note_path)return u;let e=g.vault.getAbstractFileByPath(u.note_path);if(!e)return u;let t=g.metadataCache.getFileCache(e),r=t&&t.frontmatter;if(!r)return u;let n={...u};for(let a of["do_ocr","analyze","ocr_status","ocr_redo","deep_reading_status"])Object.prototype.hasOwnProperty.call(r,a)&&(n[a]=r[a]);return n}function Je(g,u){return g&&{...g,...u}}var Ue={en:{action_running:"Running ",api_key_missing:"Missing",api_key_set:"Entered",btn_install:"Open Setup Wizard",btn_install_desc:"Check whether the environment is ready, then open the step-by-step setup wizard",btn_reconfig:"Reconfigure",btn_reconfig_desc:"Open the setup wizard again to change directories, platform, or API keys",btn_validate:"Validate",check_bbt_fail:"Not detected",check_bbt_ok:"Installed",check_python_fail:"Not found",check_python_ok:"Ready",check_zotero_fail:"Not detected",check_zotero_ok:"Found",complete_export_path:"Save Better BibTeX JSON exports into:",complete_next:"Recommended next steps",complete_step1:"Open Dashboard",complete_step1_desc:'Press Ctrl+P and run "PaperForge: Open Main Panel", or click the PaperForge icon in the left sidebar.',complete_step2:"Sync Literature",complete_step2_desc:"In the main panel, click Sync Library to bring papers from Zotero into Obsidian and generate notes.",complete_step3:"Run OCR",complete_step3_desc:"In the Obsidian Base view, mark do_ocr:true on papers, then run OCR in the main panel.",complete_step4:"Configure Better BibTeX Auto-export",complete_step4_desc:'In Zotero, right-click the library or collection you want to sync -> Export -> Better BibTeX JSON -> enable "Keep updated".',complete_summary:"Saved Configuration",complete_title:"Setup Complete",copied:"Copied!",copy_pf_deep_cmd:"Copy /pf-deep Command",dashboard_drift_warning:"PaperForge CLI (v{0}) differs from plugin (v{1}). Open Settings \u2192 Runtime Health to sync.",deep_reading_not_found:"Deep reading file not found",desc:"Obsidian + Zotero literature pipeline. Sync papers, generate notes, run OCR, and read deeply in one place.",dir_base:"Base Dir",dir_index:"Index Dir",dir_notes:"Notes Dir",dir_resources:"Resource Dir",dir_system:"System Dir",dir_vault:"Vault Path",error_copied:"Copied!",error_copy_diagnostic:"Copy diagnostic",feat_agent_platform:"Agent Platform",feat_agent_platform_desc:"Select which agent platform to manage skills for.",feat_api_base_url:"API Base URL",feat_api_base_url_desc:"Custom OpenAI-compatible API endpoint. Leave empty for default.",feat_api_model:"API Model",feat_api_model_desc:"Embedding model name for this endpoint.",feat_build_btn:"Build",feat_build_complete:"Vector build complete.",feat_build_failed:"Build failed. See terminal output.",feat_building:"Building...",feat_cache_remove_failed:"Failed: {0}",feat_cache_removed:"Model cache removed.",feat_checking:"Checking...",feat_checking_btn:"Checking...",feat_deps_checking:"Checking dependencies...",feat_deps_missing:"Dependencies not installed. Required: chromadb, openai.",feat_enter_key:"Enter a valid OpenAI API key.",feat_install_btn:"Install",feat_install_deps:"Install Dependencies",feat_install_deps_desc:"pip install chromadb openai (~35MB).",feat_install_done:"Dependencies installed. Building vectors...",feat_install_failed:"Install failed: ",feat_installing:"Installing...",feat_installing_pkgs:"Installing {pkgs}...",feat_key_rejected:"API key rejected.",feat_memory_desc:"The Memory Layer is the core data engine of PaperForge, powered by SQLite. It integrates literature metadata (papers, assets, aliases, reading events), provides FTS5 metadata search across titles, abstracts, authors, domains, and collections, and powers agent-context and paper-status. Always active \u2014 no toggle needed.",feat_memory_rebuild_btn:"Rebuild",feat_memory_rebuild_done:"Memory DB rebuilt.",feat_memory_rebuild_failed:"Rebuild failed.",feat_memory_rebuilding:"Rebuilding...",feat_model_changed_warn:"Model changed ({0} -> {1}). Existing vectors are incompatible \u2014 rebuild required.",feat_network_error:"Network error: ",feat_no_python:"No Python found. Check Installation tab.",feat_not_cached:"Not cached",feat_openai_key:"OpenAI API Key",feat_openai_key_desc:"Used for API embedding calls. Model is defined below.",feat_output_copied:"Output copied to clipboard.",feat_rebuild_btn:"Rebuild",feat_rebuild_vectors:"Rebuild Vectors",feat_rebuild_vectors_changed:"Model changed \u2014 rebuild to update all vectors.",feat_rebuild_vectors_desc:"Rebuild all OCR fulltext vectors. Required after model or mode change.",feat_removing:"Removing...",feat_retry_btn:"Retry",feat_skills_desc:"Manage and enable/disable agent skills installed in your vault. Each row corresponds to a SKILL.md file \u2014 toggle off to prevent the agent from auto-invoking that skill.",feat_skills_system:"System Skills ship with PaperForge and are updated alongside PaperForge.",feat_skills_user:"User Skills are custom skills you install from community or create yourself.",feat_uninstall_btn:"Uninstall",feat_valid_key:"API key valid.",feat_vector_config_label:"Vector Settings",feat_vector_corrupted:"Vector index corrupted \u2014 needs force rebuild.",feat_vector_desc:"Vector Database enables semantic search across OCR-extracted fulltext via API embedding. Documents are split into chunks, embedded via OpenAI-compatible API, and stored in ChromaDB.",feat_vector_enable:"Enable Vector Retrieval",feat_vector_enable_desc:"Semantic search across OCR fulltext. Requires: pip install openai chromadb (~35MB).",feat_vector_rebuild_force_btn:"Force Rebuild",feat_verify:"Verify",feat_verify_btn:"Verify",field_paddleocr:"PaddleOCR API Key",field_python_custom:"Custom Path",field_python_interp:"Python Interpreter",field_zotero_data:"Zotero Data Dir",field_zotero_placeholder:"Required. Path to Zotero data directory for PDF attachment resolution.",guide_ocr:"Run OCR",guide_ocr_desc:"In the main panel, click Run OCR to extract full text and figures from PDFs for later reading and analysis.",guide_open:"Open Main Panel",guide_open_desc:'Press Ctrl+P and run "PaperForge: Open Main Panel", or click the PaperForge icon in the left sidebar.',guide_sync:"Sync Literature",guide_sync_desc:"After Better BibTeX JSON export is configured, click Sync Library to import papers from Zotero into Obsidian and generate notes automatically.",header_title:"PaperForge",install_bootstrapping:"PaperForge Python package not found. Installing automatically...",install_btn:"Start Install",install_btn_retry:"Retry",install_btn_running:"Installing...",install_complete:"Installation complete!",install_failed:"Installation failed: ",install_validating:"Validating setup...",jump_to_deep_reading:"Open Deep Reading",label_agent:"Agent Platform",nav_close:"Close",nav_next:"Next",nav_prev:"Back",not_set:"Not entered",notice_check_fail:"Missing: ",notice_python_missing:"Python was not detected. Install Python 3.10+ and add it to PATH.",ocr_privacy_title:"OCR Privacy Notice",ocr_privacy_warning:"OCR will upload PDFs to the PaddleOCR API. Do not upload sensitive or confidential documents.",ocr_queue_add:"Add to OCR Queue",ocr_queue_added:"Added to OCR queue",ocr_queue_remove:"Remove from OCR Queue",ocr_queue_removed:"Removed from OCR queue",ocr_understand:"I understand, continue",optional_later:"(can be set later in Settings)",orphan_delete_failed:"Prune failed",orphan_delete_selected:"Delete {count} selected",orphan_deleted:"Deleted {count} orphan workspace(s)",orphan_desc:"These papers are no longer in your Zotero library.",orphan_deselect_all:"Deselect all",orphan_explain:"Removed from Zotero. Workspace files remain on disk.",orphan_keep_all:"Keep all",orphan_none_selected:"No papers selected for deletion",orphan_select_all:"Select all",orphan_title:"Found {count} orphan paper(s)",panel_actions:"Quick Actions",prep_bbt:"Better BibTeX",prep_bbt_desc:"In Zotero: Tools -> Add-ons -> install Better BibTeX.",prep_export:"Better BibTeX Auto-export",prep_export_desc:'In Zotero, right-click the collection you want to sync -> Export Collection -> BetterBibTeX JSON -> enable "Keep updated" -> save the JSON file into the exports folder shown below. Obsidian Base views will use the JSON filename as the Base name:',prep_export_path_label:"Save the exported JSON file into this folder:",prep_key:"PaddleOCR Key",prep_key_desc:"Get your API key from https://aistudio.baidu.com/paddleocr",prep_python:"Python 3.10+",prep_python_desc:"Python must be available from the command line. If you are not sure, click below to auto-detect.",prep_zotero:"Zotero Desktop",prep_zotero_desc:"Install Zotero from https://www.zotero.org",run_in_agent:"Run in {0}",runtime_health:"Runtime Health",runtime_health_checking:"Checking...",runtime_health_desc:"Check whether the installed paperforge Python package matches the plugin version and whether the deployed skill contract is current.",runtime_health_match:"Match",runtime_health_mismatch:"Mismatch",runtime_health_package_ver:"Python package v{0}",runtime_health_plugin_ver:"Plugin v{0}",runtime_health_sync:"Sync Runtime",runtime_health_sync_done:"Runtime synced to v{0}",runtime_health_sync_fail:"Sync failed: {0}",runtime_health_syncing:"Syncing...",section_config:"Current Configuration",section_guide:"How To Use",section_prep:"Preparation",section_prep_desc:"Before first use, finish these 4 preparation items. Better BibTeX auto-export is configured after setup:",setup_done:"PaperForge environment is ready",setup_pending:"Not installed yet. Finish the preparation items below, then open the wizard.",tab_features:"Features",tab_setup:"Installation",tab_maintenance:"Maintenance",validate_base:"Base directory is required",validate_fail:"Please complete the required fields below",validate_index:"Index directory is required",validate_key:"PaddleOCR API key (optional, needed for OCR)",validate_notes:"Notes directory is required",validate_resources:"Resources directory is required",validate_system:"System directory is required",validate_vault:"Vault path is required",validate_zotero:"Zotero data directory (optional, needed for PDF linking)",wizard_agent_hint:"Choose the AI agent platform you use most often. PaperForge will place the matching command and skill files in the correct location.",wizard_dir_hint:"PaperForge stores user-facing literature data under the resources directory. These folders will live there:",wizard_dir_sub_hint:"Resolved folder preview based on the names below:",wizard_intro:"This wizard walks you through the full setup. In most cases, the default values are fine to keep.",wizard_keys_hint:"Enter your PaddleOCR API key below. If you want PaperForge to auto-locate Zotero PDFs, you can also fill in the Zotero data directory.",wizard_preview:"After installation, system files stay at the vault root while literature data stays under the resources directory.",wizard_safety:"Safety: if the selected folders already contain files, setup preserves existing files and only creates missing PaperForge folders and files.",wizard_step1:"Overview",wizard_step2:"Directory Setup",wizard_step3:"Platform & Keys",wizard_step4:"Install",wizard_step5:"Done",wizard_skip_ocr_desc:"OCR will not be available until you configure a valid PaddleOCR API key. You can continue setup now and configure it later in Settings.",wizard_skip_ocr_continue:"Continue without OCR key",wizard_skip_ocr_back:"Back to configure",wizard_api_hint_skip:"OCR key is optional \u2014 you may skip it and configure later.",wizard_sys_hint:"These folders live at the vault root, outside the resources directory:",wizard_title:"PaperForge Setup Wizard",ocr_maint_no_action:"No Action Needed",ocr_maint_rebuild:"Rebuild Recommended",ocr_maint_failed:"OCR Failed",ocr_maint_limited:"Result Limited",ocr_maint_needs_attention:"Needs Attention",ocr_maint_limitations:"Result Limitations",ocr_maint_hero_ok:"OCR looks usable overall.",ocr_maint_hero_warn:"OCR needs attention: {rebuild} rebuild recommended, {failed} failed.",ocr_maint_hero_note:"This page only promotes issues where maintenance is likely to help. Some papers may have limitations that maintenance will not improve.",ocr_maint_limitations_intro:"These papers look less certain, but PaperForge does not currently have a high-confidence maintenance action to recommend.",ocr_maint_all_papers:"All Papers",ocr_maint_rebuild_btn:"Rebuild results",ocr_maint_redo_btn:"Rerun OCR"},zh:{action_running:"\u6B63\u5728\u6267\u884C ",api_key_missing:"\u672A\u914D\u7F6E \u2717",api_key_set:"\u5DF2\u914D\u7F6E \u2713",btn_install:"\u6253\u5F00\u5B89\u88C5\u5411\u5BFC",btn_install_desc:"\u81EA\u52A8\u68C0\u6D4B Python + \u524D\u7F6E\u73AF\u5883\uFF0C\u901A\u8FC7\u540E\u6253\u5F00\u5206\u6B65\u5B89\u88C5\u5411\u5BFC",btn_reconfig:"\u91CD\u65B0\u914D\u7F6E",btn_reconfig_desc:"\u91CD\u65B0\u8FD0\u884C\u5B89\u88C5\u5411\u5BFC\uFF0C\u4FEE\u6539\u76EE\u5F55\u6216\u5BC6\u94A5\u914D\u7F6E",btn_validate:"\u9A8C\u8BC1",check_bbt_fail:"\u672A\u68C0\u6D4B\u5230",check_bbt_ok:"\u5DF2\u5B89\u88C5",check_python_fail:"\u672A\u5B89\u88C5",check_python_ok:"\u5DF2\u5C31\u7EEA",check_zotero_fail:"\u672A\u68C0\u6D4B\u5230",check_zotero_ok:"\u5DF2\u5B89\u88C5",complete_next:"\u4E0B\u4E00\u6B65\u64CD\u4F5C",complete_step1:"\u6253\u5F00 PaperForge Dashboard",complete_step1_desc:"Ctrl+P \u2192 \u8F93\u5165 PaperForge: Open Dashboard\uFF0C\u6216\u70B9\u5DE6\u4FA7\u4E66\u672C\u56FE\u6807",complete_step2:"\u540C\u6B65\u6587\u732E",complete_step2_desc:"Dashboard \u4E2D\u70B9 Sync Library\uFF0C\u4ECE Zotero \u62C9\u53D6\u6587\u732E\u751F\u6210\u7B14\u8BB0",complete_step3:"\u8FD0\u884C OCR",complete_step3_desc:"Dashboard \u4E2D\u70B9 Run OCR\uFF0C\u63D0\u53D6 PDF \u5168\u6587\u4E0E\u56FE\u8868",complete_step4:"\u914D\u7F6E BBT \u81EA\u52A8\u5BFC\u51FA",complete_summary:"\u5F53\u524D\u5B8C\u6574\u914D\u7F6E",complete_title:"\u2713 PaperForge \u5B89\u88C5\u5B8C\u6210",copied:"\u5DF2\u590D\u5236\uFF01",copy_pf_deep_cmd:"\u590D\u5236 /pf-deep \u547D\u4EE4",dashboard_drift_warning:'\u63D2\u4EF6\u7248\u672C\u4E0E Python \u8FD0\u884C\u65F6\u7248\u672C\u4E0D\u5339\u914D\u3002\u8BF7\u5728\u8BBE\u7F6E\u4E2D\u70B9\u51FB"\u540C\u6B65\u8FD0\u884C\u65F6"\u3002',deep_reading_not_found:"\u7CBE\u8BFB\u6587\u4EF6\u672A\u627E\u5230",desc:"Obsidian + Zotero \u6587\u732E\u7BA1\u7406\u6D41\u6C34\u7EBF\u3002\u81EA\u52A8\u540C\u6B65\u6587\u732E\u3001\u751F\u6210\u7B14\u8BB0\u3001OCR \u63D0\u53D6\u5168\u6587\uFF0C\u4E00\u7AD9\u5F0F\u6587\u732E\u7CBE\u8BFB\u5DE5\u4F5C\u6D41\u3002",dir_base:"Base \u76EE\u5F55",dir_index:"\u7D22\u5F15\u76EE\u5F55",dir_notes:"\u6B63\u6587\u76EE\u5F55",dir_resources:"\u8D44\u6E90\u76EE\u5F55",dir_system:"\u7CFB\u7EDF\u76EE\u5F55",dir_vault:"Vault \u8DEF\u5F84",error_copied:"\u5DF2\u590D\u5236\uFF01",error_copy_diagnostic:"\u590D\u5236\u8BCA\u65AD\u4FE1\u606F",feat_agent_platform:"Agent \u5E73\u53F0",feat_agent_platform_desc:"\u9009\u62E9\u8981\u7BA1\u7406\u7684 Agent \u5E73\u53F0\u3002",feat_api_base_url:"API \u5730\u5740",feat_api_base_url_desc:"\u81EA\u5B9A\u4E49 OpenAI \u517C\u5BB9 API \u7AEF\u70B9\u3002\u7559\u7A7A\u4F7F\u7528\u9ED8\u8BA4\u5730\u5740\u3002",feat_api_model:"API \u6A21\u578B",feat_api_model_desc:"\u8BE5\u7AEF\u70B9\u4F7F\u7528\u7684\u5D4C\u5165\u6A21\u578B\u540D\u79F0\u3002",feat_build_btn:"\u6784\u5EFA",feat_build_complete:"\u5411\u91CF\u6784\u5EFA\u5B8C\u6210\u3002",feat_build_failed:"\u6784\u5EFA\u5931\u8D25\u3002\u8BF7\u67E5\u770B\u7EC8\u7AEF\u8F93\u51FA\u3002",feat_building:"\u6784\u5EFA\u4E2D\u2026",feat_cache_remove_failed:"\u5931\u8D25\uFF1A{0}",feat_cache_removed:"\u6A21\u578B\u7F13\u5B58\u5DF2\u6E05\u9664\u3002",feat_checking:"\u68C0\u6D4B\u4E2D\u2026",feat_checking_btn:"\u68C0\u6D4B\u4E2D\u2026",feat_deps_checking:"\u6B63\u5728\u68C0\u6D4B\u4F9D\u8D56\u2026",feat_deps_missing:"\u4F9D\u8D56\u672A\u5B89\u88C5\u3002\u9700\u8981\uFF1Achromadb, openai\u3002",feat_enter_key:"\u8BF7\u8F93\u5165\u6709\u6548\u7684 OpenAI API Key\u3002",feat_install_btn:"\u5B89\u88C5",feat_install_deps:"\u5B89\u88C5\u4F9D\u8D56",feat_install_done:"\u4F9D\u8D56\u5DF2\u5B89\u88C5\u3002\u6B63\u5728\u6784\u5EFA\u5411\u91CF\u2026",feat_install_failed:"\u5B89\u88C5\u5931\u8D25\uFF1A",feat_installing:"\u5B89\u88C5\u4E2D\u2026",feat_installing_pkgs:"\u6B63\u5728\u5B89\u88C5 {pkgs}...",feat_key_rejected:"API Key \u88AB\u62D2\u7EDD\u3002",feat_memory_desc:"\u8BB0\u5FC6\u5C42\u662F PaperForge \u7684\u6838\u5FC3\u6570\u636E\u5F15\u64CE\uFF0C\u57FA\u4E8E SQLite \u6784\u5EFA\u3002\u5B83\u6574\u5408\u4E86\u6587\u732E\u5143\u6570\u636E\uFF08\u8BBA\u6587\u3001\u8D44\u6E90\u6587\u4EF6\u3001\u522B\u540D\u3001\u9605\u8BFB\u4E8B\u4EF6\uFF09\uFF0C\u652F\u6301 FTS5 \u5143\u6570\u636E\u68C0\u7D22\uFF08\u6807\u9898\u3001\u6458\u8981\u3001\u4F5C\u8005\u3001domain\u3001collection\uFF09\uFF0C\u5E76\u4E3A agent-context \u548C paper-status \u547D\u4EE4\u63D0\u4F9B\u6570\u636E\u652F\u6491\u3002\u59CB\u7EC8\u8FD0\u884C\uFF0C\u65E0\u9700\u624B\u52A8\u5F00\u542F\u3002",feat_memory_rebuild_btn:"\u91CD\u5EFA\u6570\u636E\u5E93",feat_memory_rebuild_done:"\u8BB0\u5FC6\u6570\u636E\u5E93\u91CD\u5EFA\u5B8C\u6210\u3002",feat_memory_rebuild_failed:"\u91CD\u5EFA\u5931\u8D25\u3002",feat_memory_rebuilding:"\u91CD\u5EFA\u4E2D\u2026",feat_model:"\u6A21\u578B",feat_model_changed_warn:"\u6A21\u578B\u5DF2\u66F4\u6362\uFF08{0} -> {1}\uFF09\u3002\u5DF2\u6709\u5411\u91CF\u4E0D\u517C\u5BB9\u2014\u2014\u9700\u8981\u91CD\u5EFA\u3002",feat_network_error:"\u7F51\u7EDC\u9519\u8BEF\uFF1A",feat_no_python:"\u672A\u627E\u5230 Python\u3002\u8BF7\u67E5\u770B\u5B89\u88C5\u6807\u7B7E\u9875\u3002",feat_not_cached:"\u672A\u7F13\u5B58",feat_openai_key:"OpenAI API Key",feat_openai_key_desc:"\u7528\u4E8E API \u5D4C\u5165\u8C03\u7528\uFF0C\u6A21\u578B\u5728\u4E0B\u65B9\u5B9A\u4E49\u3002",feat_output_copied:"\u8F93\u51FA\u5DF2\u590D\u5236\u5230\u526A\u8D34\u677F\u3002",feat_rebuild_btn:"\u91CD\u5EFA",feat_rebuild_vectors:"\u91CD\u5EFA\u5411\u91CF",feat_rebuild_vectors_changed:"\u6A21\u578B\u5DF2\u66F4\u6362 \u2014 \u9700\u8981\u91CD\u5EFA\u5411\u91CF\u3002",feat_rebuild_vectors_desc:"\u91CD\u5EFA\u6240\u6709 OCR \u5168\u6587\u5411\u91CF\u3002\u66F4\u6362\u6A21\u578B\u6216\u6A21\u5F0F\u540E\u9700\u8981\u91CD\u5EFA\u3002",feat_removing:"\u5220\u9664\u4E2D\u2026",feat_retry_btn:"\u91CD\u8BD5",feat_skills_desc:"\u7BA1\u7406 Vault \u4E2D\u5DF2\u5B89\u88C5\u7684 Agent \u6280\u80FD\u3002\u6BCF\u884C\u5BF9\u5E94\u4E00\u4E2A SKILL.md \u6587\u4EF6\uFF0C\u5173\u95ED\u5F00\u5173\u53EF\u963B\u6B62 Agent \u81EA\u52A8\u8C03\u7528\u8BE5\u6280\u80FD\u3002",feat_skills_system:"\u7CFB\u7EDF\u6280\u80FD\u968F PaperForge \u4E00\u540C\u53D1\u5E03\uFF0C\u4F1A\u8DDF\u968F PaperForge \u7248\u672C\u66F4\u65B0\u3002",feat_skills_user:"\u7528\u6237\u6280\u80FD\u662F\u4F60\u81EA\u884C\u5B89\u88C5\u6216\u521B\u5EFA\u7684\u81EA\u5B9A\u4E49\u6280\u80FD\u3002",feat_uninstall_btn:"\u5378\u8F7D",feat_valid_key:"API Key \u6709\u6548\u3002",feat_vector_config_label:"\u5411\u91CF\u5E93\u914D\u7F6E",feat_vector_corrupted:"\u5411\u91CF\u7D22\u5F15\u5DF2\u635F\u574F \u2014 \u9700\u8981\u5F3A\u5236\u91CD\u5EFA\u3002",feat_vector_desc:"\u5411\u91CF\u6570\u636E\u5E93\u901A\u8FC7\u5D4C\u5165\u6A21\u578B\u5B9E\u73B0 OCR \u5168\u6587\u7684\u8BED\u4E49\u641C\u7D22\u3002\u6587\u6863\u88AB\u5207\u5206\u4E3A\u6587\u672C\u5757\uFF08chunk\uFF09\uFF0C\u7F16\u7801\u4E3A\u5411\u91CF\u5B58\u5165 ChromaDB\u3002\u652F\u6301\u672C\u5730\u6A21\u578B\uFF08\u514D\u8D39\uFF0CCPU \u8FD0\u884C\uFF09\u6216 OpenAI API\uFF08\u4ED8\u8D39\uFF0C\u66F4\u5FEB\u901F\uFF09\u3002",feat_vector_enable:"\u542F\u7528\u5411\u91CF\u68C0\u7D22",feat_vector_enable_desc:"\u5BF9 OCR \u5168\u6587\u8FDB\u884C\u8BED\u4E49\u641C\u7D22\u3002\u9700\u5B89\u88C5: pip install chromadb sentence-transformers openai (~500MB)\u3002",feat_vector_rebuild_force_btn:"\u5F3A\u5236\u91CD\u5EFA",feat_verify:"\u9A8C\u8BC1",feat_verify_btn:"\u9A8C\u8BC1",field_paddleocr:"PaddleOCR API \u5BC6\u94A5",field_python_custom:"\u81EA\u5B9A\u4E49 Python \u8DEF\u5F84",field_python_interp:"\u5F53\u524D Python \u89E3\u91CA\u5668",field_zotero_data:"Zotero \u6570\u636E\u76EE\u5F55",field_zotero_placeholder:"\u53EF\u9009\uFF0C\u7528\u4E8E\u81EA\u52A8\u68C0\u6D4B PDF",guide_ocr:"\u8FD0\u884C OCR",guide_ocr_desc:"Dashboard \u4E2D\u70B9 Run OCR\uFF0C\u63D0\u53D6 PDF \u5168\u6587\u4E0E\u56FE\u8868",guide_open:"\u6253\u5F00 Dashboard",guide_open_desc:"Ctrl+P \u2192 \u8F93\u5165 PaperForge: Open Dashboard\uFF0C\u6216\u70B9\u5DE6\u4FA7\u4E66\u672C\u56FE\u6807",guide_sync:"\u540C\u6B65\u6587\u732E",guide_sync_desc:"Dashboard \u4E2D\u70B9 Sync Library\uFF0C\u4ECE Zotero \u62C9\u53D6\u6587\u732E\u751F\u6210\u7B14\u8BB0",header_title:"PaperForge",install_bootstrapping:"\u672A\u68C0\u6D4B\u5230 PaperForge Python \u5305\uFF0C\u6B63\u5728\u81EA\u52A8\u5B89\u88C5\u2026",install_btn:"\u5F00\u59CB\u5B89\u88C5",install_btn_retry:"\u91CD\u8BD5",install_btn_running:"\u6B63\u5728\u5B89\u88C5...",install_complete:"\u2713 \u5B89\u88C5\u5B8C\u6210\uFF01",install_failed:"\u2717 \u5B89\u88C5\u5931\u8D25\uFF1A",install_validating:"\u6B63\u5728\u6821\u9A8C\u5B89\u88C5\u73AF\u5883\u2026",jump_to_deep_reading:"\u8DF3\u8F6C\u5230\u7CBE\u8BFB",label_agent:"Agent \u5E73\u53F0",nav_close:"\u5173\u95ED",nav_next:"\u4E0B\u4E00\u6B65 \u2192",nav_prev:"\u2190 \u4E0A\u4E00\u6B65",no_pending_ocr:"\u6240\u6709 OCR \u4EFB\u52A1\u5DF2\u5B8C\u6210",not_set:"\u672A\u8BBE\u7F6E",notice_check_fail:"\u672A\u901A\u8FC7: ",notice_python_missing:"Python \u672A\u68C0\u6D4B\u5230\uFF0C\u8BF7\u5148\u5B89\u88C5 Python 3.10+ \u5E76\u52A0\u5165 PATH",ocr_privacy_title:"OCR \u9690\u79C1\u63D0\u793A",ocr_privacy_warning:"OCR \u4F1A\u5C06 PDF \u4E0A\u4F20\u5230 PaddleOCR API \u8FDB\u884C\u5904\u7406\u3002\u8BF7\u4E0D\u8981\u4E0A\u4F20\u5305\u542B\u654F\u611F\u4FE1\u606F\u6216\u65E0\u6CD5\u5916\u4F20\u7684\u6587\u732E\u3002",ocr_queue_add:"\u52A0\u5165 OCR \u961F\u5217",ocr_queue_added:"\u5DF2\u52A0\u5165 OCR \u961F\u5217",ocr_queue_remove:"\u79FB\u51FA OCR \u961F\u5217",ocr_queue_removed:"\u5DF2\u79FB\u51FA OCR \u961F\u5217",ocr_understand:"\u6211\u4E86\u89E3\uFF0C\u7EE7\u7EED",optional_later:"\uFF08\u7A0D\u540E\u53EF\u5728\u8BBE\u7F6E\u4E2D\u8865\u5145\uFF09",orphan_delete_failed:"\u6E05\u7406\u5931\u8D25",orphan_delete_selected:"\u5220\u9664 {count} \u7BC7",orphan_deleted:"\u5DF2\u5220\u9664 {count} \u7BC7\u6B8B\u7559\u6587\u732E",orphan_desc:"\u8FD9\u4E9B\u6587\u732E\u5DF2\u4ECE Zotero \u4E2D\u79FB\u9664\u3002",orphan_deselect_all:"\u53D6\u6D88\u5168\u9009",orphan_explain:"\u5DF2\u4ECE Zotero \u4E2D\u79FB\u9664\u3002\u5DE5\u4F5C\u533A\u6587\u4EF6\u4ECD\u4FDD\u7559\u5728\u78C1\u76D8\u4E0A\u3002",orphan_keep_all:"\u4FDD\u7559\u5168\u90E8",orphan_none_selected:"\u672A\u9009\u62E9\u4EFB\u4F55\u6587\u732E",orphan_select_all:"\u5168\u9009",orphan_title:"\u53D1\u73B0 {count} \u7BC7\u6B8B\u7559\u6587\u732E",panel_actions:"\u5FEB\u6377\u64CD\u4F5C",prep_bbt:"Better BibTeX",prep_bbt_desc:"Zotero \u2192 \u5DE5\u5177 \u2192 \u63D2\u4EF6 \u2192 \u5B89\u88C5 Better BibTeX",prep_export:"BBT \u81EA\u52A8\u5BFC\u51FA",prep_export_desc:"\u53F3\u952E\u6587\u732E\u5B50\u5206\u7C7B \u2192 \u5BFC\u51FA\u5206\u7C7B \u2192 BetterBibTeX JSON \u2192 \u52FE\u9009\u4FDD\u6301\u66F4\u65B0 \u2192 \u5BFC\u51FA\u5230\uFF08JSON \u6587\u4EF6\u540D\u5373\u4E3A Base \u540D\uFF09\uFF1A",prep_key:"PaddleOCR Key",prep_key_desc:"\u5728 https://aistudio.baidu.com/paddleocr \u83B7\u53D6 API Key",prep_python:"Python 3.10+",prep_python_desc:"\u786E\u4FDD Python \u53EF\u547D\u4EE4\u884C\u8C03\u7528\u3002\u70B9\u51FB\u4E0B\u65B9\u6309\u94AE\u81EA\u52A8\u68C0\u6D4B\u3002",prep_zotero:"Zotero \u684C\u9762\u7248",prep_zotero_desc:"\u5B89\u88C5 Zotero (https://www.zotero.org)",run_in_agent:"\u5728 {0} \u4E2D\u8FD0\u884C",runtime_health:"\u8FD0\u884C\u65F6\u72B6\u6001",runtime_health_checking:"\u6B63\u5728\u68C0\u6D4B\u2026",runtime_health_desc:"\u68C0\u67E5\u63D2\u4EF6\u4E0E Python \u8FD0\u884C\u65F6\u7248\u672C\u7684\u5339\u914D\u60C5\u51B5\uFF0C\u5E76\u786E\u8BA4\u5DF2\u90E8\u7F72\u7684 skill contract \u662F\u5426\u4E3A\u5F53\u524D\u7248\u672C\u3002",runtime_health_match:"\u5339\u914D",runtime_health_mismatch:"\u4E0D\u5339\u914D",runtime_health_package_ver:"Python \u5305 v{0}",runtime_health_plugin_ver:"\u63D2\u4EF6 v{0}",runtime_health_sync:"\u540C\u6B65\u8FD0\u884C\u65F6",runtime_health_sync_done:"\u8FD0\u884C\u65F6\u5DF2\u540C\u6B65\u81F3 v{0}",runtime_health_sync_fail:"\u8FD0\u884C\u65F6\u540C\u6B65\u5931\u8D25\uFF1A{0}",runtime_health_syncing:"\u6B63\u5728\u540C\u6B65\u2026",section_config:"\u5F53\u524D\u914D\u7F6E",section_guide:"\u64CD\u4F5C\u65B9\u5F0F",section_prep:"\u5B89\u88C5\u51C6\u5907",section_prep_desc:"\u9996\u6B21\u4F7F\u7528\u524D\uFF0C\u8BF7\u4F9D\u6B21\u5B8C\u6210\u4EE5\u4E0B\u51C6\u5907\uFF1A",setup_done:"\u2713 PaperForge \u73AF\u5883\u5DF2\u914D\u7F6E\u5B8C\u6210",setup_pending:"\u5C1A\u672A\u5B89\u88C5\uFF0C\u5B8C\u6210\u5B89\u88C5\u51C6\u5907\u540E\u70B9\u51FB\u5B89\u88C5\u5411\u5BFC",tab_features:"\u529F\u80FD",tab_setup:"\u5B89\u88C5",tab_maintenance:"\u7EF4\u62A4",validate_base:"Base \u76EE\u5F55\u672A\u586B\u5199",validate_fail:"\u914D\u7F6E\u9A8C\u8BC1\u5931\u8D25",validate_index:"\u7D22\u5F15\u76EE\u5F55\u672A\u586B\u5199",validate_key:"PaddleOCR API \u5BC6\u94A5\u672A\u586B\u5199",validate_notes:"\u6B63\u6587\u76EE\u5F55\u672A\u586B\u5199",validate_resources:"\u8D44\u6E90\u76EE\u5F55\u672A\u586B\u5199",validate_system:"\u7CFB\u7EDF\u76EE\u5F55\u672A\u586B\u5199",validate_vault:"Vault \u8DEF\u5F84\u672A\u586B\u5199",validate_zotero:"Zotero \u6570\u636E\u76EE\u5F55\u4E3A\u5FC5\u586B\u9879",wizard_agent_hint:"\u9009\u62E9\u4F60\u4F7F\u7528\u7684 AI Agent \u5E73\u53F0\uFF0C\u5B89\u88C5\u65F6\u5C06\u6309\u5BF9\u5E94\u683C\u5F0F\u90E8\u7F72\u6280\u80FD\u6587\u4EF6\uFF1A",wizard_dir_hint:"\u8D44\u6E90\u76EE\u5F55\u662F\u6587\u732E\u6570\u636E\u7684\u7EDF\u4E00\u6839\u76EE\u5F55\uFF0C\u4EE5\u4E0B\u5B50\u76EE\u5F55\u5C06\u521B\u5EFA\u5728\u5176\u5185\u90E8\uFF1A",wizard_dir_sub_hint:"\u8D44\u6E90\u76EE\u5F55\u5185\u7684\u4E24\u4E2A\u5B50\u76EE\u5F55\uFF1A",wizard_intro:"\u672C\u5411\u5BFC\u5C06\u5F15\u5BFC\u60A8\u5B8C\u6210 PaperForge \u73AF\u5883\u7684\u5B8C\u6574\u914D\u7F6E\u3002\u5B89\u88C5\u8FC7\u7A0B\u4F1A\u81EA\u52A8\u521B\u5EFA\u6240\u6709\u76EE\u5F55\u7ED3\u6784\uFF0C\u65E0\u9700\u624B\u52A8\u64CD\u4F5C\u3002",wizard_keys_hint:"\u4EE5\u4E0B\u4E3A API \u5BC6\u94A5\u4E0E Zotero \u914D\u7F6E\uFF1A",wizard_preview:"\u7CFB\u7EDF\u6587\u4EF6\u548C Agent \u914D\u7F6E\u4F4D\u4E8E Vault \u6839\u76EE\u5F55\u4E0B\u3002\u6587\u732E\u6570\u636E\uFF08\u6B63\u6587\u3001\u7D22\u5F15\uFF09\u7EDF\u4E00\u5B58\u653E\u5728\u8D44\u6E90\u76EE\u5F55\u5185\u3002\u5B89\u88C5\u540E\u4ECD\u53EF\u5728\u8BBE\u7F6E\u4E2D\u4FEE\u6539\u3002",wizard_safety:"\u5B89\u5168\u8BF4\u660E\uFF1A\u5982\u679C\u4F60\u9009\u62E9\u7684\u76EE\u5F55\u91CC\u5DF2\u7ECF\u6709\u6587\u4EF6\uFF0C\u5B89\u88C5\u5411\u5BFC\u4F1A\u4FDD\u7559\u5DF2\u6709\u5185\u5BB9\uFF0C\u53EA\u8865\u5145\u7F3A\u5931\u7684 PaperForge \u6587\u4EF6\u548C\u76EE\u5F55\u3002",wizard_step1:"\u6982\u89C8",wizard_step2:"\u76EE\u5F55",wizard_step3:"Agent",wizard_step4:"\u5B89\u88C5",wizard_step5:"\u5B8C\u6210",wizard_skip_ocr_desc:"OCR \u529F\u80FD\u5728\u914D\u7F6E\u6709\u6548\u7684 PaddleOCR API \u5BC6\u94A5\u4E4B\u524D\u4E0D\u53EF\u7528\u3002\u60A8\u53EF\u4EE5\u7EE7\u7EED\u5B8C\u6210\u8BBE\u7F6E\uFF0C\u7A0D\u540E\u5728\u8BBE\u7F6E\u4E2D\u914D\u7F6E\u3002",wizard_skip_ocr_continue:"\u7EE7\u7EED\uFF0C\u7A0D\u540E\u914D\u7F6E\u5BC6\u94A5",wizard_skip_ocr_back:"\u8FD4\u56DE\u914D\u7F6E",wizard_api_hint_skip:"OCR \u5BC6\u94A5\u4E3A\u9009\u586B\u9879 \u2014 \u53EF\u8DF3\u8FC7\uFF0C\u7A0D\u540E\u5728\u8BBE\u7F6E\u4E2D\u914D\u7F6E\u3002",wizard_sys_hint:"\u72EC\u7ACB\u4E8E\u8D44\u6E90\u76EE\u5F55\u7684\u7CFB\u7EDF\u6587\u4EF6\uFF1A",wizard_title:"PaperForge \u5B89\u88C5\u5411\u5BFC",ocr_maint_no_action:"\u65E0\u9700\u5904\u7406",ocr_maint_rebuild:"\u5EFA\u8BAE\u91CD\u5EFA",ocr_maint_failed:"OCR \u5931\u8D25",ocr_maint_limited:"\u7ED3\u679C\u4E00\u822C",ocr_maint_needs_attention:"\u9700\u8981\u5904\u7406",ocr_maint_limitations:"\u7ED3\u679C\u8BF4\u660E",ocr_maint_hero_ok:"OCR \u6574\u4F53\u6B63\u5E38\u3002",ocr_maint_hero_warn:"OCR \u9700\u8981\u5173\u6CE8\uFF1A{rebuild} \u7BC7\u5EFA\u8BAE\u91CD\u5EFA\uFF0C{failed} \u7BC7\u5904\u7406\u5931\u8D25\u3002",ocr_maint_hero_note:"\u672C\u9875\u53EA\u63D0\u793A\u7EF4\u62A4\u540E\u5927\u6982\u7387\u4F1A\u6539\u5584\u7684\u95EE\u9898\u3002\u90E8\u5206\u8BBA\u6587\u6548\u679C\u4E00\u822C\uFF0C\u7EF4\u62A4\u672A\u5FC5\u80FD\u6539\u5584\u3002",ocr_maint_limitations_intro:"\u8FD9\u7C7B\u8BBA\u6587\u901A\u5E38\u8868\u793A\u7248\u5F0F\u590D\u6742\u6216\u4FE1\u53F7\u504F\u5F31\uFF0CPaperForge \u76EE\u524D\u6CA1\u6709\u9AD8\u7F6E\u4FE1\u5EA6\u7684\u7EF4\u62A4\u5EFA\u8BAE\u3002",ocr_maint_all_papers:"\u5168\u90E8\u8BBA\u6587",ocr_maint_rebuild_btn:"\u91CD\u5EFA\u7ED3\u679C",ocr_maint_redo_btn:"\u91CD\u65B0 OCR"}},Ge=null;function Nt(g){try{let u=g.vault;if(typeof u.getConfig=="function"){let e=u.getConfig("language");if(e&&String(e).startsWith("zh"))return"zh"}}catch(u){}try{if(typeof localStorage!="undefined"){let u=localStorage.getItem("language");if(u&&String(u).startsWith("zh"))return"zh"}}catch(u){}return"en"}function gt(g){Ge=Nt(g)==="zh"?Ue.zh:Ue.en}function i(g){return Ge&&Ge[g]||Ue.en[g]||g}var F=require("obsidian"),L=q(require("fs")),Z=q(require("path")),Ke=q(require("os")),$=require("child_process");var Ft=q(Xe());var ie=q(require("fs")),ae=q(require("path")),ft=q(require("os")),pe=require("child_process"),Ye=null,ht=!1;function z(g,u,e,t){let r=e||ie,n=t||pe.execFileSync;if(u&&u.python_path&&u.python_path.trim()){let l=u.python_path.trim();if(r.existsSync(l))return{path:l,source:"manual",extraArgs:[]}}let a=[ae.join(g,".paperforge-test-venv","Scripts","python.exe"),ae.join(g,".venv","Scripts","python.exe"),ae.join(g,"venv","Scripts","python.exe")];for(let l of a)try{if(r.existsSync(l))return{path:l,source:"auto-detected",extraArgs:[]}}catch(o){}let s=[{path:"py",extraArgs:["-3"]},{path:"python",extraArgs:[]},{path:"python3",extraArgs:[]}];for(let l of s)try{let o=n(l.path,[...l.extraArgs,"--version"],{encoding:"utf-8",timeout:5e3,windowsHide:!0});if(o&&o.toLowerCase().includes("python"))return{path:l.path,source:"auto-detected",extraArgs:l.extraArgs}}catch(o){}return{path:"python",source:"auto-detected",extraArgs:[]}}function _t(g,u,e,t,r){t===void 0&&(t=1e4);let n=r||pe.execFile;return new Promise(a=>{n(g,["-c","import paperforge; print(paperforge.__version__)"],{cwd:e,timeout:t},(s,l)=>{if(s){a({status:"not-installed",pyVersion:null,pluginVersion:u,error:s.message});return}let o=l&&l.trim()||null;a(o===u?{status:"match",pyVersion:o,pluginVersion:u,error:null}:{status:"mismatch",pyVersion:o,pluginVersion:u,error:null})})})}function mt(g,u,e){e===void 0&&(e=[]);let t=`paperforge==${u}`,r=`git+https://github.com/LLLin000/PaperForge.git@${u}`,n=[...e,"-m","pip","install","--upgrade",t],a=[...e,"-m","pip","install","--upgrade",r];return{cmd:g,url:r,args:a,pypiArgs:n,gitArgs:a,timeout:12e4}}function yt(g,u,e,t,r,n){let a=r||pe.spawn;return new Promise(s=>{let l=Date.now(),o={cwd:e,timeout:t,windowsHide:!0};n&&(o.env=n);let c=a(g,u,o),p=[],h=[];c.stdout.on("data",d=>{p.push(d.toString("utf-8"))}),c.stderr.on("data",d=>{h.push(d.toString("utf-8"))}),c.on("close",d=>{s({stdout:p.join(""),stderr:h.join(""),exitCode:d,elapsed:Date.now()-l})}),c.on("error",d=>{s({stdout:p.join(""),stderr:h.join("")+`
`+d.message,exitCode:-1,elapsed:Date.now()-l})})})}function Qe(){if(ht)return Ye;ht=!0;try{let g;if(process.platform==="win32"){let u=process.env.ComSpec||"C:\\Windows\\System32\\cmd.exe";g=(0,pe.execFileSync)(u,["/c","where","git"],{timeout:5e3,windowsHide:!0,encoding:"utf-8"})}else g=(0,pe.execFileSync)("which",["git"],{timeout:5e3,encoding:"utf-8"});if(g){let u=g.split(`
`)[0].trim();u&&(Ye=ae.dirname(u))}}catch(g){}return Ye}function be(){let g={...process.env},u=process.platform,e=ft.homedir(),t=[],r=Qe();r&&t.push(r),u==="darwin"?t.push("/opt/homebrew/bin","/usr/local/bin","/usr/bin",`${e}/.local/bin`):u==="linux"&&t.push("/usr/local/bin","/usr/bin",`${e}/.local/bin`);let n=g.PATH||"";return g.PATH=[...t,n].filter(Boolean).join(ae.delimiter),g}function bt(g){return String(g).toLowerCase().replace(/[^a-z0-9]/g,"").includes("betterbibtex")}function et(g){if(!g)return!1;try{if(!ie.existsSync(g))return!1;for(let u of ie.readdirSync(g))if(bt(u))return!0}catch(u){}return!1}function $e(g){if(!g)return!1;try{if(!ie.existsSync(g))return!1;for(let u of ie.readdirSync(g)){let e=ae.join(g,u,"extensions");try{if(!ie.existsSync(e))continue;for(let t of ie.readdirSync(e))if(bt(t))return!0}catch(t){}}}catch(u){}return!1}var ve=q(require("fs")),K=q(require("path")),vt=require("child_process"),oe=null;function $t(g,u){let e=u||ve,t=K.join(g,"paperforge.json"),r={system_dir:"System",resources_dir:"Resources",literature_dir:"Literature",base_dir:"Bases"};try{if(!e.existsSync(t))return{...r,_warning:"paperforge.json not found; using defaults"};let n=e.readFileSync(t,"utf-8"),a=JSON.parse(n),s=a.vault_config||{};return{system_dir:s.system_dir||a.system_dir||r.system_dir,resources_dir:s.resources_dir||a.resources_dir||r.resources_dir,literature_dir:s.literature_dir||a.literature_dir||r.literature_dir,base_dir:s.base_dir||a.base_dir||r.base_dir,_warning:null}}catch(n){return console.warn("PaperForge: Failed to read paperforge.json, using defaults",n),{...r,_warning:"paperforge.json invalid; using defaults"}}}function le(g,u){let e=$t(g,u),t=K.join(g,e.system_dir,"PaperForge");return{vault:g,systemDir:t,indexesDir:K.join(t,"indexes"),logsDir:K.join(t,"logs"),dbPath:K.join(t,"indexes","paperforge.db"),memoryStatePath:K.join(t,"indexes","memory-runtime-state.json"),vectorStatePath:K.join(t,"indexes","vector-runtime-state.json"),healthStatePath:K.join(t,"indexes","runtime-health.json"),buildStatePath:K.join(t,"indexes","vector-build-state.json"),orphanStatePath:K.join(t,"indexes","sync-orphan-state.json"),exportsDir:K.join(t,"exports"),ocrDir:K.join(t,"ocr"),pluginDataPath:K.join(g,".obsidian","plugins","paperforge","data.json"),pfJsonPath:K.join(g,"paperforge.json"),configWarning:e._warning}}function tt(g){try{return ve.existsSync(g)?JSON.parse(ve.readFileSync(g,"utf-8")):null}catch(u){return null}}function jt(g){let u=le(g);return tt(u.memoryStatePath)}function Oe(g){let u=le(g);return tt(u.vectorStatePath)}function rt(g){let u=le(g);return tt(u.healthStatePath)}function xt(g){var e;let u=rt(g);return!!(u&&((e=u.summary)==null?void 0:e.status)==="ok")}function je(g){let u=jt(g);return!u||u.paper_count_db===0?"DB not found. Run paperforge memory build.":"Papers: "+u.paper_count_db+" | "+(u.fresh?"fresh":"stale")}function we(g){let u=Oe(g);return u?u.healthy===!1?"Vector index unreadable - rebuild required":"Chunks: "+u.chunk_count+" | "+u.model+" | "+u.mode:"Status unavailable"}function de(g,u){if(oe)return oe;if(u&&u.python_path&&u.python_path.trim()){let r=u.python_path.trim();if(ve.existsSync(r))return oe={path:r,source:"manual",extraArgs:[]},oe}let e=[K.join(g,".paperforge-test-venv","Scripts","python.exe"),K.join(g,".venv","Scripts","python.exe"),K.join(g,"venv","Scripts","python.exe")];for(let r=0;r({...a,_selected:!0,_idx:s})),this.vaultPath=r,this.py=n}_updateUI(){let e=this.orphans.filter(t=>t._selected);this._countEl.setText(i("orphan_delete_selected").replace("{count}",String(e.length))),this._selectAllBtn.setText(e.length===this.orphans.length?i("orphan_deselect_all"):i("orphan_select_all"));for(let t of this.orphans){let r=this._rowEls[t._idx];r&&r.toggleClass("paperforge-orphan-dimmed",!t._selected)}}onOpen(){let{contentEl:e}=this;e.addClass("paperforge-modal"),e.createEl("h2",{text:i("orphan_title").replace("{count}",String(this.orphans.length))}),e.createEl("p",{cls:"paperforge-modal-desc",text:i("orphan_desc")}),this._rowEls=[];let t=e.createEl("div",{cls:"paperforge-orphan-list"});for(let n of this.orphans){let a=t.createEl("div",{cls:"paperforge-orphan-row"+(n._selected?"":" paperforge-orphan-dimmed")});this._rowEls.push(a);let s=a.createEl("div",{cls:"paperforge-orphan-info"}),l=s.createEl("div",{cls:"paperforge-orphan-header"});l.createEl("span",{cls:"paperforge-orphan-key",text:n.citation_key||n.key});let o=l.createEl("span",{cls:"paperforge-orphan-tags"});o.createEl("span",{cls:"paperforge-tag "+(n.has_pdf?"tag-pdf":"tag-nopdf"),text:n.has_pdf?"PDF":"no PDF"}),n.collection_path&&o.createEl("span",{cls:"paperforge-tag tag-collection",text:n.collection_path}),n.title&&s.createEl("div",{cls:"paperforge-orphan-title",text:n.title});let c=[];n.authors&&c.push(n.authors),n.year&&c.push(n.year),c.length>0&&s.createEl("div",{cls:"paperforge-orphan-meta",text:c.join(" \xB7 ")}),s.createEl("div",{cls:"paperforge-orphan-explain",text:i("orphan_explain")}),a.addEventListener("click",()=>{n._selected=!n._selected,this._updateUI()})}let r=e.createEl("div",{cls:"paperforge-modal-actions"});this._selectAllBtn=r.createEl("button",{cls:"paperforge-step-btn",text:"Deselect all"}),this._selectAllBtn.addEventListener("click",()=>{let n=this.orphans.every(a=>a._selected);for(let a of this.orphans)a._selected=!n;this._updateUI()}),this._countEl=r.createEl("button",{cls:"paperforge-step-btn mod-cta",text:"Delete "+this.orphans.length+" selected"}),r.createEl("button",{cls:"paperforge-step-btn",text:"Keep all"}).addEventListener("click",()=>this.close()),this._countEl.addEventListener("click",()=>{let n=this.orphans.filter(s=>s._selected);if(n.length===0){new ee.Notice(i("orphan_none_selected"));return}if(this._countEl.setText("Deleting..."),this._countEl.setAttr("disabled",""),this._selectAllBtn.setAttr("disabled",""),!this.py||!this.py.path){new ee.Notice("PaperForge: Python not found"),this.close();return}let a=n.map(s=>s.key);(0,Me.execFile)(this.py.path,[...this.py.extraArgs,"-m","paperforge","--vault",this.vaultPath,"prune","--force","--json",...a],{cwd:this.vaultPath,timeout:6e4},(s,l)=>{if(s){new ee.Notice("PaperForge: prune failed"),this.close();return}try{let o=JSON.parse(l),c=o.data&&o.data.deleted||[];new ee.Notice("Deleted "+c.length+" orphan workspace(s)")}catch(o){new ee.Notice("PaperForge: prune done")}this.close()})})}onClose(){this.contentEl.empty()}};function He(g,u,e){console.log("[PF] checkOrphanState called");try{let r=le(e).orphanStatePath;if(!se.existsSync(r)){console.log("[PF] orphan file NOT FOUND");return}console.log("[PF] orphan file FOUND");let n=se.readFileSync(r,"utf-8"),s=JSON.parse(n).orphans||[];if(console.log("[PF] orphans count:",s.length),s.length===0)return;let l=de(e,u.settings);console.log("[PF] py.path:",l?l.path:"null"),new nt(g,s,e,l).open(),se.unlinkSync(r),console.log("[PF] orphan file cleaned")}catch(t){console.log("[PF] checkOrphanState exception:",t.message||t)}}var Le=class extends ee.Modal{constructor(e,t){super(e);this._pendingSave=null;this._showSkipConfirm=!1;this.plugin=t,this._step=1}onOpen(){this._render()}onClose(){this.contentEl.empty()}_render(){let{contentEl:e}=this;e.empty(),e.addClass("paperforge-modal"),this._renderStepIndicator(),this._renderStepContent(),this._renderNavigation()}_renderStepIndicator(){let e=[i("wizard_step1"),i("wizard_step2"),i("wizard_step3"),i("wizard_step4"),i("wizard_step5")],t=this.contentEl.createEl("div",{cls:"paperforge-step-bar"});e.forEach((r,n)=>{let a=n+1,s=t.createEl("div",{cls:`paperforge-step-dot ${a===this._step?"active":""} ${a1&&e.createEl("button",{cls:"paperforge-step-btn",text:i("nav_prev")}).addEventListener("click",()=>{this._step--,this._showSkipConfirm=!1,this._render()}),this._step<5?e.createEl("button",{cls:"paperforge-step-btn mod-cta",text:i("nav_next")}).addEventListener("click",()=>{if(this._step===3){let r=this._validateStep3();if(r.blocked){if(r.reason==="zotero")return;if(r.reason==="ocr"){this._showSkipConfirm=!0,this._render();return}}}this._step++,this._showSkipConfirm=!1,this._render()}):e.createEl("button",{cls:"paperforge-step-btn",text:i("nav_close")}).addEventListener("click",()=>this.close())}_validateStep3(){let e=this.plugin.settings,t=kt(this._apiKeyValidated,e.zotero_data_dir);if(t.reason==="ocr")return t;let r=(e.zotero_data_dir||"").trim();if(!r)return new ee.Notice("Zotero \u6570\u636E\u76EE\u5F55\u4E3A\u5FC5\u586B\u9879\uFF0C\u8BF7\u586B\u5199\u8DEF\u5F84"),{blocked:!0,reason:"zotero"};if(!se.existsSync(r))return new ee.Notice("Zotero \u6570\u636E\u76EE\u5F55\u8DEF\u5F84\u4E0D\u5B58\u5728"),{blocked:!0,reason:"zotero"};if(!se.statSync(r).isDirectory())return new ee.Notice("Zotero \u6570\u636E\u76EE\u5F55\u8DEF\u5F84\u4E0D\u662F\u4E00\u4E2A\u76EE\u5F55"),{blocked:!0,reason:"zotero"};let n=wt.join(r,"storage");return!se.existsSync(n)||!se.statSync(n).isDirectory()?(new ee.Notice("Zotero \u6570\u636E\u76EE\u5F55\u4E2D\u672A\u627E\u5230 storage/ \u5B50\u76EE\u5F55"),{blocked:!0,reason:"zotero"}):{blocked:!1}}_stepOverview(e){e.createEl("h2",{text:i("wizard_title")}),e.createEl("p",{text:i("wizard_intro")});let t=this.plugin.settings,r=this.app.vault.adapter.basePath,n=e.createEl("div",{cls:"paperforge-dir-tree"}),a=n.createEl("div",{cls:"paperforge-dir-node root"});a.textContent=`\u{1F4C1} Vault (${r})`;let s=n.createEl("div",{cls:"paperforge-dir-children"}),l=s.createEl("div",{cls:"paperforge-dir-node folder"});l.textContent=`\u{1F4C1} ${t.resources_dir||"Resources"}/ \u2014 \u6587\u732E\u5361\u7247\u76EE\u5F55\uFF08Base \u6570\u636E\u6765\u6E90\uFF09`,l.createEl("div",{cls:"paperforge-dir-children"}).createEl("div",{cls:"paperforge-dir-node file",text:`\u{1F4C1} ${t.literature_dir||"Literature"}/ \u2014 \u6587\u732E\u5361\u7247`}),s.createEl("div",{cls:"paperforge-dir-node folder",text:`\u{1F4C1} ${t.base_dir||"Bases"}/ \u2014 \u6570\u636E\u7BA1\u7406\u9762\u677F`}),s.createEl("div",{cls:"paperforge-dir-node folder",text:`\u{1F4C1} ${t.system_dir||"System"}/ \u2014 Zotero \u8F6F\u94FE\u63A5 + PaperForge \u7CFB\u7EDF\u6587\u4EF6\u5939`}),e.createEl("p",{text:i("wizard_preview"),cls:"paperforge-modal-hint"}),e.createEl("p",{text:i("wizard_safety"),cls:"paperforge-modal-hint"});let c=e.createEl("div",{cls:"paperforge-summary"}),p=[{label:i("dir_resources"),val:`${r}/${t.resources_dir||"Resources"}`},{label:i("dir_notes"),val:`${r}/${t.resources_dir||"Resources"}/${t.literature_dir||"Literature"}`},{label:i("dir_base"),val:`${r}/${t.base_dir||"Bases"}`},{label:i("dir_system"),val:`${r}/${t.system_dir||"System"}`}];for(let h of p){let d=c.createEl("div",{cls:"paperforge-summary-row"});d.createEl("span",{cls:"paperforge-summary-label",text:h.label}),d.createEl("span",{cls:"paperforge-summary-value",text:h.val})}}_stepDirectories(e){e.createEl("h2",{text:i("wizard_step2")}),e.createEl("p",{text:i("wizard_intro")});let t=this.plugin.settings,r=this.app.vault.adapter.basePath;this._modalField(e,i("dir_vault"),r,!0),e.createEl("p",{text:i("wizard_dir_hint"),cls:"paperforge-modal-hint"}),this._modalInput(e,"\u8D44\u6E90\u76EE\u5F55\uFF08\u521B\u5EFA\u6587\u732E\u5361\u7247\u76EE\u5F55\u7684\u5730\u65B9\uFF09","resources_dir",t.resources_dir,"Resources"),e.createEl("p",{text:i("wizard_dir_sub_hint"),cls:"paperforge-modal-hint"}),this._modalInput(e,"\u6587\u732E\u5361\u7247\u76EE\u5F55\uFF08\u5B58\u653E\u6587\u732E\u5361\u7247\u7684\u5730\u65B9\uFF0CBase \u6570\u636E\u6765\u6E90\uFF09","literature_dir",t.literature_dir,"Literature"),e.createEl("p",{text:i("wizard_sys_hint"),cls:"paperforge-modal-hint"}),this._modalInput(e,"\u7CFB\u7EDF\u76EE\u5F55\uFF08\u5B58\u653E Zotero \u8F6F\u94FE\u63A5\u548C PaperForge \u7CFB\u7EDF\u6587\u4EF6\uFF09","system_dir",t.system_dir,"System"),this._modalInput(e,"Base \u76EE\u5F55\uFF08\u5B58\u653E\u6570\u636E\u7BA1\u7406\u9762\u677F\u7684\u5730\u65B9\uFF09","base_dir",t.base_dir,"Bases"),e.createEl("p",{text:i("wizard_safety"),cls:"paperforge-modal-hint"});let n=e.createEl("div",{cls:"paperforge-summary"}),a=[{label:i("dir_resources"),val:`${r}/${t.resources_dir||""}`},{label:i("dir_notes"),val:`${r}/${t.resources_dir||""}/${t.literature_dir||""}`},{label:i("dir_system"),val:`${r}/${t.system_dir||""}`},{label:i("dir_base"),val:`${r}/${t.base_dir||""}`}];for(let s of a){let l=n.createEl("div",{cls:"paperforge-summary-row"});l.createEl("span",{cls:"paperforge-summary-label",text:s.label}),l.createEl("span",{cls:"paperforge-summary-value",text:s.val})}}_stepKeys(e){if(e.createEl("h2",{text:i("wizard_step3")}),this._showSkipConfirm){this._renderSkipConfirm(e);return}let t=this.plugin.settings;e.createEl("p",{text:i("wizard_agent_hint"),cls:"paperforge-modal-hint"});let r=[{key:"opencode",name:"OpenCode"},{key:"claude",name:"Claude Code"},{key:"cursor",name:"Cursor"},{key:"github_copilot",name:"GitHub Copilot"},{key:"windsurf",name:"Windsurf"},{key:"codex",name:"Codex"},{key:"gemini",name:"Gemini CLI"},{key:"cline",name:"Cline"}],n=e.createEl("div",{cls:"paperforge-modal-field"});n.createEl("label",{cls:"paperforge-modal-label",text:i("label_agent")});let a=n.createEl("select",{cls:"paperforge-modal-select"});for(let h of r){let d=a.createEl("option",{text:h.name,attr:{value:h.key}});h.key===(t.agent_platform||"opencode")&&(d.selected=!0)}a.addEventListener("change",()=>{t.agent_platform=a.value,this._pendingSave&&clearTimeout(this._pendingSave),this._pendingSave=setTimeout(()=>{this.plugin.saveSettings(),this._pendingSave=null},500)}),e.createEl("p",{text:i("wizard_keys_hint"),cls:"paperforge-modal-hint"});let s=e.createEl("div",{cls:"paperforge-modal-field"});s.createEl("label",{cls:"paperforge-modal-label",text:i("field_paddleocr")});let l=s.createEl("input",{cls:"paperforge-modal-input",attr:{type:"password",placeholder:"API Key"}});l.value=t.paddleocr_api_key||"",this._apiKeyValidated=!1,this._apiKeyStatus=s.createEl("span",{cls:"paperforge-apikey-status",text:""});let o=s.createEl("button",{cls:"paperforge-step-btn",text:"\u9A8C\u8BC1"});o.addEventListener("click",()=>this._validateApiKey(l.value,o)),l.addEventListener("input",()=>{t.paddleocr_api_key=l.value,this._apiKeyValidated=!1,this._apiKeyStatus.textContent="",this._apiKeyStatus.className="paperforge-apikey-status"}),this._pendingSave&&clearTimeout(this._pendingSave),this._pendingSave=setTimeout(()=>{this.plugin.saveSettings(),this._pendingSave=null},500),e.createEl("p",{text:i("wizard_api_hint_skip"),cls:"paperforge-modal-hint"});let c=e.createEl("div",{cls:"paperforge-modal-field"});c.createEl("label",{cls:"paperforge-modal-label",text:i("field_zotero_data")});let p=c.createEl("input",{cls:"paperforge-modal-input",attr:{type:"text",placeholder:i("field_zotero_placeholder")}});p.value=t.zotero_data_dir||"",p.addEventListener("input",()=>{t.zotero_data_dir=p.value,this._pendingSave&&clearTimeout(this._pendingSave),this._pendingSave=setTimeout(()=>{this.plugin.saveSettings(),this._pendingSave=null},500)})}_validateApiKey(e,t){if(!e||e.length<10){this._apiKeyStatus.textContent="\u5BC6\u94A5\u683C\u5F0F\u4E0D\u6B63\u786E\u3002\u53EF\u70B9\u4E0B\u4E00\u6B65\u8DF3\u8FC7\uFF0C\u7B49\u4F1A\u513F\u518D\u914D\u7F6E\u3002",this._apiKeyStatus.className="paperforge-apikey-status error";return}t.disabled=!0,t.textContent="\u9A8C\u8BC1\u4E2D\u2026",this._apiKeyStatus.textContent="\u6B63\u5728\u9A8C\u8BC1\u2026",this._apiKeyStatus.className="paperforge-apikey-status";let r=JSON.stringify({model:"PaddleOCR-VL-1.5"}),n={hostname:"paddleocr.aistudio-app.com",path:"/api/v2/ocr/jobs",method:"POST",headers:{Authorization:"bearer "+e,"Content-Type":"application/json","Content-Length":Buffer.byteLength(r)},timeout:1e4},a=Ct.request(n,s=>{t.disabled=!1,t.textContent="\u9A8C\u8BC1";let l="";s.on("data",o=>l+=o),s.on("end",()=>{try{let o=JSON.parse(l);s.statusCode===400&&o.code===10001?(this._apiKeyStatus.textContent="\u2713 \u5BC6\u94A5\u6709\u6548",this._apiKeyStatus.className="paperforge-apikey-status ok",this._apiKeyValidated=!0):s.statusCode===401?(this._apiKeyStatus.textContent="\u9A8C\u8BC1\u5931\u8D25\uFF1A\u5BC6\u94A5\u65E0\u6548\u3002\u53EF\u70B9\u4E0B\u4E00\u6B65\u8DF3\u8FC7\uFF0C\u7B49\u4F1A\u513F\u518D\u914D\u7F6E\u3002",this._apiKeyStatus.className="paperforge-apikey-status error",this._apiKeyValidated=!1):(this._apiKeyStatus.textContent="\u9A8C\u8BC1\u5931\u8D25\uFF1AAPI \u8FD4\u56DE "+s.statusCode+"\u3002\u53EF\u70B9\u4E0B\u4E00\u6B65\u8DF3\u8FC7\uFF0C\u7B49\u4F1A\u513F\u518D\u914D\u7F6E\u3002",this._apiKeyStatus.className="paperforge-apikey-status error",this._apiKeyValidated=!1)}catch(o){this._apiKeyStatus.textContent="\u9A8C\u8BC1\u5931\u8D25\uFF1A\u65E0\u6CD5\u89E3\u6790\u54CD\u5E94\u3002\u53EF\u70B9\u4E0B\u4E00\u6B65\u8DF3\u8FC7\uFF0C\u7B49\u4F1A\u513F\u518D\u914D\u7F6E\u3002",this._apiKeyStatus.className="paperforge-apikey-status error",this._apiKeyValidated=!1}})});a.on("error",s=>{t.disabled=!1,t.textContent="\u9A8C\u8BC1",this._apiKeyStatus.textContent="\u9A8C\u8BC1\u5931\u8D25\uFF1A\u65E0\u6CD5\u8FDE\u63A5 ("+s.message+")\u3002\u53EF\u70B9\u4E0B\u4E00\u6B65\u8DF3\u8FC7\uFF0C\u7B49\u4F1A\u513F\u518D\u914D\u7F6E\u3002",this._apiKeyStatus.className="paperforge-apikey-status error",this._apiKeyValidated=!1}),a.write(r),a.end()}_renderSkipConfirm(e){e.createEl("p",{text:i("wizard_skip_ocr_desc"),cls:"paperforge-modal-desc"});let t=e.createEl("div",{cls:"paperforge-modal-actions"});t.createEl("button",{cls:"paperforge-step-btn mod-cta",text:i("wizard_skip_ocr_continue")}).addEventListener("click",()=>{this._showSkipConfirm=!1,this._step++,this._render()}),t.createEl("button",{cls:"paperforge-step-btn",text:i("wizard_skip_ocr_back")}).addEventListener("click",()=>{this._showSkipConfirm=!1,this._render()})}_modalField(e,t,r,n){let a=e.createEl("div",{cls:"paperforge-modal-field"});a.createEl("label",{cls:"paperforge-modal-label",text:t});let s=a.createEl("input",{cls:"paperforge-modal-input",attr:{type:"text"}});s.value=r,s.disabled=!!n}_modalInput(e,t,r,n,a){let s=e.createEl("div",{cls:"paperforge-modal-field"});s.createEl("label",{cls:"paperforge-modal-label",text:t});let l=s.createEl("input",{cls:"paperforge-modal-input",attr:{type:"text",placeholder:a||""}});l.value=n;let o=this.plugin.settings;l.addEventListener("input",()=>{o[r]=l.value,this._pendingSave&&clearTimeout(this._pendingSave),this._pendingSave=setTimeout(()=>{this.plugin.saveSettings(),this._pendingSave=null},500)})}_modalSecret(e,t,r,n,a){let s=e.createEl("div",{cls:"paperforge-modal-field"});s.createEl("label",{cls:"paperforge-modal-label",text:t});let l=s.createEl("input",{cls:"paperforge-modal-input",attr:{type:"password",placeholder:a||""}});l.value=n;let o=this.plugin.settings;l.addEventListener("input",()=>{o[r]=l.value,this._pendingSave&&clearTimeout(this._pendingSave),this._pendingSave=setTimeout(()=>{this.plugin.saveSettings(),this._pendingSave=null},500)})}_stepInstall(e){e.createEl("h2",{text:i("wizard_step4")}),this._installLog=e.createEl("div",{cls:"paperforge-install-log"});let t=e.createEl("button",{cls:"paperforge-step-btn mod-cta",text:i("install_btn")});t.addEventListener("click",()=>this._runInstall(t))}async _runInstall(e){var s,l,o,c,p,h;e.disabled=!0,e.textContent=i("install_btn_running"),this._installLog.setText(i("install_validating")+`
-`),this._log(i("install_validating"));let t=this.plugin.settings,r=this._validate();if(r.length>0){this._log(i("validate_fail")+":"),r.forEach(d=>this._log(" \u2717 "+d)),e.disabled=!1,e.textContent=i("install_btn_retry");return}let n=(d,m={})=>new Promise((b,x)=>{let{path:_,extraArgs:k=[]}=N(t.vault_path.trim(),this.plugin.settings,void 0,void 0),D=(0,Me.spawn)(_,[...k,...d],{cwd:t.vault_path.trim(),env:be(),timeout:12e4,...m}),S="",f="";D.stdout.on("data",y=>{let w=y.toString("utf-8");S+=w,m.logStdout&&this._processSetupOutput(w)}),D.stderr.on("data",y=>{let w=y.toString("utf-8");f+=w,this._log("[stderr] "+w.trim())}),D.on("close",y=>{y===0?b({stdout:S,stderr:f}):x(new Error(f.trim()||S.trim()||`exit code ${y}`))}),D.on("error",y=>x(y))}),a=["-m","paperforge","--vault",t.vault_path.trim(),"setup","--headless","--system-dir",t.system_dir.trim(),"--resources-dir",t.resources_dir.trim(),"--literature-dir",t.literature_dir.trim(),"--base-dir",t.base_dir.trim(),"--agent",t.agent_platform||"opencode"];t.zotero_data_dir&&t.zotero_data_dir.trim()&&a.push("--zotero-data",t.zotero_data_dir.trim()),t.paddleocr_api_key&&t.paddleocr_api_key.trim()&&a.push("--paddleocr-key",t.paddleocr_api_key.trim());try{let d=!0;try{await n(["-c","import paperforge"])}catch(m){d=!1}if(!d){this._log(i("install_bootstrapping"));let m=this.plugin.manifest.version;this._log(`[install] Trying PyPI: pip install paperforge==${m}`);let b=["-m","pip","install","--upgrade"];process.platform!=="win32"&&b.push("--user"),b.push(`paperforge==${m}`);try{await n(b,{logStdout:!0})}catch(x){this._log(`[install] PyPI failed, falling back to git: git+https://...@v${m}`),console.warn("[PaperForge] PyPI install failed, falling back to git:",(s=x.message)==null?void 0:s.slice(0,200));let _=["-m","pip","install","--upgrade"];process.platform!=="win32"&&_.push("--user"),_.push(`git+https://github.com/LLLin000/PaperForge.git@v${m}`),await n(_,{logStdout:!0})}}await n(a,{logStdout:!0,env:be()}),this._log(i("install_complete")),t.setup_complete=!0,await this.plugin.saveSettings(),setTimeout(()=>{this._step=5,this._render()},800)}catch(d){console.error("PaperForge setup failed:",d.message);let m=this._formatSetupError(d.message);this._log(i("install_failed")+m);let b=(l=this._installLog.parentElement)==null?void 0:l.createEl("button",{cls:"paperforge-copy-diag-btn",text:i("error_copy_diagnostic")||"Copy diagnostic"});if(b){let x=d.message,_=((c=(o=this.plugin)==null?void 0:o.settings)==null?void 0:c.python_path)||"auto",k=((h=(p=this.plugin)==null?void 0:p.manifest)==null?void 0:h.version)||"?",D=process.platform+" "+process.arch,S,f;try{S=Qe()||"(not found)"}catch(R){S="(error)"}try{f=N(t.vault_path.trim(),this.plugin.settings,void 0,void 0)}catch(R){f=null}let y=(process.env.PATH||"").length,w=(process.env.PATH||"").toLowerCase().includes("git"),T=["[PaperForge Diagnostic]","Category: "+m,"Plugin version: "+k,"Python: "+_,"Resolved Python: "+((f==null?void 0:f.path)||"?"),"OS: "+D,"Vault path: "+(t.vault_path||"?"),"--- Git ---","Git dir (resolved): "+S,"PATH length: "+y+" chars","PATH contains git: "+w,"--- Raw error ---",x.slice(0,2e3)].join(`
+`),this._log(i("install_validating"));let t=this.plugin.settings,r=this._validate();if(r.length>0){this._log(i("validate_fail")+":"),r.forEach(d=>this._log(" \u2717 "+d)),e.disabled=!1,e.textContent=i("install_btn_retry");return}let n=(d,m={})=>new Promise((b,x)=>{let{path:_,extraArgs:w=[]}=z(t.vault_path.trim(),this.plugin.settings,void 0,void 0),D=(0,Me.spawn)(_,[...w,...d],{cwd:t.vault_path.trim(),env:be(),timeout:12e4,...m}),S="",f="";D.stdout.on("data",y=>{let C=y.toString("utf-8");S+=C,m.logStdout&&this._processSetupOutput(C)}),D.stderr.on("data",y=>{let C=y.toString("utf-8");f+=C,this._log("[stderr] "+C.trim())}),D.on("close",y=>{y===0?b({stdout:S,stderr:f}):x(new Error(f.trim()||S.trim()||`exit code ${y}`))}),D.on("error",y=>x(y))}),a=["-m","paperforge","--vault",t.vault_path.trim(),"setup","--headless","--system-dir",t.system_dir.trim(),"--resources-dir",t.resources_dir.trim(),"--literature-dir",t.literature_dir.trim(),"--base-dir",t.base_dir.trim(),"--agent",t.agent_platform||"opencode"];t.zotero_data_dir&&t.zotero_data_dir.trim()&&a.push("--zotero-data",t.zotero_data_dir.trim()),t.paddleocr_api_key&&t.paddleocr_api_key.trim()&&a.push("--paddleocr-key",t.paddleocr_api_key.trim());try{let d=!0;try{await n(["-c","import paperforge"])}catch(m){d=!1}if(!d){this._log(i("install_bootstrapping"));let m=this.plugin.manifest.version;this._log(`[install] Trying PyPI: pip install paperforge==${m}`);let b=["-m","pip","install","--upgrade"];process.platform!=="win32"&&b.push("--user"),b.push(`paperforge==${m}`);try{await n(b,{logStdout:!0})}catch(x){this._log(`[install] PyPI failed, falling back to git: git+https://...@v${m}`),console.warn("[PaperForge] PyPI install failed, falling back to git:",(s=x.message)==null?void 0:s.slice(0,200));let _=["-m","pip","install","--upgrade"];process.platform!=="win32"&&_.push("--user"),_.push(`git+https://github.com/LLLin000/PaperForge.git@v${m}`),await n(_,{logStdout:!0})}}await n(a,{logStdout:!0,env:be()}),this._log(i("install_complete")),t.setup_complete=!0,await this.plugin.saveSettings(),setTimeout(()=>{this._step=5,this._render()},800)}catch(d){console.error("PaperForge setup failed:",d.message);let m=this._formatSetupError(d.message);this._log(i("install_failed")+m);let b=(l=this._installLog.parentElement)==null?void 0:l.createEl("button",{cls:"paperforge-copy-diag-btn",text:i("error_copy_diagnostic")||"Copy diagnostic"});if(b){let x=d.message,_=((c=(o=this.plugin)==null?void 0:o.settings)==null?void 0:c.python_path)||"auto",w=((h=(p=this.plugin)==null?void 0:p.manifest)==null?void 0:h.version)||"?",D=process.platform+" "+process.arch,S,f;try{S=Qe()||"(not found)"}catch(R){S="(error)"}try{f=z(t.vault_path.trim(),this.plugin.settings,void 0,void 0)}catch(R){f=null}let y=(process.env.PATH||"").length,C=(process.env.PATH||"").toLowerCase().includes("git"),T=["[PaperForge Diagnostic]","Category: "+m,"Plugin version: "+w,"Python: "+_,"Resolved Python: "+((f==null?void 0:f.path)||"?"),"OS: "+D,"Vault path: "+(t.vault_path||"?"),"--- Git ---","Git dir (resolved): "+S,"PATH length: "+y+" chars","PATH contains git: "+C,"--- Raw error ---",x.slice(0,2e3)].join(`
`);b.addEventListener("click",()=>{navigator.clipboard.writeText(T).then(()=>{b.setText(i("error_copied")||"Copied!"),setTimeout(()=>{b.setText(i("error_copy_diagnostic")||"Copy diagnostic")},3e3)}).catch(()=>{new ee.Notice("[!!] Clipboard write failed",6e3)})})}e.disabled=!1,e.textContent=i("install_btn_retry")}}_log(e){this._installLog&&this._installLog.setText(this._installLog.textContent+e+`
`)}_validate(){let e=[],t=this.plugin.settings;return(!t.vault_path||!t.vault_path.trim())&&e.push(i("validate_vault")),(!t.resources_dir||!t.resources_dir.trim())&&e.push(i("validate_resources")),(!t.literature_dir||!t.literature_dir.trim())&&e.push(i("validate_notes")),(!t.base_dir||!t.base_dir.trim())&&e.push(i("validate_base")),(!t.paddleocr_api_key||!t.paddleocr_api_key.trim())&&this._log(" ! "+i("validate_key")+" "+i("optional_later")),(!t.zotero_data_dir||!t.zotero_data_dir.trim())&&this._log(" ! "+i("validate_zotero")+" "+i("optional_later")),e}_processSetupOutput(e){let t=e.split(`
`).filter(Boolean);for(let r of t)if(r.includes("[*]")||r.includes("[OK]")||r.includes("[FAIL]")){let n=r.replace(/^\[\*\].*\d+:?\s*/,"").replace(/^\[OK\]\s*/,"").replace(/^\[FAIL\]\s*/,"");this._log(" "+n)}}_formatSetupError(e){if(process.platform==="darwin"&&/No module named ['"]?paperforge/i.test(e))return"PaperForge not installed \u2014 install Python from Homebrew or python.org (Apple CLT /Library/Developer/CommandLineTools python often fails); then: python3 -m pip install --user git+https://github.com/LLLin000/PaperForge.git";let t=[{match:/pip.*not found|No module named.*pip|command not found.*pip/i,msg:"pip not found"},{match:/command not found|No such file|not recognized/i,msg:"Python not found"},{match:/resolve host|getaddrinfo.*nodename|connect ETIMEDOUT|connect ECONNREFUSED|fetch failed|Network error|ENOTFOUND|ECONNREFUSED|ECONNRESET/i,msg:"Network error"},{match:/certificate verify failed|SSL.*certificate|self.signed.cert|CERTIFICATE_VERIFY_FAILED/i,msg:"SSL certificate error"},{match:/No space left on device|disk full|ENOSPC/i,msg:"Disk full"},{match:/paperforge.*not found|cannot import|ModuleNotFoundError|No module named/i,msg:"PaperForge not installed"},{match:/permission denied|EACCES|EPERM/i,msg:"Permission denied"},{match:/ENOENT/i,msg:"Path not found"},{match:/timeout|timed out/i,msg:"Timeout"}];for(let n of t)if(n.match.test(e))return n.msg;return e.split(`
-`).filter(Boolean).slice(0,3).join(" | ").slice(0,200)||"Unknown error"}_stepComplete(e){e.createEl("h2",{text:i("complete_title")});let t=e.createEl("div",{cls:"paperforge-summary"});t.createEl("div",{cls:"paperforge-summary-title",text:i("complete_summary")});let r=this.plugin.settings,n=this.app.vault.adapter.basePath,a=[{label:i("dir_vault"),val:n},{label:i("dir_resources"),val:`${n}/${r.resources_dir}`},{label:i("dir_notes"),val:`${n}/${r.resources_dir}/${r.literature_dir}`},{label:i("dir_base"),val:`${n}/${r.base_dir}`},{label:i("dir_system"),val:`${n}/${r.system_dir}`},{label:"API Key",val:r.paddleocr_api_key?i("api_key_set"):i("api_key_missing")},{label:i("field_zotero_data"),val:r.zotero_data_dir||i("not_set")}];for(let p of a){let h=t.createEl("div",{cls:"paperforge-summary-row"});h.createEl("span",{cls:"paperforge-summary-label",text:p.label}),h.createEl("span",{cls:"paperforge-summary-value",text:p.val})}let s=t.createEl("div",{cls:"paperforge-summary-row"});s.createEl("span",{cls:"paperforge-summary-label",text:"PaperForge"});let l=s.createEl("span",{cls:"paperforge-summary-value",text:"\u2014"});{let p=n,{path:h,extraArgs:d=[]}=N(p,this.plugin.settings,void 0,void 0);(0,Me.execFile)(h,[...d,"-c","import paperforge; print(paperforge.__version__)"],{cwd:p,timeout:1e4},(m,b)=>{!m&&b&&(l.textContent="v"+b.trim())})}for(let p of a){let h=t.createEl("div",{cls:"paperforge-summary-row"});h.createEl("span",{cls:"paperforge-summary-label",text:p.label}),h.createEl("span",{cls:"paperforge-summary-value",text:p.val})}e.createEl("h3",{text:i("complete_next")});let o=e.createEl("div",{cls:"paperforge-nextsteps"}),c=[[i("complete_step4"),i("complete_step4_desc")],["",`${i("complete_export_path")} ${n}/${r.system_dir}/PaperForge/exports/`],[i("complete_step1"),i("complete_step1_desc")],[i("complete_step2"),i("complete_step2_desc")],[i("complete_step3"),i("complete_step3_desc")]];for(let[p,h]of c){let d=o.createEl("div",{cls:"paperforge-nextstep-item"});p&&d.createEl("strong",{text:p}),d.createEl("span",{text:h})}}};function St(g){var u;return g.recommended_action==="rebuild"?{category:"rebuild",label:"Rebuild Recommended",primaryAction:"rebuild",reason:"Derived OCR results can be regenerated from existing OCR data."}:g.status==="failed"?{category:"failed",label:"OCR Failed",primaryAction:"redo",reason:g.error_summary||"OCR did not finish successfully."}:(g.degraded_reasons||[]).length>0||g.status==="done_degraded"?{category:"limited",label:"Result Limited",primaryAction:null,reason:((u=g.degraded_reasons)==null?void 0:u[0])||"This paper has weaker confidence signals, but no clear maintenance action is recommended."}:{category:"ok",label:"No Action Needed",primaryAction:null,reason:"OCR results look usable and no maintenance action is recommended."}}function Pt(g){let u={ok:0,rebuild:0,failed:0,limited:0};for(let t of g)u[t.category]+=1;let e=u.failed>0||u.rebuild>0?"warn":"ok";return{counts:u,tone:e}}var Ve=class extends F.PluginSettingTab{constructor(e,t){super(e,t);this._saveTimeout=null;this._pfConfig=null;this._lastSyncTime=null;this._memoryStatusText=null;this._vectorDepsOk=null;this._embedStatusText=null;this._skillsCollapsed={user:!0};this._featurePanelsCollapsed={};this._advCollapsed=!0;this._refreshPending=!1;this._pythonInterpDescEl=null;this._customPathDescEl=null;this._checkEl=null;this.activeTab="setup";this.plugin=t}_refreshPfConfig(){this._pfConfig=this.plugin.readPaperforgeJson()}display(){let{containerEl:e}=this;if(e.empty(),this._refreshPfConfig(),!document.getElementById("paperforge-tab-styles")){let a=document.createElement("style");a.id="paperforge-tab-styles",a.textContent=`
+`).filter(Boolean).slice(0,3).join(" | ").slice(0,200)||"Unknown error"}_stepComplete(e){e.createEl("h2",{text:i("complete_title")});let t=e.createEl("div",{cls:"paperforge-summary"});t.createEl("div",{cls:"paperforge-summary-title",text:i("complete_summary")});let r=this.plugin.settings,n=this.app.vault.adapter.basePath,a=[{label:i("dir_vault"),val:n},{label:i("dir_resources"),val:`${n}/${r.resources_dir}`},{label:i("dir_notes"),val:`${n}/${r.resources_dir}/${r.literature_dir}`},{label:i("dir_base"),val:`${n}/${r.base_dir}`},{label:i("dir_system"),val:`${n}/${r.system_dir}`},{label:"API Key",val:r.paddleocr_api_key?i("api_key_set"):i("api_key_missing")},{label:i("field_zotero_data"),val:r.zotero_data_dir||i("not_set")}];for(let p of a){let h=t.createEl("div",{cls:"paperforge-summary-row"});h.createEl("span",{cls:"paperforge-summary-label",text:p.label}),h.createEl("span",{cls:"paperforge-summary-value",text:p.val})}let s=t.createEl("div",{cls:"paperforge-summary-row"});s.createEl("span",{cls:"paperforge-summary-label",text:"PaperForge"});let l=s.createEl("span",{cls:"paperforge-summary-value",text:"\u2014"});{let p=n,{path:h,extraArgs:d=[]}=z(p,this.plugin.settings,void 0,void 0);(0,Me.execFile)(h,[...d,"-c","import paperforge; print(paperforge.__version__)"],{cwd:p,timeout:1e4},(m,b)=>{!m&&b&&(l.textContent="v"+b.trim())})}for(let p of a){let h=t.createEl("div",{cls:"paperforge-summary-row"});h.createEl("span",{cls:"paperforge-summary-label",text:p.label}),h.createEl("span",{cls:"paperforge-summary-value",text:p.val})}e.createEl("h3",{text:i("complete_next")});let o=e.createEl("div",{cls:"paperforge-nextsteps"}),c=[[i("complete_step4"),i("complete_step4_desc")],["",`${i("complete_export_path")} ${n}/${r.system_dir}/PaperForge/exports/`],[i("complete_step1"),i("complete_step1_desc")],[i("complete_step2"),i("complete_step2_desc")],[i("complete_step3"),i("complete_step3_desc")]];for(let[p,h]of c){let d=o.createEl("div",{cls:"paperforge-nextstep-item"});p&&d.createEl("strong",{text:p}),d.createEl("span",{text:h})}}};function St(g){var u;return g.recommended_action==="rebuild"?{category:"rebuild",label:"Rebuild Recommended",primaryAction:"rebuild",reason:"Derived OCR results can be regenerated from existing OCR data."}:g.status==="failed"?{category:"failed",label:"OCR Failed",primaryAction:"redo",reason:g.error_summary||"OCR did not finish successfully."}:(g.degraded_reasons||[]).length>0||g.status==="done_degraded"?{category:"limited",label:"Result Limited",primaryAction:null,reason:((u=g.degraded_reasons)==null?void 0:u[0])||"This paper has weaker confidence signals, but no clear maintenance action is recommended."}:{category:"ok",label:"No Action Needed",primaryAction:null,reason:"OCR results look usable and no maintenance action is recommended."}}function Pt(g){let u={ok:0,rebuild:0,failed:0,limited:0};for(let t of g)u[t.category]+=1;let e=u.failed>0||u.rebuild>0?"warn":"ok";return{counts:u,tone:e}}var Ve=class extends F.PluginSettingTab{constructor(e,t){super(e,t);this._saveTimeout=null;this._pfConfig=null;this._lastSyncTime=null;this._memoryStatusText=null;this._vectorDepsOk=null;this._embedStatusText=null;this._skillsCollapsed={user:!0};this._featurePanelsCollapsed={};this._advCollapsed=!0;this._refreshPending=!1;this._pythonInterpDescEl=null;this._customPathDescEl=null;this._checkEl=null;this.activeTab="setup";this.plugin=t}_refreshPfConfig(){this._pfConfig=this.plugin.readPaperforgeJson()}display(){let{containerEl:e}=this;if(e.empty(),this._refreshPfConfig(),!document.getElementById("paperforge-tab-styles")){let a=document.createElement("style");a.id="paperforge-tab-styles",a.textContent=`
.paperforge-settings-tabs { display: flex; gap: 4px; margin-bottom: 16px; border-bottom: 1px solid var(--background-modifier-border); }
.paperforge-settings-tab { padding: 6px 16px; border: none; background: none; cursor: pointer; border-bottom: 2px solid transparent; font-size: 14px; color: var(--text-muted); }
.paperforge-settings-tab--active { color: var(--text-accent); border-bottom-color: var(--text-accent); }
@@ -29,21 +29,21 @@
.paperforge-manual-links a { color: var(--text-accent); }
.paperforge-modal-subtitle { color: var(--text-muted); font-size: 13px; margin-bottom: 12px; }
.paperforge-modal-item { font-size: 13px; margin-left: 8px; color: var(--text-muted); }
- `,document.head.appendChild(a)}let t=e.createDiv({cls:"paperforge-settings-tabs"}),r=[{id:"setup",label:i("tab_setup")||"\u5B89\u88C5"},{id:"features",label:i("tab_features")||"\u529F\u80FD"},{id:"maintenance",label:i("tab_maintenance")||"\u7EF4\u62A4"},{id:"release-notes",label:"\u66F4\u65B0\u4E0E\u624B\u518C"}],n={};r.forEach(a=>{t.createEl("button",{cls:"paperforge-settings-tab"+(a.id===this.activeTab?" paperforge-settings-tab--active":""),text:a.label}).addEventListener("click",()=>{this.activeTab=a.id,this.display()})}),r.forEach(a=>{n[a.id]=e.createDiv({cls:"paperforge-tab-content"+(a.id===this.activeTab?" paperforge-tab-content--active":"")})}),this.activeTab==="setup"?this._renderSetupTab(n.setup):this.activeTab==="features"?this._renderFeaturesTab(n.features):this.activeTab==="maintenance"?this._renderMaintenanceTab(n.maintenance):this._renderReleaseNotesTab(n["release-notes"])}_renderSetupTab(e){let t=this.app.vault.adapter.basePath;this.plugin.settings.vault_path||(this.plugin.settings.vault_path=t,this._debouncedSave()),this.plugin.settings.setup_complete&&(L.existsSync(Z.join(t,"paperforge.json"))||(this.plugin.settings.setup_complete=!1,this._debouncedSave())),e.createEl("h2",{text:i("header_title")||"PaperForge"}),e.createEl("p",{text:i("desc"),cls:"paperforge-settings-desc"});let n=e.createEl("div",{cls:"paperforge-setup-bar"}).createEl("span",{cls:"paperforge-setup-label"});this.plugin.settings.setup_complete?(n.setText(i("setup_done")),n.addClass("paperforge-setup-done")):(n.setText(i("setup_pending")),n.addClass("paperforge-setup-pending"));let a=this.app.vault.adapter.basePath,s=N(a,this.plugin.settings,void 0,void 0),l=s.path,o=this.plugin.settings._python_path_stale?"stale":s.source,c=new F.Setting(e).setName(i("field_python_interp")).setDesc(this._getPythonDesc(l,o));this._pythonInterpDescEl=c.descEl;let p=new F.Setting(e).setName(i("field_python_custom")).setDesc("");this._customPathDescEl=p.descEl,p.addText(S=>{S.setPlaceholder("e.g. C:\\Python310\\python.exe").setValue(this.plugin.settings.python_path||"").onChange(f=>{if(this.plugin.settings.python_path=f,this.plugin.saveSettings(),f&&f.trim()){let T=L.existsSync(f.trim());this.plugin.settings._python_path_stale=!T}else this.plugin.settings._python_path_stale=!1;let y=N(this.app.vault.adapter.basePath,this.plugin.settings,void 0,void 0),w=this.plugin.settings._python_path_stale?"stale":y.source;this._pythonInterpDescEl&&(this._pythonInterpDescEl.textContent=this._getPythonDesc(y.path,w))})}),p.addButton(S=>{S.setButtonText(i("btn_validate")).onClick(()=>this._validatePythonOverride())}),e.createEl("h3",{text:i("runtime_health")}),e.createEl("p",{text:i("runtime_health_desc"),cls:"paperforge-settings-desc"});let h=new F.Setting(e).setName("PaperForge").setDesc(i("runtime_health_checking")),d=h.descEl.createEl("span",{cls:"paperforge-runtime-badge"}),m=null;h.addButton(S=>{m=S,S.setButtonText(i("runtime_health_sync")).setDisabled(!0).onClick(()=>this._syncRuntime(S))});{let S=this.app.vault.adapter.basePath,{path:f,extraArgs:y=[]}=N(S,this.plugin.settings,void 0,void 0),w=this.plugin.manifest.version||"?";(0,$.execFile)(f,[...y,"-c","import paperforge; print(paperforge.__version__)"],{cwd:S,timeout:1e4},(T,R)=>{let B=this.plugin.settings.setup_complete,A=!T&&R?R.trim():null,V=A?`${i("runtime_health_plugin_ver").replace("{0}",w)} \u2192 ${i("runtime_health_package_ver").replace("{0}",A)}`:B?`Plugin v${w} \u2192 Python package not installed. Click "Sync Runtime" to install.`:`Plugin v${w} \u2192 Not configured. Please open the setup wizard first.`;h.setDesc(V),A===w?(d.setText(i("runtime_health_match")),d.className="paperforge-runtime-badge match",m&&m.setDisabled(!0)):A?(d.setText(i("runtime_health_mismatch")),d.className="paperforge-runtime-badge mismatch",m&&m.setDisabled(!1)):(d.setText(B?"Not installed":"Setup needed"),d.className="paperforge-runtime-badge missing",m&&m.setDisabled(!1))})}e.createEl("h3",{text:i("section_prep")}),e.createEl("p",{text:i("section_prep_desc"),cls:"paperforge-settings-desc"});let b=e.createEl("div",{cls:"paperforge-guide"}),x=[["prep_python","prep_python_desc"],["prep_zotero","prep_zotero_desc"],["prep_bbt","prep_bbt_desc"],["prep_key","prep_key_desc"]];for(let[S,f]of x){let y=b.createEl("div",{cls:"paperforge-guide-item"});y.createEl("strong",{text:i(S)}),y.createEl("span",{text:" \u2014 "+i(f)})}this._checkEl=e.createEl("div",{cls:"paperforge-message"});let _=!this.plugin.settings.setup_complete;new F.Setting(e).setName(i(_?"btn_install":"btn_reconfig")).setDesc(i(_?"btn_install_desc":"btn_reconfig_desc")).addButton(S=>{S.setButtonText(i(_?"btn_install":"btn_reconfig")).setCta().onClick(()=>{_?this._preCheck(()=>{new Le(this.app,this.plugin).open()}):new Le(this.app,this.plugin).open()})}),e.createEl("h3",{text:i("section_guide")});let k=e.createEl("div",{cls:"paperforge-guide"}),D=[["guide_open","guide_open_desc"],["guide_sync","guide_sync_desc"],["guide_ocr","guide_ocr_desc"]];for(let[S,f]of D){let y=k.createEl("div",{cls:"paperforge-guide-item"});y.createEl("strong",{text:i(S)}),y.createEl("span",{text:" \u2014 "+i(f)})}if(this.plugin.settings.setup_complete){e.createEl("h3",{text:i("section_config")});let S=e.createEl("div",{cls:"paperforge-summary"}),f=this.plugin.settings,y=this._pfConfig,w=[{label:i("dir_vault"),val:t},{label:i("dir_resources"),val:`${t}/${y==null?void 0:y.resources_dir}`},{label:" "+i("dir_notes"),val:`${t}/${y==null?void 0:y.resources_dir}/${y==null?void 0:y.literature_dir}`},{label:i("dir_base"),val:`${t}/${y==null?void 0:y.base_dir}`},{label:i("dir_system"),val:`${t}/${y==null?void 0:y.system_dir}`},{label:"API Key",val:f.paddleocr_api_key?i("api_key_set"):i("api_key_missing")},{label:i("field_zotero_data"),val:f.zotero_data_dir||i("not_set")}];for(let T of w){let R=S.createEl("div",{cls:"paperforge-summary-row"});R.createEl("span",{cls:"paperforge-summary-label",text:T.label}),R.createEl("span",{cls:"paperforge-summary-value",text:T.val})}}}_execMemoryStatus(e,t,r){(0,$.exec)(`"${e}" -m paperforge --vault "${t}" memory status --json`,{encoding:"utf-8",timeout:15e3},(n,a)=>{if(n){r("Status unavailable");return}try{let s=JSON.parse(a);if(s.ok){let l=s.data,o=l.fresh?"fresh":"stale";r(`Papers: ${l.paper_count_db} | ${o}${l.needs_rebuild?" - needs rebuild":""}`)}else r("DB not found. Run paperforge memory build.")}catch(s){r("Could not parse status.")}})}_execEmbedStatus(e,t,r){(0,$.exec)(`"${e}" -m paperforge --vault "${t}" embed status --json`,{encoding:"utf-8",timeout:15e3},(n,a)=>{if(n){r("Status unavailable");return}try{let s=JSON.parse(a);s.ok?r(`Chunks: ${s.data.chunk_count} | ${s.data.model} | ${s.data.mode}`):r("Could not parse status.")}catch(s){r("Could not parse status.")}})}_callPython(e,t){let r=this.app.vault.adapter.basePath,n=de(r,this.plugin.settings),a=[...n.extraArgs,"-m","paperforge","--vault",r,...e];if(t&&t.stream){let s=(0,$.spawn)(n.path,a,{cwd:r,env:t.env||process.env,windowsHide:!0});return t.onData&&s.stdout.on("data",t.onData),t.onStderr&&s.stderr.on("data",t.onStderr),t.onError&&s.on("error",t.onError),s.on("close",t.onClose),s}return(0,$.execFile)(n.path,a,{cwd:r,timeout:t&&t.timeout||6e4},(s,l,o)=>{t&&t.onClose&&t.onClose(s?1:0,l,o)}),null}_renderMemoryStatusText(e,t,r){if(e.innerHTML="",e.createEl("span",{text:t,cls:"paperforge-memory-text"}).style.cssText="flex:1;",r==="syncing"){let s=e.createEl("span",{text:"Syncing...",cls:"paperforge-sync-status"});s.style.cssText="opacity:0.7; margin-right:8px;"}else if(r){let s=e.createEl("span",{text:r,cls:"paperforge-sync-status"});s.style.cssText="opacity:0.7; margin-right:8px;"}let n=e.createEl("button",{cls:"paperforge-rebuild-btn",text:i("feat_memory_rebuild_btn")});n.style.cssText="margin-left:auto; border:1px solid var(--background-modifier-border); background:var(--background-secondary); cursor:pointer; font-size:11px; padding:2px 6px; border-radius:3px; margin-right:4px;",n.title="Rebuild memory database",n.onclick=()=>{let s=this.app.vault.adapter.basePath,l=de(s,this.plugin.settings);if(!l.path){new F.Notice(i("feat_no_python"));return}console.log("[PaperForge] Rebuilding memory:",l.path),n.setText(i("feat_memory_rebuilding")),n.setAttr("disabled",""),this._callPython(["memory","build"],{timeout:6e4,onClose:(o,c,p)=>{console.log("[PaperForge] memory build exit:",o?"FAIL:"+o:"OK",(c||"").slice(0,200),(p||"").slice(0,200)),n.setText(i("feat_memory_rebuild_btn")),n.removeAttribute("disabled"),o===0?new F.Notice(i("feat_memory_rebuild_done")):new F.Notice(i("feat_memory_rebuild_failed")+(p?" "+p.slice(0,80):"")),this._memoryStatusText=je(s),this._refreshSnapshots(s)}})};let a=e.createEl("button",{cls:"paperforge-refresh-btn",text:"\u21BB"});a.style.cssText="border:none; background:none; cursor:pointer; font-size:16px; padding:0 4px;",a.title="Sync now",a.onclick=()=>{this._memoryStatusText=null,this._runManualSync()}}_getBuildCommand(e){let t=this.app.vault.adapter.basePath,r=N(t,e,void 0,void 0);return r.path?`"${r.path}" -m paperforge --vault "${t}" sync`:null}_runManualSync(){let e=this.app.vault.adapter.basePath;if(!de(e,this.plugin.settings).path)return;let r=document.querySelector(".paperforge-memory-status");r&&this._renderMemoryStatusText(r,"Checking...","syncing"),this.plugin._autoSyncRunning=!0,this._callPython(["sync"],{timeout:12e4,onClose:n=>{this.plugin._autoSyncRunning=!1,this._memoryStatusText=null,n===0&&(this._lastSyncTime=new Date().toLocaleTimeString(),this.plugin._lastSyncTime=this._lastSyncTime),this.display(),this._refreshSnapshots(e),He(this.app,this.plugin,e)}})}_refreshSnapshots(e){let t=de(e,this.plugin.settings),r=[...t.extraArgs,"-m","paperforge","--vault",e,"runtime-health","--json"];this._refreshPending=!0,(0,$.execFile)(t.path,r,{cwd:e,timeout:3e4,windowsHide:!0},(n,a,s)=>{this._refreshPending=!1,this._memoryStatusText=je(e),this._embedStatusText=we(e),this.display()})}_renderFeaturesTab(e){e.createEl("h3",{text:"Skills"});let t=e.createEl("div",{cls:"paperforge-desc-box"});t.style.cssText="padding:8px 12px; margin:0 0 12px; background:var(--background-secondary); border-radius:4px; font-size:12px; color:var(--text-muted); line-height:1.5;",t.setText(i("feat_skills_desc")),t.createEl("br"),t.createEl("span",{text:i("feat_skills_system"),cls:""}).style.opacity="0.7";let r={opencode:"OpenCode",claude:"Claude Code",codex:"Codex",cursor:"Cursor",windsurf:"Windsurf",github_copilot:"GitHub Copilot",gemini:"Gemini CLI"},n={opencode:".opencode/skills",claude:".claude/skills",codex:".codex/skills",cursor:".cursor/skills",windsurf:".windsurf/skills",github_copilot:".github/skills",gemini:".gemini/skills"},a=this.app.vault.adapter.basePath,s=this.plugin.settings.selected_skill_platform||"opencode";new F.Setting(e).setName(i("feat_agent_platform")).setDesc(i("feat_agent_platform_desc")).addDropdown(f=>{Object.entries(r).forEach(([y,w])=>f.addOption(y,w)),f.setValue(s).onChange(y=>{this.plugin.settings.selected_skill_platform=y,this.plugin.saveSettings(),this.display()})}).addExtraButton(f=>{f.setIcon("folder").setTooltip("Open skills folder").onClick(()=>{let y=n[s]||".opencode/skills",w=Z.join(a,y);L.existsSync(w)?(0,$.exec)(`start "" "${w}"`):new F.Notice(`Skills folder not found: ${y}`)})});let l=Z.join(a,n[s]),o=[],c=[];L.existsSync(l)&&L.readdirSync(l,{withFileTypes:!0}).forEach(f=>{if(!f.isDirectory())return;let y=Z.join(l,f.name,"SKILL.md");if(!L.existsSync(y))return;let w=L.readFileSync(y,"utf-8"),T=w.match(/^name:\s*(.+)$/m),R=w.split(`
-`),B=R.findIndex(W=>/^description:/.test(W)),A="";if(B>=0){let W=R[B].match(/^description:\s*(.+)$/);if(W&&W[1]&&W[1]!==">"&&W[1]!=="|-"&&W[1]!=="|")A=W[1].trim();else{for(let U=B+1;U{if(y.length===0)return;let T=p.createEl("div",{cls:"paperforge-skills-group"}),R=T.createEl("div",{cls:"paperforge-skills-collapse-header"}),B=T.createEl("div",{cls:"paperforge-skills-collapse-content"}),A=R.createEl("span",{text:"\u25BC",cls:"paperforge-skills-arrow"});A.style.cssText="display:inline-block; font-size:10px; margin-right:6px; transition:transform 0.2s; transform:rotate(0deg);",R.createEl("h4",{text:`${f} (${y.length})`,cls:"paperforge-skills-subheader"}),y.forEach(O=>{let J=O.name+(O.version?" v"+O.version:""),W=w?" [system]":" [user]",U=O.desc||"",te=new F.Setting(B).setName(J+W).setDesc(U);te.settingEl.style.opacity=O.disabled?"0.4":"1",te.addToggle(ne=>{ne.setValue(!O.disabled).onChange(ge=>{let re=!ge,fe=O.content.match(/^disable-model-invocation:\s*(.+)$/m)?O.content.replace(/^disable-model-invocation:\s*.+$/m,`disable-model-invocation: ${re}`):O.content.replace(/^(---\r?\n)/,`$1disable-model-invocation: ${re}
-`);L.writeFileSync(O.path,fe,"utf-8"),O.disabled=re,O.content=fe,te.settingEl.style.opacity=O.disabled?"0.4":"1"})})});let V=w?"system":"user";(this._skillsCollapsed[V]||!1)&&(B.style.display="none",A.style.transform="rotate(-90deg)"),R.addEventListener("click",()=>{B.style.display!=="none"?(B.style.display="none",A.style.transform="rotate(-90deg)"):(B.style.display="",A.style.transform="rotate(0deg)"),this._skillsCollapsed[V]=B.style.display==="none"})};h("System Skills",o,!0),h("User Skills",c,!1),o.length===0&&c.length===0&&p.createEl("p",{text:`No skills found in ${n[s]}. Run setup to deploy skills.`,cls:"setting-item-description"}),this._advCollapsed===void 0&&(this._advCollapsed=!0);let d=e.createEl("div",{cls:"paperforge-collapsible-header"});d.style.cssText="cursor:pointer; display:flex; align-items:center; gap:8px; padding:8px 0; user-select:none;";let m=d.createEl("span",{text:"\u25B6",cls:"paperforge-collapsible-arrow"});m.style.cssText="display:inline-block; transition:transform 0.2s; font-size:10px; transform:"+(this._advCollapsed?"rotate(0deg)":"rotate(90deg)")+";";let b=d.createEl("span",{text:"Advanced"});b.style.cssText="font-size:16px; font-weight:700; line-height:1.4;";let x=d.createEl("span",{text:"Memory + Vector DB + Embedding"});x.style.cssText="font-size:12px; color:var(--text-muted); margin-left:10px;";let _=e.createEl("div",{cls:"paperforge-collapsible-content"});_.style.display=this._advCollapsed?"none":"",d.addEventListener("click",()=>{this._advCollapsed=!this._advCollapsed,_.style.display=this._advCollapsed?"none":"",m.style.transform=this._advCollapsed?"rotate(0deg)":"rotate(90deg)"}),_.createEl("h4",{text:"Memory Layer"});let k=_.createEl("div",{cls:"paperforge-desc-box"});k.style.cssText="padding:8px 12px; margin:0 0 12px; background:var(--background-secondary); border-radius:4px; font-size:12px; color:var(--text-muted); line-height:1.5;",k.setText(i("feat_memory_desc"));let D=_.createEl("div",{cls:"paperforge-memory-status"});D.style.cssText="display:flex; align-items:center; padding:8px 12px; margin:8px 0; background:var(--background-secondary); border-radius:4px;";let S=this.app.vault.adapter.basePath;this.plugin._lastSyncTime&&!this._lastSyncTime&&(this._lastSyncTime=this.plugin._lastSyncTime),this._memoryStatusText===null&&(this._memoryStatusText=je(S)),this._renderMemoryStatusText(D,this._memoryStatusText,this._lastSyncTime),this._renderVectorSection(_)}_renderVectorSection(e){var o;e.createEl("h4",{text:"Vector Database"}),this.plugin.settings.features||(this.plugin.settings.features={memory_layer:!0,vector_db:!1});let t=e.createEl("div",{cls:"paperforge-desc-box"});if(t.style.cssText="padding:8px 12px; margin:0 0 8px; background:var(--background-secondary); border-radius:4px; font-size:12px; color:var(--text-muted); line-height:1.5;",t.setText(i("feat_vector_desc")),new F.Setting(e).setName(i("feat_vector_enable")).setDesc(i("feat_vector_enable_desc")).addToggle(c=>{c.setValue(!!this.plugin.settings.features.vector_db).onChange(p=>{this.plugin.settings.features.vector_db=p,this.plugin.saveSettings(),this._vectorDepsOk=null,this._embedStatusText=null,this.display()})}),!this.plugin.settings.features.vector_db)return;let r=this.app.vault.adapter.basePath,n=e.createEl("div",{cls:"paperforge-skills-collapse-header"});n.style.cssText="display:flex; align-items:center; cursor:pointer; padding:6px 0 2px; margin:0;";let a=n.createEl("span",{text:"\u25BC"});a.style.cssText="display:inline-block; font-size:10px; margin-right:6px; transition:transform 0.2s;",n.createEl("span",{text:i("feat_vector_config_label"),cls:""}).style.cssText="font-size:12px; color:var(--text-muted);";let s=e.createEl("div",{cls:"paperforge-vector-config"}),l=c=>{s.style.display=c?"none":"",a.style.transform=c?"rotate(-90deg)":"rotate(0deg)"};if(l(st(this._featurePanelsCollapsed,"vectorConfig",!1)),n.addEventListener("click",()=>{let c=Et(this._featurePanelsCollapsed,"vectorConfig",!1);l(c)}),this._vectorDepsOk===!0){this._renderVectorReady(s,r);return}if(this._vectorDepsOk===!1){this._renderVectorNoDeps(s);return}if(this._vectorDepsOk===null){let c=Oe(r);this._vectorDepsOk=c&&(o=c.deps_installed)!=null?o:!1,this._vectorDepsOk&&(this._embedStatusText=we(r)),this.display()}}_renderApiConfig(e){new F.Setting(e).setName(i("feat_openai_key")).setDesc(i("feat_openai_key_desc")).addText(t=>{t.setPlaceholder("sk-...").setValue(this.plugin.settings.vector_db_api_key||"").onChange(r=>{this.plugin.settings.vector_db_api_key=r,this.plugin.saveSettings()})}),new F.Setting(e).setName(i("feat_api_base_url")).setDesc(i("feat_api_base_url_desc")).addText(t=>{t.setPlaceholder("https://api.openai.com/v1").setValue(this.plugin.settings.vector_db_api_base||"").onChange(r=>{this.plugin.settings.vector_db_api_base=r,this.plugin.saveSettings()})}),new F.Setting(e).setName(i("feat_api_model")).setDesc(i("feat_api_model_desc")).addText(t=>{t.setPlaceholder("text-embedding-3-small").setValue(this.plugin.settings.vector_db_api_model||"text-embedding-3-small").onChange(r=>{this.plugin.settings.vector_db_api_model=r,this.plugin.saveSettings()})})}_renderVectorNoDeps(e){let t=e.createEl("div");t.style.cssText="padding:8px 12px; margin:8px 0; background:var(--background-secondary); border-radius:4px;",t.setText(i("feat_deps_missing")),new F.Setting(e).setName(i("feat_install_deps")).setDesc(i("feat_install_deps_desc")).addButton(r=>{r.setButtonText(i("feat_install_btn")).setCta().onClick(async()=>{let n=this.app.vault.adapter.basePath,a=de(n,this.plugin.settings);if(!a.path){new F.Notice(i("feat_no_python"));return}r.setButtonText(i("feat_installing")),r.setDisabled(!0);let s="chromadb openai",l=new F.Notice(i("feat_installing_pkgs").replace("{pkgs}",s),0);try{let o=Object.assign({},process.env,{PYTHONIOENCODING:"utf-8",PYTHONUTF8:"1"}),c=s.split(" ");await new Promise((p,h)=>{(0,$.execFile)(a.path,[...a.extraArgs,"-m","pip","install",...c],{cwd:n,timeout:3e5,env:o,windowsHide:!0},d=>{d?h(d):p()})}),l.hide(),new F.Notice(i("feat_install_done")),this._vectorDepsOk=!0,this._embedStatusText=we(n),this.display()}catch(o){l.hide(),new F.Notice(i("feat_install_failed")+(o.stderr||o.message||o)),r.setButtonText(i("feat_retry_btn")),r.setDisabled(!1)}})})}_renderVectorReady(e,t){let r=e.createEl("div");r.style.cssText="padding:8px 12px; margin:8px 0; background:var(--background-secondary); border-radius:4px;",r.setText(we(t)),this._renderApiConfig(e);let n=e.createEl("div");n.style.cssText="padding:4px 0;";let a=n.createEl("div");a.style.cssText="display:flex; align-items:center; justify-content:space-between; margin-bottom:8px;",a.createEl("span",{text:i("feat_rebuild_vectors"),cls:"setting-item-name"});let s=n.createEl("div");s.style.cssText="display:flex; align-items:center; gap:8px;";let l=n.createEl("div",{cls:"paperforge-embed-status-text"});(()=>{var b;s.empty(),l.empty();let c=(Oe(t)||{}).build_state||{};this.plugin._embedProgress=this.plugin._embedProgress||{current:0,total:0,key:""},!this.plugin._embedProcess&&c.status==="running"&&(this.plugin._embedProgress={current:c.current||0,total:c.total||1,key:c.paper_id||""});let{current:p,total:h,key:d}=this.plugin._embedProgress;if(!!this.plugin._embedProcess||c.status==="running"){let x=s.createEl("div",{cls:"paperforge-progress-track"});x.style.cssText="flex:1;";let _=h>0?(p/h*100).toFixed(1):"0",k=x.createEl("div",{cls:"paperforge-progress-seg done"});if(k.style.cssText=`width:${_}%; min-width:${p>0?"2px":"0"};`,p{this._callPython(["embed","stop","--json"],{timeout:8e3}),this.plugin._embedProcess&&(this.plugin._embedProcess.kill(),this.plugin._embedProcess=null),this.display()})}else{let x=Oe(t),_=!!(x&&((b=x.chunk_count)!=null?b:0)>0),k=x&&x.corrupted,D=f=>{if(!de(t,this.plugin.settings).path){new F.Notice(i("feat_no_python"));return}let w=Object.assign({},process.env,{PYTHONIOENCODING:"utf-8",PYTHONUTF8:"1",VECTOR_DB_API_KEY:this.plugin.settings.vector_db_api_key||"",VECTOR_DB_API_BASE:this.plugin.settings.vector_db_api_base||"",VECTOR_DB_API_MODEL:this.plugin.settings.vector_db_api_model||""});this.plugin._embedStderr="",this.plugin._embedProgress={current:0,total:0,key:""},this.plugin._embedProcess=this._callPython(["embed","build",f],{stream:!0,env:w,onData:T=>{let R=T.toString("utf-8").split(`
-`);for(let B of R)if(B.startsWith("EMBED_START:"))this.plugin._embedProgress.total=parseInt(B.split(":")[1])||0;else if(B.startsWith("EMBED_PROGRESS:")){let A=B.split(":");this.plugin._embedProgress.current=parseInt(A[1])||0,this.plugin._embedProgress.key=A[3]||""}else B.startsWith("EMBED_DONE")&&(this.plugin._embedProcess=null,this.plugin._embedProgress.current=this.plugin._embedProgress.total);this.display()},onStderr:T=>{this.plugin._embedStderr||(this.plugin._embedStderr=""),this.plugin._embedStderr+=T.toString("utf-8")},onError:T=>{this.plugin._embedProcess=null,new F.Notice(i("feat_build_failed")+": "+(T.message||T)),this.display()},onClose:T=>{if(this.plugin._embedProcess=null,T===0)this.plugin._embedProgress.current=this.plugin._embedProgress.total,this.plugin.saveSettings(),this._embedStatusText=we(t),new F.Notice(i("feat_build_complete"));else{this._embedStatusText=null;let R=(this.plugin._embedStderr||"").slice(0,200);new F.Notice(i("feat_build_failed")+(R?": "+R:""),8e3)}this.plugin._embedStderr="",this.display(),this._refreshSnapshots(t)}}),this.display()};if(k){let f=n.createEl("div");f.style.cssText="padding:8px 12px; margin:8px 0; background:var(--background-modifier-warning); border-radius:4px; font-size:12px; display:flex; align-items:center; justify-content:space-between;",f.createEl("span",{text:i("feat_vector_corrupted")});let y=f.createEl("button",{text:i("feat_vector_rebuild_force_btn")});y.className="mod-cta",y.addEventListener("click",()=>D("--force"))}_&&!k&&s.createEl("span",{text:x.chunk_count+" chunks embedded",cls:"setting-item-description"});let S=s.createEl("button");if(S.setText(_?i("feat_rebuild_btn"):i("feat_build_btn")),S.addClass("mod-cta"),S.addEventListener("click",()=>D("--resume")),!k&&_){let f=s.createEl("button");f.setText(i("feat_vector_rebuild_force_btn")),f.style.marginLeft="6px",f.addEventListener("click",()=>D("--force"))}}})()}_getCurrentModelKey(){return this.plugin.settings.vector_db_api_model||"text-embedding-3-small"}_parseEmbedStatus(e){let t={};return e&&(e.split(`
-`).forEach(r=>{let n=r.match(/^\s*([^:]+):\s*(.*)/);n&&(t[n[1].trim()]=n[2].trim())}),t.db_exists!==void 0&&(t.db_exists=t.db_exists==="True"),t.chunk_count!==void 0&&(t.chunk_count=parseInt(t.chunk_count,10)||0)),t}_getPythonDesc(e,t){return t==="stale"?`[!!] ${e} (stale \u2014 path no longer exists, update or clear the override below)`:t==="manual"?`${e} (manual)`:`${e} (auto-detected)`}_refreshPythonInterpDesc(e,t){let r=this._pythonInterpDescEl;r&&(t==="stale"?r.textContent=`[!!] ${e} (stale \u2014 path no longer exists, update or clear the override below)`:t==="manual"?r.textContent=`${e} (manual)`:r.textContent=`${e} (auto-detected)`)}_validatePythonOverride(){let e=this.plugin.settings.python_path?this.plugin.settings.python_path.trim():"",t=this._customPathDescEl;if(!e){let r="\u8BF7\u8F93\u5165\u8DEF\u5F84 / Enter a path first";t&&(t.innerHTML=`\u2717 ${r}`),new F.Notice(r);return}if(!L.existsSync(e)){let r="\u8DEF\u5F84\u4E0D\u5B58\u5728 / Path does not exist";t&&(t.innerHTML=`\u2717 ${r}`),new F.Notice(r,4e3);return}try{L.accessSync(e,L.constants.X_OK)}catch(r){let n="\u4E0D\u53EF\u6267\u884C / Not executable";t&&(t.innerHTML=`\u2717 ${n}`),new F.Notice(n,4e3);return}(0,$.execFile)(e,["--version"],{timeout:8e3},(r,n)=>{if(r||!n){let o="\u65E0\u6CD5\u8FD0\u884C / Cannot run";t&&(t.innerHTML=`\u2717 ${o}`),new F.Notice(o,4e3);return}let a=n.match(/Python (\d+)\.(\d+)/);if(!a){let o="\u65E0\u6CD5\u89E3\u6790\u7248\u672C / Cannot parse version";t&&(t.innerHTML=`\u2717 ${o}`),new F.Notice(o,4e3);return}let s=parseInt(a[1],10),l=parseInt(a[2],10);if(s<3||s===3&&l<10){let o="Python \u7248\u672C\u8FC7\u4F4E\uFF0C\u9700\u8981 3.10+ / Python version too low, need 3.10+";t&&(t.innerHTML=`\u2717 ${o}`),new F.Notice(o,4e3);return}(0,$.execFile)(e,["-m","pip","--version"],{timeout:8e3},o=>{if(o){let c=`\u2713 Python ${s}.${l} \u6709\u6548\uFF0C\u4F46\u672A\u68C0\u6D4B\u5230 pip / Valid, but pip not found`;t&&(t.innerHTML=`\u26A0 ${c}`),new F.Notice(c,4e3)}else{let c=`\u2713 Python ${s}.${l} \u6709\u6548 / Valid`;t&&(t.innerHTML=`${c}`),new F.Notice(c,4e3)}})})}_syncRuntime(e){let t=this.app.vault.adapter.basePath,{path:r,extraArgs:n=[]}=N(t,this.plugin.settings,void 0,void 0),a=this.plugin.manifest.version,s=mt(r,a,n);e.setDisabled(!0),e.setButtonText(i("runtime_health_syncing"));let l=(c,p)=>(console.log(`[PaperForge] Sync Runtime: trying ${p}`),yt(s.cmd,c,t,s.timeout,void 0,be())),o=()=>{let c="opencode";try{let m=L.readFileSync(Z.join(t,"paperforge.json"),"utf-8"),b=JSON.parse(m);b.agent_key&&(c=b.agent_key)}catch(m){}let p=[...n,"-c",'from paperforge.services.skill_deploy import deploy_skills; from pathlib import Path; r=deploy_skills(vault=Path(r"'+t.replace(/\\/g,"\\\\")+'"), agent_key="'+c+'", overwrite=True); print("skills deployed" if r["skill_deployed"] else "skills skipped", flush=True)'],h=(0,$.spawn)(r,p,{cwd:t,timeout:3e4,windowsHide:!0}),d="";h.stdout.on("data",m=>{d+=m.toString("utf-8")}),h.on("close",m=>{console.log(`[PaperForge] Skill deploy: ${d.trim()} (exit ${m})`)})};l(s.pypiArgs,"PyPI").then(c=>{if(c.exitCode===0){console.log("[PaperForge] Sync Runtime: installed via PyPI"),o(),new F.Notice(i("runtime_health_sync_done").replace("{0}",a),5e3),this.display();return}console.warn("[PaperForge] Sync Runtime: PyPI failed, falling back to git..."),l(s.gitArgs,"git").then(p=>{p.exitCode===0?(console.log("[PaperForge] Sync Runtime: installed via git"),o(),new F.Notice(i("runtime_health_sync_done").replace("{0}",a),5e3),this.display()):(e.setDisabled(!1),e.setButtonText(i("runtime_health_sync")),console.error("[PaperForge] git fallback stderr:",p.stderr),new F.Notice(i("runtime_health_sync_fail").replace("{0}","pip exit code "+p.exitCode),8e3))})})}_debouncedSave(){clearTimeout(this._saveTimeout),this._saveTimeout=setTimeout(()=>this.plugin.saveSettings(),500)}_preCheck(e){var a;let t=this.app.vault.adapter.basePath,{path:r,extraArgs:n=[]}=N(t,(a=this.plugin)==null?void 0:a.settings,void 0,void 0);(0,$.execFile)(r,[...n,"--version"],{timeout:8e3},(s,l)=>{let o=[];o.push({label:"Python",ok:!s,detail:s?i("check_python_fail"):l.trim()});let c=!1,p=process.env.HOME||process.env.USERPROFILE||Ke.homedir()||"";if(process.platform==="darwin")c=["/Applications/Zotero.app",Z.join(p,"Applications","Zotero.app")].some(k=>{try{return L.existsSync(k)}catch(D){return!1}});else if(process.platform==="win32"){let _=process.env.ProgramFiles||"",k=process.env.LOCALAPPDATA||"";c=[Z.join(_,"Zotero"),Z.join(_,"(x86)","Zotero"),Z.join(k,"Programs","Zotero"),Z.join(k,"Zotero"),Z.join(p,"AppData","Local","Programs","Zotero")].filter(Boolean).some(S=>{try{return L.existsSync(S)}catch(f){return!1}})}else c=[Z.join(p,".local","share","zotero","zotero"),"/usr/bin/zotero","/usr/local/bin/zotero"].some(k=>{try{return L.existsSync(k)}catch(D){return!1}});let h=this.plugin.settings.zotero_data_dir;if(!c&&h)try{c=L.existsSync(h)}catch(_){}o.push({label:"Zotero",ok:c,detail:c?i("check_zotero_ok"):i("check_zotero_fail")});let d=!1,m=process.env.APPDATA||"";process.platform==="win32"&&m&&(d=$e(Z.join(m,"Zotero","Zotero","Profiles"))),!d&&process.platform==="darwin"&&p&&(d=$e(Z.join(p,"Library","Application Support","Zotero","Profiles"))),!d&&process.platform!=="win32"&&process.platform!=="darwin"&&p&&(d=$e(Z.join(p,".zotero","zotero","Profiles"))),!d&&h&&String(h).trim()&&(d=et(h.trim())),!d&&p&&(d=et(Z.join(p,"Zotero"))),o.push({label:"Better BibTeX",ok:d,detail:d?i("check_bbt_ok"):i("check_bbt_fail")});let b={true:"\u2713",false:"\u2717"};if(this._checkEl){this._checkEl.setText(o.map(k=>`${b[String(k.ok)]} ${k.label}: ${k.detail}`).join(`
-`));let _=o.some(k=>!k.ok);this._checkEl.className=`paperforge-message msg-${_?"error":"ok"}`}let x=o.filter(_=>!_.ok);x.length>0&&new F.Notice(`[!!] \u672A\u901A\u8FC7: ${x.map(_=>_.label).join(", ")}`,6e3),e()})}_renderMaintenanceTab(e){e.createEl("h2",{text:i("tab_maintenance")||"\u7EF4\u62A4"});let t=this.app.vault.adapter.basePath,r=N(t,this.plugin.settings,L,$.execFileSync);if(!r.path){e.createEl("p",{text:"\u26A0 Python \u672A\u914D\u7F6E\uFF0C\u8BF7\u5148\u5728\u201C\u5B89\u88C5\u201D\u6807\u7B7E\u9875\u914D\u7F6E\u3002",cls:"setting-item-description"});return}let n=e.createEl("div");n.createEl("p",{text:"\u6B63\u5728\u52A0\u8F7D OCR \u7EF4\u62A4\u6570\u636E\u2026"});let a=Z.join(Ke.tmpdir(),`pf_ocr_maintenance_${Date.now()}.json`),s=["-m","paperforge","ocr","list","--json","--output",a];(0,$.execFile)(r.path,s,{cwd:t,timeout:3e4,windowsHide:!0},(l,o,c)=>{if(n.empty(),!L.existsSync(a)){n.createEl("p",{text:"\u274C \u65E0\u6CD5\u52A0\u8F7D OCR \u6570\u636E\u3002\u8BF7\u786E\u4FDD\u5DF2\u5B89\u88C5 paperforge \u5E76\u8FD0\u884C\u8FC7 OCR\u3002",cls:"setting-item-description"});return}let p=[];try{p=JSON.parse(L.readFileSync(a,"utf-8"))}catch(v){p=[]}try{L.unlinkSync(a)}catch(v){}if(!p.length){n.createEl("p",{text:"\u6CA1\u6709 OCR \u8BBA\u6587\u3002\u8BF7\u5148\u8FD0\u884C OCR\u3002"});return}let h=p.map(v=>({row:v,ui:St(v)})),d=Pt(h.map(v=>v.ui));n.empty();let m=n.createEl("div",{cls:"pf-maint-hero pf-card"});m.createEl("h3",{text:d.tone==="warn"?i("ocr_maint_hero_warn").replace("{rebuild}",String(d.counts.rebuild)).replace("{failed}",String(d.counts.failed)):i("ocr_maint_hero_ok")}),m.createEl("p",{text:i("ocr_maint_hero_note"),cls:"setting-item-description"});let b=m.createEl("div",{cls:"pf-maint-counts"});for(let[v,C]of[[i("ocr_maint_no_action"),d.counts.ok],[i("ocr_maint_rebuild"),d.counts.rebuild],[i("ocr_maint_failed"),d.counts.failed]]){let E=b.createEl("div",{cls:"pf-maint-stat"});E.createEl("strong",{text:String(C)}),E.createEl("span",{text:v})}let x=h.filter(v=>v.ui.category==="rebuild"||v.ui.category==="failed");if(x.length>0){n.createEl("h3",{text:i("ocr_maint_needs_attention")});let v=n.createEl("div",{cls:"pf-maint-section"});for(let C of x){let E=v.createEl("div",{cls:"pf-maint-card"});E.createEl("strong",{text:C.row.title_short||C.row.title||C.row.key});let P=E.createEl("span",{cls:"pf-maint-chip pf-maint-chip--"+C.ui.category,text:C.ui.label});P.style.marginLeft="8px",E.createEl("p",{text:C.ui.reason,cls:"setting-item-description"});let M=E.createEl("button",{text:C.ui.primaryAction==="rebuild"?i("ocr_maint_rebuild_btn"):i("ocr_maint_redo_btn")});M.style.cssText="padding:4px 10px; border-radius:4px; cursor:pointer; font-size:12px;",M.dataset.action=C.ui.primaryAction||"",M.dataset.key=C.row.key}}let _=h.filter(v=>v.ui.category==="limited");if(_.length>0){n.createEl("h3",{text:i("ocr_maint_limitations")}),n.createEl("p",{text:i("ocr_maint_limitations_intro"),cls:"setting-item-description"});for(let v of _){let C=n.createEl("div",{cls:"pf-maint-card"});C.createEl("strong",{text:v.row.title_short||v.row.title||v.row.key});let E=C.createEl("span",{cls:"pf-maint-chip pf-maint-chip--limited",text:v.ui.label});E.style.marginLeft="8px",C.createEl("p",{text:v.ui.reason,cls:"setting-item-description"})}}let k=n.createEl("details",{cls:"pf-maint-advanced"});k.createEl("summary",{text:i("ocr_maint_all_papers")+" ("+p.length+")"});let D=v=>{let C=v.status,E=v.health;return C==="done"&&v.version==="v1"?{badge:"? \u672A\u8BC4\u4F30",color:"#9e9e9e"}:C==="done"&&E==="green"?{badge:"\u2713 \u5B8C\u6210",color:"#4caf50"}:C==="done"&&E==="yellow"?{badge:"\u26A0 \u8D28\u91CF\u95EE\u9898",color:"#ff9800"}:C==="done"&&E==="red"?{badge:"\u26A0 \u4E25\u91CD\u5F02\u5E38",color:"#f44336"}:C==="done_degraded"?{badge:"\u26A0 \u8D28\u91CF\u95EE\u9898",color:"#ff9800"}:C==="failed"||C==="fatal_error"?{badge:"\u2717 \u5931\u8D25",color:"#f44336"}:C==="pending"||C==="nopdf"||C==="blocked"?{badge:"\u25CB \u5F85\u5904\u7406",color:"#9e9e9e"}:C==="running"||C==="queued"?{badge:"\u25CF \u5904\u7406\u4E2D",color:"#2196f3"}:C==="retryable_error"?{badge:"\u2717 \u53EF\u91CD\u8BD5",color:"#ff9800"}:{badge:C,color:"#9e9e9e"}},S=v=>v.recommended_action==="redo"?"\u91CD\u65B0OCR":v.recommended_action==="rebuild"?"\u91CD\u5EFA\u7D22\u5F15":"",f={};for(let v of p){let C=D(v).badge;f[C]=(f[C]||0)+1}let y=["\u2713 \u5B8C\u6210","? \u672A\u8BC4\u4F30","\u26A0 \u8D28\u91CF\u95EE\u9898","\u26A0 \u4E25\u91CD\u5F02\u5E38","\u2717 \u5931\u8D25","\u25CB \u5F85\u5904\u7406","\u25CF \u5904\u7406\u4E2D"],w=k.createEl("div");w.style.cssText="display:flex; align-items:center; gap:8px; margin-bottom:8px; flex-wrap:wrap;";let T={};for(let v of p)T[v.key]={sel:!1,action:v.recommended_action||""};let R="all",B=p,A=()=>{B=R==="all"?p:p.filter(v=>D(v).badge===R),re.empty(),Pe(B),U()},V=w.createEl("select");V.style.cssText="padding:4px 8px; border-radius:4px;",V.createEl("option",{text:"\u5168\u90E8",value:"all"});for(let v of y)f[v]&&V.createEl("option",{text:v+" "+f[v],value:v});V.addEventListener("change",()=>{R=V.value,A()});let Y=w.createEl("button",{text:"\u5168\u9009"}),O=w.createEl("button",{text:"\u53D6\u6D88\u5168\u9009"});Object.assign(Y.style,{padding:"4px 10px",borderRadius:"4px",cursor:"pointer"}),Object.assign(O.style,{padding:"4px 10px",borderRadius:"4px",cursor:"pointer"});let J=w.createEl("button",{text:"\u25B8 \u6267\u884C\u5DF2\u9009"});J.style.cssText="padding:4px 12px; border-radius:4px; cursor:pointer; font-weight:600; margin-left:auto;";let W=w.createEl("span",{cls:"setting-item-description"});W.style.cssText="font-size:11px;";let U=()=>{let v=0;for(let C of B)T[C.key].action&&v++;W.setText("\u5F85\u4FEE\u590D "+v+" \u7BC7")};Y.addEventListener("click",()=>{for(let v of B)T[v.key].sel=!0,T[v.key].action||(T[v.key].action=v.recommended_action||"");A()}),O.addEventListener("click",()=>{for(let v of p)T[v.key].sel=!1,T[v.key].action="";A()}),J.addEventListener("click",()=>{let v=[],C=[];for(let E of p){let P=T[E.key].action;P==="redo"?v.push(E.key):P==="rebuild"&&C.push(E.key)}if(!v.length&&!C.length){new F.Notice("\u8BF7\u5148\u9009\u62E9\u8981\u4FEE\u590D\u7684\u8BBA\u6587\u3002");return}n.empty(),n.createEl("p",{text:"\u6267\u884C\u4E2D\u2026"}),v.length&&(0,$.execFile)(r.path,["-m","paperforge","ocr","redo",...v],{cwd:t,timeout:3e5,windowsHide:!0},()=>{new F.Notice("\u91CD\u65B0OCR\u5DF2\u89E6\u53D1\uFF0C\u5171 "+v.length+" \u7BC7\u3002")}),C.length&&(0,$.execFile)(r.path,["-m","paperforge","ocr","rebuild",...C],{cwd:t,timeout:12e4,windowsHide:!0},()=>{new F.Notice("\u91CD\u5EFA\u5B8C\u6210\uFF0C\u5171 "+C.length+" \u7BC7\u3002")})});let te=k.createEl("div");te.style.cssText="max-height:60vh; overflow-y:auto; border:1px solid var(--background-modifier-border); border-radius:6px; margin-bottom:16px;";let ne=te.createEl("table");ne.style.cssText="width:100%; border-collapse:collapse; font-size:12px;";let ge=ne.createEl("thead"),re=ne.createEl("tbody"),he=ge.insertRow();["","Key","Title","\u72B6\u6001","\u5EFA\u8BAE","Model","Time","\u4FEE\u590D"].forEach(v=>{let C=document.createElement("th");C.textContent=v,C.style.cssText="padding:4px 6px; text-align:left; border-bottom:1px solid var(--background-modifier-border); position:sticky; top:0; background:var(--background-primary); z-index:1; white-space:nowrap;",he.appendChild(C)});let fe=(v,C)=>`${v}`,Pe=v=>{var C,E;for(let P of v){let M=T[P.key],z=D(P),Q=S(P),G=re.insertRow();G.style.cssText="border-bottom:1px solid var(--background-modifier-border);";let ke=G.insertCell();ke.style.cssText="padding:3px 4px;";let De=document.createElement("input");De.type="checkbox",De.checked=M.sel,De.addEventListener("change",()=>{M.sel=De.checked,!M.sel&&M.action&&(M.action=""),M.sel&&!M.action&&(M.action=P.recommended_action||"")}),ke.appendChild(De);let at=G.insertCell();at.style.cssText="padding:3px 4px; white-space:nowrap; font-size:11px; max-width:90px; overflow:hidden; text-overflow:ellipsis;",at.textContent=P.key;let We=G.insertCell();We.style.cssText="padding:3px 4px; white-space:nowrap; max-width:220px; overflow:hidden; text-overflow:ellipsis;",We.textContent=P.title_short||P.title||P.key,We.title=P.title||P.key;let it=G.insertCell();it.style.cssText="padding:3px 4px; white-space:nowrap;",it.innerHTML=fe(z.badge,z.color);let ot=G.insertCell();ot.style.cssText="padding:3px 4px; white-space:nowrap; max-width:160px; overflow:hidden; text-overflow:ellipsis; font-size:11px; color:var(--text-muted);";let _e="";Q?_e=Q:z.badge==="\u2713 \u5B8C\u6210"?_e="\u5DF2\u5B8C\u6210":z.badge.includes("\u5F85\u5904\u7406")?_e="\u7B49\u5F85OCR":z.badge.includes("\u5931\u8D25")?_e=((C=P.error_summary)==null?void 0:C.substring(0,50))||"":z.badge.includes("\u672A\u8BC4\u4F30")?_e="\u5EFA\u8BAE\u91CD\u65B0\u5904\u7406":(E=P.degraded_reasons)!=null&&E.length&&(_e=P.degraded_reasons[0].substring(0,50)),ot.textContent=_e;let lt=G.insertCell();lt.style.cssText="padding:3px 4px; white-space:nowrap; max-width:140px; overflow:hidden; text-overflow:ellipsis; font-size:11px;",lt.textContent=P.model||"-";let ct=G.insertCell();ct.style.cssText="padding:3px 4px; white-space:nowrap; font-size:11px; color:var(--text-muted);",ct.textContent=P.finished_at||"-";let Re=G.insertCell();if(Re.style.cssText="padding:3px 4px; text-align:center; white-space:nowrap;",Q){let me=document.createElement("input");me.type="checkbox",me.checked=!!M.action,me.title=Q,me.addEventListener("change",()=>{M.action=me.checked?P.recommended_action:"",M.sel=me.checked,A()}),Re.appendChild(me);let qe=document.createElement("span");qe.style.cssText="font-size:10px; color:var(--text-faint); margin-left:2px;",qe.textContent=Q,Re.appendChild(qe)}else Re.textContent="-",Re.style.cssText="padding:3px 4px; text-align:center; font-size:11px; color:var(--text-faint);"}};Pe(p),U(),e.createEl("hr"),e.createEl("h3",{text:"\u5168\u5C40\u64CD\u4F5C"});let Ee=e.createEl("div");Ee.style.cssText="display:flex; gap:8px; flex-wrap:wrap;";let Fe=Ee.createEl("button",{text:"\u91CD\u5EFA\u641C\u7D22\u7D22\u5F15"});Fe.style.cssText="padding:6px 14px; border-radius:4px; cursor:pointer;",Fe.addEventListener("click",()=>{new F.Notice("\u6B63\u5728\u91CD\u5EFA\u641C\u7D22\u7D22\u5F15\u2026"),(0,$.execFile)(r.path,["-m","paperforge","embed","build","--force"],{cwd:t,timeout:3e5,windowsHide:!0},(v,C,E)=>{new F.Notice("\u641C\u7D22\u7D22\u5F15\u91CD\u5EFA\u5B8C\u6210\u3002")})});let Te=Ee.createEl("button",{text:"\u91CD\u5EFA\u8BB0\u5FC6\u5E93"});Te.style.cssText="padding:6px 14px; border-radius:4px; cursor:pointer;",Te.addEventListener("click",()=>{new F.Notice("\u6B63\u5728\u91CD\u5EFA\u8BB0\u5FC6\u5E93\u2026"),(0,$.execFile)(r.path,["-m","paperforge","repair","--fix"],{cwd:t,timeout:12e4,windowsHide:!0},(v,C,E)=>{new F.Notice("\u8BB0\u5FC6\u5E93\u91CD\u5EFA\u5B8C\u6210\u3002")})})})}_renderReleaseNotesTab(e){e.createEl("h2",{text:"\u66F4\u65B0\u4E0E\u624B\u518C"}),e.createEl("h3",{text:"\u7248\u672C\u66F4\u65B0\u8BB0\u5F55"});let t=Ft.default.versions||[];for(let a of t){let s=e.createEl("div",{cls:"paperforge-release-card"}),l=s.createEl("div",{cls:"paperforge-release-header"});if(l.createEl("strong",{text:`v${a.version} \u2014 ${a.title}`}),l.createEl("span",{cls:"paperforge-release-date",text:` (${a.date})`}),a.breaking_or_migration&&a.breaking_or_migration.length>0){let o=s.createEl("div",{cls:"paperforge-release-section"});o.createEl("div",{cls:"paperforge-release-label",text:"\u884C\u4E3A\u53D8\u66F4 / \u8FC1\u79FB\u6CE8\u610F"});for(let c of a.breaking_or_migration)o.createEl("div",{cls:"paperforge-release-item",text:`\u2022 ${c}`})}if(a.new_features&&a.new_features.length>0){let o=s.createEl("div",{cls:"paperforge-release-section"});o.createEl("div",{cls:"paperforge-release-label",text:"\u65B0\u529F\u80FD"});for(let c of a.new_features)o.createEl("div",{cls:"paperforge-release-item",text:`\u2022 ${c}`})}if(a.fixes&&a.fixes.length>0){let o=s.createEl("div",{cls:"paperforge-release-section"});o.createEl("div",{cls:"paperforge-release-label",text:"\u4FEE\u590D"});for(let c of a.fixes)o.createEl("div",{cls:"paperforge-release-item",text:`\u2022 ${c}`})}if(a.recommended_actions&&a.recommended_actions.length>0){let o=s.createEl("div",{cls:"paperforge-release-section paperforge-release-recommended"});o.createEl("div",{cls:"paperforge-release-label",text:"\u5EFA\u8BAE\u64CD\u4F5C"});for(let c of a.recommended_actions)o.createEl("div",{cls:"paperforge-release-item paperforge-release-item-bold",text:`\u2022 ${c}`})}}e.createEl("h3",{text:"\u4F7F\u7528\u624B\u518C"}),e.createEl("div",{cls:"paperforge-manual-links"}).createEl("a",{text:"\u2192 \u67E5\u770B\u5B8C\u6574\u4F7F\u7528\u624B\u518C\uFF08GitHub\uFF09",href:"https://github.com/LLLin000/PaperForge/blob/master/docs/user-manual.md"}).setAttr("target","_blank")}};var I=require("obsidian"),ue=q(require("fs")),Ne=q(require("path")),xe=require("child_process");var Ie=q(require("path"));function Tt(g){if(!g)return null;let u=Ie.dirname(g);for(;;){let e=Ie.basename(u);if(!e||e===".")break;let t=e.match(/^([A-Z0-9]{8})(?:\s*-\s*.*)?$/i);if(t)return t[1];let r=Ie.dirname(u);if(r===u)break;u=r}return null}var Ce=class extends I.ItemView{constructor(e){super(e);this._currentMode=null;this._currentDomain=null;this._currentPaperKey=null;this._currentPaperEntry=null;this._currentFilePath=null;this._cachedItems=null;this._modeSubscribers=[];this._leafChangeTimer=null;this._ocrPrivacyShown=!1;this._cachedStats=null;this._techDetailsExpanded=!1;this._paperforgeVersion="";this._dashboardPermissions={};this._headerTitle=null;this._versionBadge=null;this._messageEl=null;this._metricsEl=null;this._ocrSection=null;this._ocrEmpty=null;this._ocrBadge=null;this._ocrTrack=null;this._ocrCounts=null;this._driftBannerEl=null;this._currentMode=null,this._currentDomain=null,this._currentPaperKey=null,this._currentPaperEntry=null,this._currentFilePath=null,this._cachedItems=null,this._modeSubscribers=[],this._leafChangeTimer=null,this._ocrPrivacyShown=!1}getViewType(){return ye}getDisplayText(){return"PaperForge"}getIcon(){return Be}async onOpen(){this._buildPanel(),this._modeSubscribers=[],this._leafChangeTimer=null,this._setupEventSubscriptions(),this._fetchVersion(),this._detectAndSwitch()}async onClose(){if(this._modeSubscribers&&this._modeSubscribers.length>0){for(let e of this._modeSubscribers)e.event==="active-leaf-change"?this.app.workspace.off("active-leaf-change",e.ref):e.event==="modify"&&this.app.vault.off("modify",e.ref);this._modeSubscribers=[]}this._leafChangeTimer&&(clearTimeout(this._leafChangeTimer),this._leafChangeTimer=null),this._cachedItems=null,this._cachedStats=null}_buildPanel(){let e=this.containerEl;e.empty(),e.addClass("paperforge-status-panel");let t=e.createEl("div",{cls:"paperforge-header"}),r=t.createEl("div",{cls:"paperforge-header-left"});r.createEl("div",{cls:"paperforge-header-logo",text:"P"}),this._modeContextEl=r.createEl("div",{cls:"paperforge-mode-context"}),this._headerTitle=r.createEl("h3",{cls:"paperforge-header-title",text:"PaperForge"}),this._versionBadge=r.createEl("span",{cls:"paperforge-header-badge",text:"v\u2014"});let n=t.createEl("button",{cls:"paperforge-header-refresh",attr:{"aria-label":"Refresh"}});n.innerHTML="\u21BB",n.addEventListener("click",()=>{this._invalidateIndex(),this._detectAndSwitch()}),this._messageEl=e.createEl("div",{cls:"paperforge-message"}),this._contentEl=e.createEl("div",{cls:"paperforge-content-area"})}_fetchVersion(){var s,l;let e=this.app.vault.adapter.basePath,t=this.app.plugins.plugins.paperforge,r=((s=t==null?void 0:t.manifest)==null?void 0:s.version)||"?",{path:n,extraArgs:a=[]}=N(e,(l=t==null?void 0:t.settings)!=null?l:null,void 0,void 0);_t(n,r,e,1e4,void 0).then(o=>{if(o.status==="not-installed")return;let c=o.pyVersion||"";this._paperforgeVersion=c.startsWith("v")?c:"v"+c,this._versionBadge&&this._versionBadge.setText(this._paperforgeVersion),this._driftBannerEl&&r&&this._paperforgeVersion!=="v"+r.replace(/^v/,"")?(this._driftBannerEl.style.display="block",this._driftBannerEl.setText(i("dashboard_drift_warning").replace("{0}",this._paperforgeVersion).replace("{1}","v"+r.replace(/^v/,"")))):this._driftBannerEl&&(this._driftBannerEl.style.display="none")})}_fetchStats(e){var s;if(!this._metricsEl)return;if(!e&&!this._cachedStats)this._metricsEl.empty(),this._metricsEl.createEl("div",{cls:"paperforge-status-loading",text:"Loading..."});else if(e&&!this._cachedStats)return;let t=this.app.vault.adapter.basePath,r=this.app.plugins.plugins.paperforge,{path:n,extraArgs:a=[]}=N(t,(s=r==null?void 0:r.settings)!=null?s:null,void 0,void 0);(0,xe.execFile)(n,[...a,"-m","paperforge","dashboard","--json"],{cwd:t,timeout:3e4},(l,o)=>{if(!l)try{let c=JSON.parse(o);if(c.ok&&c.data){let p=this._normalizeDashboardData(c.data);this._cachedStats=p,this._metricsEl.empty(),this._renderStats(p),this._renderOcr(p),this._dashboardPermissions=c.data.permissions||{};return}}catch(c){}this._fallbackFetchStats(e,t,r)})}_normalizeDashboardData(e){let t=e.stats||{},r=t.ocr_health||{},n=t.pdf_health||{},a=e.ocr_version_state||{},s=(r.done||0)+(r.pending||0)+(r.failed||0);return{total_papers:t.papers||0,formal_notes:t.papers||0,exports:0,bases:0,ocr:{total:s,pending:r.pending||0,processing:0,done:r.done||0,failed:r.failed||0},path_errors:(n.broken||0)+(n.missing||0),ocr_version_state:{total_papers:a.total_papers||0,derived_stale_count:a.derived_stale_count||0,raw_upgradable_count:a.raw_upgradable_count||0}}}_fallbackFetchStats(e,t,r){var s,l,o;let n=((s=r==null?void 0:r.settings)==null?void 0:s.system_dir)||"System",a=Ne.join(t,n,"PaperForge","indexes","formal-library.json");try{let c=ue.readFileSync(a,"utf-8"),p=JSON.parse(c),h=p.items||[],d={},m={pdf_health:{healthy:0,unhealthy:0},ocr_health:{healthy:0,unhealthy:0},note_health:{healthy:0,unhealthy:0},asset_health:{healthy:0,unhealthy:0}},b=0,x=0,_=0,k=0,D=0,S=0;for(let f of h){f.note_path&&S++;let y=f.lifecycle||"pdf_ready";d[y]=(d[y]||0)+1;let w=f.health||{};for(let R of["pdf_health","ocr_health","note_health","asset_health"])(w[R]||"healthy")==="healthy"?m[R].healthy++:m[R].unhealthy++;let T=f.ocr_status||"";b++,T==="done"?x++:T==="pending"?_++:T==="processing"||T==="queued"||T==="running"?k++:D++}this._cachedStats={version:p.paperforge_version||((l=this._cachedStats)==null?void 0:l.version)||"\u2014",total_papers:h.length,formal_notes:S,exports:0,bases:0,ocr:{total:b,pending:_,processing:k,done:x,failed:D},path_errors:0,lifecycle_level_counts:d,health_aggregate:m},this._metricsEl.empty(),this._renderStats(this._cachedStats),this._renderOcr(this._cachedStats)}catch(c){!e&&!this._cachedStats&&this._metricsEl.createEl("div",{cls:"paperforge-status-loading",text:"No index \u2014 trying CLI..."});let{path:p,extraArgs:h=[]}=N(t,(o=r==null?void 0:r.settings)!=null?o:null,void 0,void 0);(0,xe.execFile)(p,[...h,"-m","paperforge","status","--json"],{cwd:t,timeout:3e4},(d,m)=>{if(d){if(this._cachedStats)return;this._metricsEl.createEl("div",{cls:"paperforge-status-error",text:`Cannot reach PaperForge CLI.
-Make sure paperforge is installed and in your PATH.`});return}try{let b=JSON.parse(m);this._cachedStats=b,this._metricsEl.empty(),this._renderStats(b),this._renderOcr(b)}catch(b){this._cachedStats||this._metricsEl.createEl("div",{cls:"paperforge-status-error",text:"Invalid response from paperforge status."})}})}}_renderSkeleton(e){e.addClass("paperforge-loading")}_renderEmptyState(e,t){e.createEl("div",{cls:"paperforge-empty-state",text:t||"No data"})}_buildMetricBar(e,t,r){if(r<=0)return;let n=Math.min(100,t/r*100);e.createEl("div",{cls:"paperforge-metric-progress"}).createEl("div",{cls:"paperforge-metric-progress-fill",attr:{style:`width:${n.toFixed(1)}%`}})}_loadIndex(){var a;let e=this.app.vault.adapter.basePath,t=this.app.plugins.plugins.paperforge,r=((a=t==null?void 0:t.settings)==null?void 0:a.system_dir)||"System",n=Ne.join(e,r,"PaperForge","indexes","formal-library.json");try{let s=ue.readFileSync(n,"utf-8");return JSON.parse(s)}catch(s){return null}}_getCachedIndex(){if(!this._cachedItems){let e=this._loadIndex();this._cachedItems=e?e.items||[]:[]}return this._cachedItems}_findEntry(e){if(!e)return null;let t=this._getCachedIndex().find(r=>r.zotero_key===e)||null;return ut(this.app,t)}_patchCachedEntry(e,t){if(!e||!this._cachedItems)return;let r=this._cachedItems.findIndex(n=>n.zotero_key===e);r!==-1&&(this._cachedItems[r]=Je(this._cachedItems[r],t))}_filterByDomain(e){return e?this._getCachedIndex().filter(t=>t.domain===e):[]}_renderStats(e){var s;if(this._versionBadge&&this._versionBadge.setText(this._paperforgeVersion||(e.version?"v"+e.version:"v\u2014")),!e||typeof e.total_papers=="undefined"){this._metricsEl&&this._renderSkeleton(this._metricsEl);return}if(!this._metricsEl)return;this._metricsEl.removeClass("paperforge-loading");let t=e.total_papers||0,r=e.formal_notes||0,n=[{value:t,label:"Papers",color:"var(--color-cyan)",barMax:0},{value:r,label:"Formal Notes",color:"var(--color-blue)",barMax:t},{value:e.exports||0,label:"Exports",color:"var(--color-purple)",barMax:0}];for(let l of n){let o=this._metricsEl.createEl("div",{cls:"paperforge-metric-card"});o.style.setProperty("--metric-color",l.color),o.createEl("div",{cls:"paperforge-metric-value",text:((s=l.value)==null?void 0:s.toString())||"\u2014"}),o.createEl("div",{cls:"paperforge-metric-label",text:l.label}),l.barMax>0&&this._buildMetricBar(o,l.value,l.barMax)}let a=e.ocr_version_state||{};if(a.total_papers>0&&(a.derived_stale_count>0||a.raw_upgradable_count>0)){let l=[];a.derived_stale_count>0&&l.push(`${a.derived_stale_count} stale`),a.raw_upgradable_count>0&&l.push(`${a.raw_upgradable_count} upgradable`);let o=this._metricsEl.createEl("div",{cls:"paperforge-metric-card"});o.style.setProperty("--metric-color","var(--color-yellow)"),o.createEl("div",{cls:"paperforge-metric-value",text:l.join(", ")}),o.createEl("div",{cls:"paperforge-metric-label",text:"OCR Version"})}}_renderOcr(e){if(!this._ocrSection)return;let t=e.ocr||{},r=t.total||0;if(r===0){this._ocrSection.style.display="none";return}this._ocrSection.style.display="block",this._ocrEmpty&&(this._ocrEmpty.style.display="none");let n=t.done||0,a=t.pending||0,s=t.processing||0,l=t.failed||0;if(this._ocrBadge&&(this._ocrBadge.removeClass("active","idle"),s>0?(this._ocrBadge.addClass("active"),this._ocrBadge.setText("Processing")):a>0?(this._ocrBadge.addClass("idle"),this._ocrBadge.setText("Pending")):(this._ocrBadge.addClass("idle"),this._ocrBadge.setText("Idle"))),this._ocrTrack){this._ocrTrack.empty(),s>0?this._ocrTrack.addClass("paperforge-processing"):this._ocrTrack.removeClass("paperforge-processing");let o=[{cls:"pending",count:a},{cls:"active",count:s},{cls:"done",count:n},{cls:"failed",count:l}];for(let c of o)if(c.count>0){let p=(c.count/r*100).toFixed(1);this._ocrTrack.createEl("div",{cls:`paperforge-progress-seg ${c.cls}`,attr:{style:`width:${p}%`}})}}if(this._ocrCounts){this._ocrCounts.empty();let o=[{cls:"pending",value:a,label:"Pending"},{cls:"active",value:s,label:"Processing"},{cls:"done",value:n,label:"Done"},{cls:"failed",value:l,label:"Failed"}];for(let c of o){let p=this._ocrCounts.createEl("div",{cls:"paperforge-ocr-count"});p.createEl("div",{cls:"paperforge-ocr-count-value",text:c.value.toString()}),p.createEl("div",{cls:"paperforge-ocr-count-label",text:c.label})}}}_renderLifecycleStepper(e,t,r){if(!t||!r){this._renderSkeleton(e);return}let n=[{key:"indexed",label:"Indexed"},{key:"pdf_ready",label:"PDF Ready"},{key:"fulltext_ready",label:"Fulltext Ready"},{key:"deep_read_done",label:"Deep Read"}],a=e.createEl("div",{cls:"paperforge-lifecycle-stepper"}),s=!1;for(let l of n){let o=a.createEl("div",{cls:"step"});o.createEl("div",{cls:"step-indicator"}),o.createEl("div",{cls:"step-label",text:l.label}),l.key===r?(o.addClass("current"),s=!0):s?o.addClass("pending"):o.addClass("completed")}}_renderHealthMatrix(e,t){if(!t){this._renderSkeleton(e);return}let r=[{key:"pdf_health",label:"PDF Health",iconOk:"\u2713",iconWarn:"\u26A0",iconFail:"\u2717"},{key:"ocr_health",label:"OCR Health",iconOk:"\u2713",iconWarn:"\u26A0",iconFail:"\u2717"},{key:"note_health",label:"Note Health",iconOk:"\u2713",iconWarn:"\u26A0",iconFail:"\u2717"},{key:"asset_health",label:"Asset Health",iconOk:"\u2713",iconWarn:"\u26A0",iconFail:"\u2717"}],n=e.createEl("div",{cls:"paperforge-health-matrix"});for(let a of r){let s=t[a.key]||"healthy",l=n.createEl("div",{cls:"paperforge-health-cell"}),o,c,p;s==="healthy"||s==="ok"?(o=a.iconOk,c="ok",p=`${a.label}: OK`):s==="warn"||s==="warning"||s==="degraded"?(o=a.iconWarn,c="warn",p=`${a.label}: Needs Attention`):(o=a.iconFail,c="fail",p=`${a.label}: Failed`),l.addClass(c),l.setAttribute("title",p),l.createEl("div",{cls:"paperforge-health-cell-icon",text:o}),l.createEl("div",{cls:"paperforge-health-cell-label",text:a.label})}}_renderMaturityGauge(e,t,r){if(t==null||t===void 0){this._renderSkeleton(e);return}let n=e.createEl("div",{cls:"paperforge-maturity-gauge"}),a=n.createEl("div",{cls:"gauge-track"}),s=4,l=Math.max(1,Math.min(s,Math.round(t)));for(let o=1;o<=s;o++){let c=a.createEl("div",{cls:"gauge-segment"});o<=l&&(c.addClass("filled"),c.addClass(`level-${o}`))}if(n.createEl("div",{cls:"gauge-level",text:`Level ${l} / ${s}`}),l0){let c=n.createEl("ul",{cls:"gauge-blockers"});for(let p of o)c.createEl("li",{text:p})}}}_renderBarChart(e,t){if(!t||Object.keys(t).length===0){this._renderEmptyState(e,"No lifecycle data");return}let r=[{key:"indexed",label:"Indexed",cls:"stage-indexed"},{key:"pdf_ready",label:"PDF Ready",cls:"stage-pdf-ready"},{key:"fulltext_ready",label:"Fulltext Ready",cls:"stage-fulltext-ready"},{key:"deep_read_done",label:"Deep Read",cls:"stage-deep-read"}],n=e.createEl("div",{cls:"paperforge-bar-chart"}),a=Math.max(1,...r.map(s=>t[s.key]||0));for(let s of r){let l=t[s.key]||0,o=l/a*100,c=n.createEl("div",{cls:"bar-row"});c.createEl("div",{cls:"bar-label",text:s.label}),c.createEl("div",{cls:"bar-track"}).createEl("div",{cls:`bar-fill ${s.cls}`,attr:{style:`width:${o.toFixed(1)}%`}}),c.createEl("div",{cls:"bar-count",text:l.toString()})}}_invalidateIndex(){this._cachedItems=null}_extractZoteroKeyFromPath(e){return Tt(e)}_resolveModeForFile(e){if(!e)return{mode:"global",filePath:null,key:null,domain:null};let t=e.extension,r=e.path;if(t==="base")return{mode:"collection",filePath:r,key:null,domain:e.basename.trim()};if(t==="md"){let a=this.app.metadataCache.getFileCache(e),s=a&&a.frontmatter&&a.frontmatter.zotero_key;if(s)return{mode:"paper",filePath:r,key:s,domain:null}}if(t==="pdf"){let a=this._getCachedIndex();for(let s of a){let l=(s.pdf_path||"").match(/\[\[([^\]]+)\]\]/);if((l?l[1]:s.pdf_path)===r)return{mode:"paper",filePath:r,key:s.zotero_key,domain:null}}}let n=this._extractZoteroKeyFromPath(r);return n?{mode:"paper",filePath:r,key:n,domain:null}:{mode:"global",filePath:r,key:null,domain:null}}_detectAndSwitch(){let e=this._resolveModeForFile(this.app.workspace.getActiveFile());this._currentDomain=e.domain||null,this._currentPaperKey=e.key||null,this._currentPaperEntry=e.key?this._findEntry(e.key):null,this._switchMode(e.mode,e.filePath)}_switchMode(e,t){if(this._currentMode===e&&this._currentFilePath===t){this._refreshCurrentMode();return}if(this._currentMode=e,this._currentFilePath=t,this._techDetailsExpanded=!1,!!this._contentEl)switch(this._contentEl.empty(),this._contentEl.removeClass("switching"),this._renderModeHeader(e),e){case"global":this._renderGlobalMode();break;case"paper":this._renderPaperMode();break;case"collection":this._renderCollectionMode();break}}_renderGlobalMode(){var fe,Pe,Ee,Fe,Te,v,C;if(!this._contentEl)return;let e=this._contentEl.createEl("div",{cls:"paperforge-global-view"});this._driftBannerEl=e.createEl("div",{cls:"paperforge-drift-banner"}),this._driftBannerEl.style.display="none";let t=this._getCachedIndex(),r=t.length,n=0,a=0,s=0;for(let E of t)E.has_pdf&&n++,E.ocr_status==="done"&&a++,E.deep_reading_status==="done"&&s++;let l=e.createEl("div",{cls:"paperforge-library-snapshot"});l.createEl("div",{cls:"paperforge-section-label",text:"Library Snapshot"});let o=l.createEl("div",{cls:"paperforge-snapshot-pills"}),c=[{value:r,label:"papers"},{value:n,label:"PDFs ready"},{value:a,label:"OCR done"},{value:s,label:"deep-read done"}];for(let E of c){let P=o.createEl("div",{cls:"paperforge-snapshot-pill"});P.createEl("span",{cls:"paperforge-snapshot-value",text:String(E.value)}),P.createEl("span",{cls:"paperforge-snapshot-label",text:" "+E.label})}let p=e.createEl("div",{cls:"paperforge-system-status"});p.createEl("div",{cls:"paperforge-section-label",text:"System Status"});let h=p.createEl("div",{cls:"paperforge-status-grid"}),d=this.app.plugins.plugins.paperforge,m=((fe=d==null?void 0:d.manifest)==null?void 0:fe.version)||"?",b=this._paperforgeVersion;if(!b)try{let E=this.app.vault.adapter.basePath,{path:P,extraArgs:M=[]}=N(E,(Pe=d==null?void 0:d.settings)!=null?Pe:null,void 0,void 0),z=(0,xe.execFileSync)(P,[...M,"-c","import paperforge; print(paperforge.__version__)"],{cwd:E,timeout:5e3,encoding:"utf-8",windowsHide:!0}).trim();z&&(b=z.startsWith("v")?z:"v"+z,this._paperforgeVersion=b)}catch(E){}b=b||"\u2014";let x=b==="v"+m;this._renderSystemStatusRow(h,"Runtime",x?"healthy":"mismatch",x?"v"+m:"plugin v"+m+" \u2260 CLI "+b);let _=this._loadIndex(),k=_&&_.items&&_.items.length>0;this._renderSystemStatusRow(h,"Index",k?"healthy":"missing",k?_.items.length+" entries":"formal-library.json not found");let D=((Ee=d==null?void 0:d.settings)==null?void 0:Ee.system_dir)||"System",S=this.app.vault.adapter.basePath,f=!1,y="No exports found";try{let E=Ne.join(S,D,"PaperForge","exports");if(ue.existsSync(E)){let P=ue.readdirSync(E).filter(M=>M.endsWith(".json"));f=P.length>0,y=f?P.length+" export(s)":"No JSON exports"}}catch(E){}this._renderSystemStatusRow(h,"Zotero Export",f?"healthy":"missing",y);let w=!!((Fe=d==null?void 0:d.settings)!=null&&Fe.paddleocr_api_key);if(!w)try{let E=((Te=d==null?void 0:d.settings)==null?void 0:Te.system_dir)||"System",P=Ne.join(S,E,"PaperForge",".env");if(ue.existsSync(P)){let z=ue.readFileSync(P,"utf-8").match(/^PADDLEOCR_API_TOKEN\s*=\s*(.+)$/m);w=!!(z&&z[1]&&z[1].trim())}}catch(E){}w||(w=!!(process.env.PADDLEOCR_API_TOKEN||process.env.PADDLEOCR_API_KEY||process.env.OCR_TOKEN)),this._renderSystemStatusRow(h,"OCR Token",w?"configured":"missing",w?"Configured":"Not set");let T=!1,R="",B=this.app.vault.adapter.basePath,A=rt(B);T=xt(B),R=A&&((v=A.summary)==null?void 0:v.reason)||A&&((C=A.summary)==null?void 0:C.status)||"Unknown",this._renderSystemStatusRow(h,"Memory Layer",T?"healthy":"fail",R);let V=!x&&b!=="\u2014";if(V||!k||!f||!w){let E=e.createEl("div",{cls:"paperforge-issue-summary"});E.createEl("div",{cls:"paperforge-section-label",text:"\u9700\u8981\u5904\u7406"});let P=E.createEl("div",{cls:"paperforge-issue-list"});V&&P.createEl("div",{cls:"paperforge-issue-item",text:"Runtime version mismatch"}),k||P.createEl("div",{cls:"paperforge-issue-item",text:"Index missing or corrupted"}),f||P.createEl("div",{cls:"paperforge-issue-item",text:"No Zotero export found"}),w||P.createEl("div",{cls:"paperforge-issue-item",text:"PaddleOCR API key not configured"});let M=E.createEl("div",{cls:"paperforge-issue-actions"}),z=M.createEl("button",{cls:"paperforge-contextual-btn"});z.createEl("span",{text:"Run Doctor"}),z.addEventListener("click",()=>{let G=X.find(ke=>ke.id==="paperforge-doctor");G&&this._runAction(G,z)});let Q=M.createEl("button",{cls:"paperforge-contextual-btn"});Q.createEl("span",{text:"Repair Issues"}),Q.addEventListener("click",()=>{let G=X.find(ke=>ke.id==="paperforge-repair");G&&this._runAction(G,Q)})}let O=e.createEl("div",{cls:"paperforge-global-actions"});O.createEl("div",{cls:"paperforge-section-label",text:"Start Working"});let J=O.createEl("div",{cls:"paperforge-global-actions-row"}),W=J.createEl("button",{cls:"paperforge-contextual-btn primary"});W.createEl("span",{cls:"paperforge-contextual-btn-icon",text:"\u{1F4C1}"}),W.createEl("span",{text:"Open Literature Hub"}),W.addEventListener("click",()=>{var M;let E=((M=d==null?void 0:d.settings)==null?void 0:M.base_dir)||"Bases",P=this.app.vault.getAbstractFileByPath(E);if(P){let z=null;if(P.children&&(z=P.children.find(Q=>Q.extension==="base")),z){let Q=this.app.workspace.getLeaf(!1);Q&&Q.openFile(z)}else new I.Notice("[!!] No .base file found in "+E,6e3)}else new I.Notice("[!!] Base directory not found: "+E,6e3)});let U=J.createEl("button",{cls:"paperforge-contextual-btn"});U.createEl("span",{cls:"paperforge-contextual-btn-icon",text:"\u21BB"}),U.createEl("span",{text:"Sync Library"}),U.addEventListener("click",()=>{let E=X.find(P=>P.id==="paperforge-sync");E&&this._runAction(E,U)});let te=J.createEl("button",{cls:"paperforge-contextual-btn"});te.createEl("span",{cls:"paperforge-contextual-btn-icon",text:"\u229E"}),te.createEl("span",{text:"Run OCR"}),te.addEventListener("click",()=>{let E=X.find(P=>P.id==="paperforge-ocr");E&&this._runAction(E,te)});let ne=J.createEl("button",{cls:"paperforge-contextual-btn"});ne.createEl("span",{cls:"paperforge-contextual-btn-icon",text:"\u2695"}),ne.createEl("span",{text:"Run Doctor"}),ne.addEventListener("click",()=>{let E=X.find(P=>P.id==="paperforge-doctor");E&&this._runAction(E,ne)});let ge=J.createEl("button",{cls:"paperforge-contextual-btn"});ge.createEl("span",{cls:"paperforge-contextual-btn-icon",text:"\u2139"}),ge.createEl("span",{text:"Refresh Status"}),ge.addEventListener("click",()=>{this._fetchStats(!1)});let re=J.createEl("button",{cls:"paperforge-contextual-btn warn"});re.createEl("span",{cls:"paperforge-contextual-btn-icon",text:"\u21BA"}),re.createEl("span",{text:"Redo OCR"}),re.addEventListener("click",()=>{let E=X.find(P=>P.id==="paperforge-ocr-redo");E&&this._runAction(E,re)});let he=J.createEl("button",{cls:"paperforge-contextual-btn"});he.createEl("span",{cls:"paperforge-contextual-btn-icon",text:"\u21BA"}),he.createEl("span",{text:"Repair Issues"}),he.addEventListener("click",()=>{let E=X.find(P=>P.id==="paperforge-repair");E&&this._runAction(E,he)})}_renderSystemStatusRow(e,t,r,n){let a=e.createEl("div",{cls:"paperforge-status-row"});a.createEl("span",{cls:"paperforge-status-dot"}).addClass(r==="healthy"||r==="configured"?"ok":"fail"),a.createEl("span",{cls:"paperforge-status-label",text:t}),a.createEl("span",{cls:"paperforge-status-detail",text:n||""})}_renderPaperMode(){let e=this._currentPaperEntry,t=this._currentPaperKey;if(!this._contentEl)return;if(!t){this._renderEmptyState(this._contentEl,"No paper data available.");return}if(!e){this._contentEl.createEl("div",{cls:"paperforge-content-placeholder",text:'Paper "'+t+'" not found in canonical index. Sync first.'});return}let r=this._contentEl.createEl("div",{cls:"paperforge-paper-view"}),n=r.createEl("div",{cls:"paperforge-paper-header"});n.createEl("div",{cls:"paperforge-paper-title",text:e.title||"Untitled"});let a=n.createEl("div",{cls:"paperforge-paper-meta"});e.authors&&e.authors.length>0&&a.createEl("span",{cls:"paperforge-paper-authors",text:e.authors.join(", ")}),e.year&&a.createEl("span",{cls:"paperforge-paper-year",text:String(e.year)});let s=r.createEl("div",{cls:"paperforge-status-strip"}),l=s.createEl("div",{cls:"paperforge-status-strip-left"}),o=s.createEl("div",{cls:"paperforge-status-strip-right"}),c=[{key:"pdf",label:"PDF",ok:e.has_pdf===!0},{key:"ocr",label:"OCR",ok:e.ocr_status==="done",pending:["pending","queued","processing"].includes(e.ocr_status||""),fail:["failed","blocked","done_incomplete","nopdf"].includes(e.ocr_status||"")},{key:"deep",label:"\u7CBE\u8BFB",ok:e.deep_reading_status==="done"}];for(let p of c){let h=l.createEl("span",{cls:"paperforge-status-pill"}),d="pending";p.ok?d="ok":p.fail?d="fail":p.pending&&(d="pending"),h.addClass(d);let m=p.ok?"\u2713":p.fail?"\u2717":"\u25CB";h.createEl("span",{cls:"paperforge-status-pill-icon",text:m}),h.createEl("span",{text:" "+p.label})}if(e.pdf_path){let p=o.createEl("button",{cls:"paperforge-contextual-btn"});p.createEl("span",{cls:"paperforge-contextual-btn-icon",text:"\u{1F4C4}"}),p.createEl("span",{text:"\u6253\u5F00 PDF"}),p.addEventListener("click",()=>{let h=e.pdf_path.match(/\[\[([^\]]+)\]\]/),d=h?h[1]:e.pdf_path;this.app.vault.getAbstractFileByPath(d)?this.app.workspace.openLinkText(d,""):new I.Notice("[!!] PDF not found: "+d,6e3)})}if(e.fulltext_path){let p=o.createEl("button",{cls:"paperforge-contextual-btn"});p.createEl("span",{cls:"paperforge-contextual-btn-icon",text:"\u{1F4DD}"}),p.createEl("span",{text:"\u6253\u5F00\u5168\u6587"}),p.addEventListener("click",()=>this._openFulltext(e.fulltext_path))}if(this._renderPaperOverviewCard(r,e),e.next_step==="ready"&&e.deep_reading_status==="done"){let p=r.createEl("div",{cls:"paperforge-complete-row"});p.createEl("span",{text:"\u2713"}),p.createEl("span",{text:"\u5DF2\u5B8C\u6210\uFF0C\u53EF\u76F4\u63A5\u4F7F\u7528"})}else this._renderNextStepCard(r,e,t);this._renderRecentDiscussionCard(r,e),this._renderPaperTechnicalDetails(r,e)}_renderPaperOverviewCard(e,t){let r=e.createEl("div",{cls:"paperforge-paper-overview"});r.createEl("div",{cls:"paperforge-paper-overview-header"}).createEl("span",{cls:"paperforge-paper-overview-title",text:"\u6587\u7AE0\u6982\u89C8"});let a=r.createEl("div",{cls:"paperforge-paper-overview-body"}),s=a.createEl("div",{cls:"paperforge-paper-overview-excerpt",text:"\u52A0\u8F7D\u4E2D..."});if(t.note_path){let l=this.app.vault.getAbstractFileByPath(t.note_path);l?this.app.vault.read(l).then(o=>{let c=this._extractOverviewFromNote(o);if(c){let p=c.length>200?c.slice(0,200)+"...":c;if(s.setText(p),c.length>200){let h=a.createEl("div",{cls:"paperforge-expand-container"}),d=h.createEl("button",{cls:"paperforge-expand-icon",title:"\u5C55\u5F00/\u6536\u8D77"});d.innerHTML='';let m=!1;h.addEventListener("click",()=>{s.setText(m?p:c),d.innerHTML=m?'':'',m=!m})}}else s.setText("\u5C1A\u672A\u751F\u6210\u6587\u7AE0\u6982\u89C8\u3002\u8FD0\u884C /pf-deep \u5F00\u59CB\u7CBE\u8BFB\u3002")}).catch(()=>{s.setText("\u65E0\u6CD5\u8BFB\u53D6\u7B14\u8BB0\u5185\u5BB9")}):s.setText("\u7B14\u8BB0\u6587\u4EF6\u4E0D\u5B58\u5728")}else s.setText("\u5C1A\u672A\u751F\u6210\u6587\u7AE0\u6982\u89C8")}_extractOverviewFromNote(e){if(!e)return null;let t=e.indexOf("## \u{1F50D} \u7CBE\u8BFB");if(t===-1)return null;let r=e.slice(t),n=["**\u4E00\u53E5\u8BDD\u603B\u89C8:**","**\u4E00\u53E5\u8BDD\u603B\u89C8**","**\u6587\u7AE0\u6458\u8981:**","**\u6587\u7AE0\u6458\u8981**"];for(let l of n){let o=r.indexOf(l);if(o!==-1){let c=r.slice(o+l.length),p=["**5 Cs","**Figure","**\u8BC1\u636E","### Pass 2","## "],h=c.length;for(let b of p){let x=c.indexOf(b);x!==-1&&x{t.createEl("button",{cls:"paperforge-settings-tab"+(a.id===this.activeTab?" paperforge-settings-tab--active":""),text:a.label}).addEventListener("click",()=>{this.activeTab=a.id,this.display()})}),r.forEach(a=>{n[a.id]=e.createDiv({cls:"paperforge-tab-content"+(a.id===this.activeTab?" paperforge-tab-content--active":"")})}),this.activeTab==="setup"?this._renderSetupTab(n.setup):this.activeTab==="features"?this._renderFeaturesTab(n.features):this.activeTab==="maintenance"?this._renderMaintenanceTab(n.maintenance):this._renderReleaseNotesTab(n["release-notes"])}_renderSetupTab(e){let t=this.app.vault.adapter.basePath;this.plugin.settings.vault_path||(this.plugin.settings.vault_path=t,this._debouncedSave()),this.plugin.settings.setup_complete&&(L.existsSync(Z.join(t,"paperforge.json"))||(this.plugin.settings.setup_complete=!1,this._debouncedSave())),e.createEl("h2",{text:i("header_title")||"PaperForge"}),e.createEl("p",{text:i("desc"),cls:"paperforge-settings-desc"});let n=e.createEl("div",{cls:"paperforge-setup-bar"}).createEl("span",{cls:"paperforge-setup-label"});this.plugin.settings.setup_complete?(n.setText(i("setup_done")),n.addClass("paperforge-setup-done")):(n.setText(i("setup_pending")),n.addClass("paperforge-setup-pending"));let a=this.app.vault.adapter.basePath,s=z(a,this.plugin.settings,void 0,void 0),l=s.path,o=this.plugin.settings._python_path_stale?"stale":s.source,c=new F.Setting(e).setName(i("field_python_interp")).setDesc(this._getPythonDesc(l,o));this._pythonInterpDescEl=c.descEl;let p=new F.Setting(e).setName(i("field_python_custom")).setDesc("");this._customPathDescEl=p.descEl,p.addText(S=>{S.setPlaceholder("e.g. C:\\Python310\\python.exe").setValue(this.plugin.settings.python_path||"").onChange(f=>{if(this.plugin.settings.python_path=f,this.plugin.saveSettings(),f&&f.trim()){let T=L.existsSync(f.trim());this.plugin.settings._python_path_stale=!T}else this.plugin.settings._python_path_stale=!1;let y=z(this.app.vault.adapter.basePath,this.plugin.settings,void 0,void 0),C=this.plugin.settings._python_path_stale?"stale":y.source;this._pythonInterpDescEl&&(this._pythonInterpDescEl.textContent=this._getPythonDesc(y.path,C))})}),p.addButton(S=>{S.setButtonText(i("btn_validate")).onClick(()=>this._validatePythonOverride())}),e.createEl("h3",{text:i("runtime_health")}),e.createEl("p",{text:i("runtime_health_desc"),cls:"paperforge-settings-desc"});let h=new F.Setting(e).setName("PaperForge").setDesc(i("runtime_health_checking")),d=h.descEl.createEl("span",{cls:"paperforge-runtime-badge"}),m=null;h.addButton(S=>{m=S,S.setButtonText(i("runtime_health_sync")).setDisabled(!0).onClick(()=>this._syncRuntime(S))});{let S=this.app.vault.adapter.basePath,{path:f,extraArgs:y=[]}=z(S,this.plugin.settings,void 0,void 0),C=this.plugin.manifest.version||"?";(0,$.execFile)(f,[...y,"-c","import paperforge; print(paperforge.__version__)"],{cwd:S,timeout:1e4},(T,R)=>{let B=this.plugin.settings.setup_complete,A=!T&&R?R.trim():null,V=A?`${i("runtime_health_plugin_ver").replace("{0}",C)} \u2192 ${i("runtime_health_package_ver").replace("{0}",A)}`:B?`Plugin v${C} \u2192 Python package not installed. Click "Sync Runtime" to install.`:`Plugin v${C} \u2192 Not configured. Please open the setup wizard first.`;h.setDesc(V),A===C?(d.setText(i("runtime_health_match")),d.className="paperforge-runtime-badge match",m&&m.setDisabled(!0)):A?(d.setText(i("runtime_health_mismatch")),d.className="paperforge-runtime-badge mismatch",m&&m.setDisabled(!1)):(d.setText(B?"Not installed":"Setup needed"),d.className="paperforge-runtime-badge missing",m&&m.setDisabled(!1))})}e.createEl("h3",{text:i("section_prep")}),e.createEl("p",{text:i("section_prep_desc"),cls:"paperforge-settings-desc"});let b=e.createEl("div",{cls:"paperforge-guide"}),x=[["prep_python","prep_python_desc"],["prep_zotero","prep_zotero_desc"],["prep_bbt","prep_bbt_desc"],["prep_key","prep_key_desc"]];for(let[S,f]of x){let y=b.createEl("div",{cls:"paperforge-guide-item"});y.createEl("strong",{text:i(S)}),y.createEl("span",{text:" \u2014 "+i(f)})}this._checkEl=e.createEl("div",{cls:"paperforge-message"});let _=!this.plugin.settings.setup_complete;new F.Setting(e).setName(i(_?"btn_install":"btn_reconfig")).setDesc(i(_?"btn_install_desc":"btn_reconfig_desc")).addButton(S=>{S.setButtonText(i(_?"btn_install":"btn_reconfig")).setCta().onClick(()=>{_?this._preCheck(()=>{new Le(this.app,this.plugin).open()}):new Le(this.app,this.plugin).open()})}),e.createEl("h3",{text:i("section_guide")});let w=e.createEl("div",{cls:"paperforge-guide"}),D=[["guide_open","guide_open_desc"],["guide_sync","guide_sync_desc"],["guide_ocr","guide_ocr_desc"]];for(let[S,f]of D){let y=w.createEl("div",{cls:"paperforge-guide-item"});y.createEl("strong",{text:i(S)}),y.createEl("span",{text:" \u2014 "+i(f)})}if(this.plugin.settings.setup_complete){e.createEl("h3",{text:i("section_config")});let S=e.createEl("div",{cls:"paperforge-summary"}),f=this.plugin.settings,y=this._pfConfig,C=[{label:i("dir_vault"),val:t},{label:i("dir_resources"),val:`${t}/${y==null?void 0:y.resources_dir}`},{label:" "+i("dir_notes"),val:`${t}/${y==null?void 0:y.resources_dir}/${y==null?void 0:y.literature_dir}`},{label:i("dir_base"),val:`${t}/${y==null?void 0:y.base_dir}`},{label:i("dir_system"),val:`${t}/${y==null?void 0:y.system_dir}`},{label:"API Key",val:f.paddleocr_api_key?i("api_key_set"):i("api_key_missing")},{label:i("field_zotero_data"),val:f.zotero_data_dir||i("not_set")}];for(let T of C){let R=S.createEl("div",{cls:"paperforge-summary-row"});R.createEl("span",{cls:"paperforge-summary-label",text:T.label}),R.createEl("span",{cls:"paperforge-summary-value",text:T.val})}}}_execMemoryStatus(e,t,r){(0,$.exec)(`"${e}" -m paperforge --vault "${t}" memory status --json`,{encoding:"utf-8",timeout:15e3},(n,a)=>{if(n){r("Status unavailable");return}try{let s=JSON.parse(a);if(s.ok){let l=s.data,o=l.fresh?"fresh":"stale";r(`Papers: ${l.paper_count_db} | ${o}${l.needs_rebuild?" - needs rebuild":""}`)}else r("DB not found. Run paperforge memory build.")}catch(s){r("Could not parse status.")}})}_execEmbedStatus(e,t,r){(0,$.exec)(`"${e}" -m paperforge --vault "${t}" embed status --json`,{encoding:"utf-8",timeout:15e3},(n,a)=>{if(n){r("Status unavailable");return}try{let s=JSON.parse(a);s.ok?r(`Chunks: ${s.data.chunk_count} | ${s.data.model} | ${s.data.mode}`):r("Could not parse status.")}catch(s){r("Could not parse status.")}})}_callPython(e,t){let r=this.app.vault.adapter.basePath,n=de(r,this.plugin.settings),a=[...n.extraArgs,"-m","paperforge","--vault",r,...e];if(t&&t.stream){let s=(0,$.spawn)(n.path,a,{cwd:r,env:t.env||process.env,windowsHide:!0});return t.onData&&s.stdout.on("data",t.onData),t.onStderr&&s.stderr.on("data",t.onStderr),t.onError&&s.on("error",t.onError),s.on("close",t.onClose),s}return(0,$.execFile)(n.path,a,{cwd:r,timeout:t&&t.timeout||6e4},(s,l,o)=>{t&&t.onClose&&t.onClose(s?1:0,l,o)}),null}_renderMemoryStatusText(e,t,r){if(e.innerHTML="",e.createEl("span",{text:t,cls:"paperforge-memory-text"}).style.cssText="flex:1;",r==="syncing"){let s=e.createEl("span",{text:"Syncing...",cls:"paperforge-sync-status"});s.style.cssText="opacity:0.7; margin-right:8px;"}else if(r){let s=e.createEl("span",{text:r,cls:"paperforge-sync-status"});s.style.cssText="opacity:0.7; margin-right:8px;"}let n=e.createEl("button",{cls:"paperforge-rebuild-btn",text:i("feat_memory_rebuild_btn")});n.style.cssText="margin-left:auto; border:1px solid var(--background-modifier-border); background:var(--background-secondary); cursor:pointer; font-size:11px; padding:2px 6px; border-radius:3px; margin-right:4px;",n.title="Rebuild memory database",n.onclick=()=>{let s=this.app.vault.adapter.basePath,l=de(s,this.plugin.settings);if(!l.path){new F.Notice(i("feat_no_python"));return}console.log("[PaperForge] Rebuilding memory:",l.path),n.setText(i("feat_memory_rebuilding")),n.setAttr("disabled",""),this._callPython(["memory","build"],{timeout:6e4,onClose:(o,c,p)=>{console.log("[PaperForge] memory build exit:",o?"FAIL:"+o:"OK",(c||"").slice(0,200),(p||"").slice(0,200)),n.setText(i("feat_memory_rebuild_btn")),n.removeAttribute("disabled"),o===0?new F.Notice(i("feat_memory_rebuild_done")):new F.Notice(i("feat_memory_rebuild_failed")+(p?" "+p.slice(0,80):"")),this._memoryStatusText=je(s),this._refreshSnapshots(s)}})};let a=e.createEl("button",{cls:"paperforge-refresh-btn",text:"\u21BB"});a.style.cssText="border:none; background:none; cursor:pointer; font-size:16px; padding:0 4px;",a.title="Sync now",a.onclick=()=>{this._memoryStatusText=null,this._runManualSync()}}_getBuildCommand(e){let t=this.app.vault.adapter.basePath,r=z(t,e,void 0,void 0);return r.path?`"${r.path}" -m paperforge --vault "${t}" sync`:null}_runManualSync(){let e=this.app.vault.adapter.basePath;if(!de(e,this.plugin.settings).path)return;let r=document.querySelector(".paperforge-memory-status");r&&this._renderMemoryStatusText(r,"Checking...","syncing"),this.plugin._autoSyncRunning=!0,this._callPython(["sync"],{timeout:12e4,onClose:n=>{this.plugin._autoSyncRunning=!1,this._memoryStatusText=null,n===0&&(this._lastSyncTime=new Date().toLocaleTimeString(),this.plugin._lastSyncTime=this._lastSyncTime),this.display(),this._refreshSnapshots(e),He(this.app,this.plugin,e)}})}_refreshSnapshots(e){let t=de(e,this.plugin.settings),r=[...t.extraArgs,"-m","paperforge","--vault",e,"runtime-health","--json"];this._refreshPending=!0,(0,$.execFile)(t.path,r,{cwd:e,timeout:3e4,windowsHide:!0},(n,a,s)=>{this._refreshPending=!1,this._memoryStatusText=je(e),this._embedStatusText=we(e),this.display()})}_renderFeaturesTab(e){e.createEl("h3",{text:"Skills"});let t=e.createEl("div",{cls:"paperforge-desc-box"});t.style.cssText="padding:8px 12px; margin:0 0 12px; background:var(--background-secondary); border-radius:4px; font-size:12px; color:var(--text-muted); line-height:1.5;",t.setText(i("feat_skills_desc")),t.createEl("br"),t.createEl("span",{text:i("feat_skills_system"),cls:""}).style.opacity="0.7";let r={opencode:"OpenCode",claude:"Claude Code",codex:"Codex",cursor:"Cursor",windsurf:"Windsurf",github_copilot:"GitHub Copilot",gemini:"Gemini CLI"},n={opencode:".opencode/skills",claude:".claude/skills",codex:".codex/skills",cursor:".cursor/skills",windsurf:".windsurf/skills",github_copilot:".github/skills",gemini:".gemini/skills"},a=this.app.vault.adapter.basePath,s=this.plugin.settings.selected_skill_platform||"opencode";new F.Setting(e).setName(i("feat_agent_platform")).setDesc(i("feat_agent_platform_desc")).addDropdown(f=>{Object.entries(r).forEach(([y,C])=>f.addOption(y,C)),f.setValue(s).onChange(y=>{this.plugin.settings.selected_skill_platform=y,this.plugin.saveSettings(),this.display()})}).addExtraButton(f=>{f.setIcon("folder").setTooltip("Open skills folder").onClick(()=>{let y=n[s]||".opencode/skills",C=Z.join(a,y);L.existsSync(C)?(0,$.exec)(`start "" "${C}"`):new F.Notice(`Skills folder not found: ${y}`)})});let l=Z.join(a,n[s]),o=[],c=[];L.existsSync(l)&&L.readdirSync(l,{withFileTypes:!0}).forEach(f=>{if(!f.isDirectory())return;let y=Z.join(l,f.name,"SKILL.md");if(!L.existsSync(y))return;let C=L.readFileSync(y,"utf-8"),T=C.match(/^name:\s*(.+)$/m),R=C.split(`
+`),B=R.findIndex(W=>/^description:/.test(W)),A="";if(B>=0){let W=R[B].match(/^description:\s*(.+)$/);if(W&&W[1]&&W[1]!==">"&&W[1]!=="|-"&&W[1]!=="|")A=W[1].trim();else{for(let U=B+1;U{if(y.length===0)return;let T=p.createEl("div",{cls:"paperforge-skills-group"}),R=T.createEl("div",{cls:"paperforge-skills-collapse-header"}),B=T.createEl("div",{cls:"paperforge-skills-collapse-content"}),A=R.createEl("span",{text:"\u25BC",cls:"paperforge-skills-arrow"});A.style.cssText="display:inline-block; font-size:10px; margin-right:6px; transition:transform 0.2s; transform:rotate(0deg);",R.createEl("h4",{text:`${f} (${y.length})`,cls:"paperforge-skills-subheader"}),y.forEach(O=>{let J=O.name+(O.version?" v"+O.version:""),W=C?" [system]":" [user]",U=O.desc||"",te=new F.Setting(B).setName(J+W).setDesc(U);te.settingEl.style.opacity=O.disabled?"0.4":"1",te.addToggle(ne=>{ne.setValue(!O.disabled).onChange(ge=>{let re=!ge,fe=O.content.match(/^disable-model-invocation:\s*(.+)$/m)?O.content.replace(/^disable-model-invocation:\s*.+$/m,`disable-model-invocation: ${re}`):O.content.replace(/^(---\r?\n)/,`$1disable-model-invocation: ${re}
+`);L.writeFileSync(O.path,fe,"utf-8"),O.disabled=re,O.content=fe,te.settingEl.style.opacity=O.disabled?"0.4":"1"})})});let V=C?"system":"user";(this._skillsCollapsed[V]||!1)&&(B.style.display="none",A.style.transform="rotate(-90deg)"),R.addEventListener("click",()=>{B.style.display!=="none"?(B.style.display="none",A.style.transform="rotate(-90deg)"):(B.style.display="",A.style.transform="rotate(0deg)"),this._skillsCollapsed[V]=B.style.display==="none"})};h("System Skills",o,!0),h("User Skills",c,!1),o.length===0&&c.length===0&&p.createEl("p",{text:`No skills found in ${n[s]}. Run setup to deploy skills.`,cls:"setting-item-description"}),this._advCollapsed===void 0&&(this._advCollapsed=!0);let d=e.createEl("div",{cls:"paperforge-collapsible-header"});d.style.cssText="cursor:pointer; display:flex; align-items:center; gap:8px; padding:8px 0; user-select:none;";let m=d.createEl("span",{text:"\u25B6",cls:"paperforge-collapsible-arrow"});m.style.cssText="display:inline-block; transition:transform 0.2s; font-size:10px; transform:"+(this._advCollapsed?"rotate(0deg)":"rotate(90deg)")+";";let b=d.createEl("span",{text:"Advanced"});b.style.cssText="font-size:16px; font-weight:700; line-height:1.4;";let x=d.createEl("span",{text:"Memory + Vector DB + Embedding"});x.style.cssText="font-size:12px; color:var(--text-muted); margin-left:10px;";let _=e.createEl("div",{cls:"paperforge-collapsible-content"});_.style.display=this._advCollapsed?"none":"",d.addEventListener("click",()=>{this._advCollapsed=!this._advCollapsed,_.style.display=this._advCollapsed?"none":"",m.style.transform=this._advCollapsed?"rotate(0deg)":"rotate(90deg)"}),_.createEl("h4",{text:"Memory Layer"});let w=_.createEl("div",{cls:"paperforge-desc-box"});w.style.cssText="padding:8px 12px; margin:0 0 12px; background:var(--background-secondary); border-radius:4px; font-size:12px; color:var(--text-muted); line-height:1.5;",w.setText(i("feat_memory_desc"));let D=_.createEl("div",{cls:"paperforge-memory-status"});D.style.cssText="display:flex; align-items:center; padding:8px 12px; margin:8px 0; background:var(--background-secondary); border-radius:4px;";let S=this.app.vault.adapter.basePath;this.plugin._lastSyncTime&&!this._lastSyncTime&&(this._lastSyncTime=this.plugin._lastSyncTime),this._memoryStatusText===null&&(this._memoryStatusText=je(S)),this._renderMemoryStatusText(D,this._memoryStatusText,this._lastSyncTime),this._renderVectorSection(_)}_renderVectorSection(e){var o;e.createEl("h4",{text:"Vector Database"}),this.plugin.settings.features||(this.plugin.settings.features={memory_layer:!0,vector_db:!1});let t=e.createEl("div",{cls:"paperforge-desc-box"});if(t.style.cssText="padding:8px 12px; margin:0 0 8px; background:var(--background-secondary); border-radius:4px; font-size:12px; color:var(--text-muted); line-height:1.5;",t.setText(i("feat_vector_desc")),new F.Setting(e).setName(i("feat_vector_enable")).setDesc(i("feat_vector_enable_desc")).addToggle(c=>{c.setValue(!!this.plugin.settings.features.vector_db).onChange(p=>{this.plugin.settings.features.vector_db=p,this.plugin.saveSettings(),this._vectorDepsOk=null,this._embedStatusText=null,this.display()})}),!this.plugin.settings.features.vector_db)return;let r=this.app.vault.adapter.basePath,n=e.createEl("div",{cls:"paperforge-skills-collapse-header"});n.style.cssText="display:flex; align-items:center; cursor:pointer; padding:6px 0 2px; margin:0;";let a=n.createEl("span",{text:"\u25BC"});a.style.cssText="display:inline-block; font-size:10px; margin-right:6px; transition:transform 0.2s;",n.createEl("span",{text:i("feat_vector_config_label"),cls:""}).style.cssText="font-size:12px; color:var(--text-muted);";let s=e.createEl("div",{cls:"paperforge-vector-config"}),l=c=>{s.style.display=c?"none":"",a.style.transform=c?"rotate(-90deg)":"rotate(0deg)"};if(l(st(this._featurePanelsCollapsed,"vectorConfig",!1)),n.addEventListener("click",()=>{let c=Et(this._featurePanelsCollapsed,"vectorConfig",!1);l(c)}),this._vectorDepsOk===!0){this._renderVectorReady(s,r);return}if(this._vectorDepsOk===!1){this._renderVectorNoDeps(s);return}if(this._vectorDepsOk===null){let c=Oe(r);this._vectorDepsOk=c&&(o=c.deps_installed)!=null?o:!1,this._vectorDepsOk&&(this._embedStatusText=we(r)),this.display()}}_renderApiConfig(e){new F.Setting(e).setName(i("feat_openai_key")).setDesc(i("feat_openai_key_desc")).addText(t=>{t.setPlaceholder("sk-...").setValue(this.plugin.settings.vector_db_api_key||"").onChange(r=>{this.plugin.settings.vector_db_api_key=r,this.plugin.saveSettings()})}),new F.Setting(e).setName(i("feat_api_base_url")).setDesc(i("feat_api_base_url_desc")).addText(t=>{t.setPlaceholder("https://api.openai.com/v1").setValue(this.plugin.settings.vector_db_api_base||"").onChange(r=>{this.plugin.settings.vector_db_api_base=r,this.plugin.saveSettings()})}),new F.Setting(e).setName(i("feat_api_model")).setDesc(i("feat_api_model_desc")).addText(t=>{t.setPlaceholder("text-embedding-3-small").setValue(this.plugin.settings.vector_db_api_model||"text-embedding-3-small").onChange(r=>{this.plugin.settings.vector_db_api_model=r,this.plugin.saveSettings()})})}_renderVectorNoDeps(e){let t=e.createEl("div");t.style.cssText="padding:8px 12px; margin:8px 0; background:var(--background-secondary); border-radius:4px;",t.setText(i("feat_deps_missing")),new F.Setting(e).setName(i("feat_install_deps")).setDesc(i("feat_install_deps_desc")).addButton(r=>{r.setButtonText(i("feat_install_btn")).setCta().onClick(async()=>{let n=this.app.vault.adapter.basePath,a=de(n,this.plugin.settings);if(!a.path){new F.Notice(i("feat_no_python"));return}r.setButtonText(i("feat_installing")),r.setDisabled(!0);let s="chromadb openai",l=new F.Notice(i("feat_installing_pkgs").replace("{pkgs}",s),0);try{let o=Object.assign({},process.env,{PYTHONIOENCODING:"utf-8",PYTHONUTF8:"1"}),c=s.split(" ");await new Promise((p,h)=>{(0,$.execFile)(a.path,[...a.extraArgs,"-m","pip","install",...c],{cwd:n,timeout:3e5,env:o,windowsHide:!0},d=>{d?h(d):p()})}),l.hide(),new F.Notice(i("feat_install_done")),this._vectorDepsOk=!0,this._embedStatusText=we(n),this.display()}catch(o){l.hide(),new F.Notice(i("feat_install_failed")+(o.stderr||o.message||o)),r.setButtonText(i("feat_retry_btn")),r.setDisabled(!1)}})})}_renderVectorReady(e,t){let r=e.createEl("div");r.style.cssText="padding:8px 12px; margin:8px 0; background:var(--background-secondary); border-radius:4px;",r.setText(we(t)),this._renderApiConfig(e);let n=e.createEl("div");n.style.cssText="padding:4px 0;";let a=n.createEl("div");a.style.cssText="display:flex; align-items:center; justify-content:space-between; margin-bottom:8px;",a.createEl("span",{text:i("feat_rebuild_vectors"),cls:"setting-item-name"});let s=n.createEl("div");s.style.cssText="display:flex; align-items:center; gap:8px;";let l=n.createEl("div",{cls:"paperforge-embed-status-text"});(()=>{var b;s.empty(),l.empty();let c=(Oe(t)||{}).build_state||{};this.plugin._embedProgress=this.plugin._embedProgress||{current:0,total:0,key:""},!this.plugin._embedProcess&&c.status==="running"&&(this.plugin._embedProgress={current:c.current||0,total:c.total||1,key:c.paper_id||""});let{current:p,total:h,key:d}=this.plugin._embedProgress;if(!!this.plugin._embedProcess||c.status==="running"){let x=s.createEl("div",{cls:"paperforge-progress-track"});x.style.cssText="flex:1;";let _=h>0?(p/h*100).toFixed(1):"0",w=x.createEl("div",{cls:"paperforge-progress-seg done"});if(w.style.cssText=`width:${_}%; min-width:${p>0?"2px":"0"};`,p{this._callPython(["embed","stop","--json"],{timeout:8e3}),this.plugin._embedProcess&&(this.plugin._embedProcess.kill(),this.plugin._embedProcess=null),this.display()})}else{let x=Oe(t),_=!!(x&&((b=x.chunk_count)!=null?b:0)>0),w=x&&x.corrupted,D=f=>{if(!de(t,this.plugin.settings).path){new F.Notice(i("feat_no_python"));return}let C=Object.assign({},process.env,{PYTHONIOENCODING:"utf-8",PYTHONUTF8:"1",VECTOR_DB_API_KEY:this.plugin.settings.vector_db_api_key||"",VECTOR_DB_API_BASE:this.plugin.settings.vector_db_api_base||"",VECTOR_DB_API_MODEL:this.plugin.settings.vector_db_api_model||""});this.plugin._embedStderr="",this.plugin._embedProgress={current:0,total:0,key:""},this.plugin._embedProcess=this._callPython(["embed","build",f],{stream:!0,env:C,onData:T=>{let R=T.toString("utf-8").split(`
+`);for(let B of R)if(B.startsWith("EMBED_START:"))this.plugin._embedProgress.total=parseInt(B.split(":")[1])||0;else if(B.startsWith("EMBED_PROGRESS:")){let A=B.split(":");this.plugin._embedProgress.current=parseInt(A[1])||0,this.plugin._embedProgress.key=A[3]||""}else B.startsWith("EMBED_DONE")&&(this.plugin._embedProcess=null,this.plugin._embedProgress.current=this.plugin._embedProgress.total);this.display()},onStderr:T=>{this.plugin._embedStderr||(this.plugin._embedStderr=""),this.plugin._embedStderr+=T.toString("utf-8")},onError:T=>{this.plugin._embedProcess=null,new F.Notice(i("feat_build_failed")+": "+(T.message||T)),this.display()},onClose:T=>{if(this.plugin._embedProcess=null,T===0)this.plugin._embedProgress.current=this.plugin._embedProgress.total,this.plugin.saveSettings(),this._embedStatusText=we(t),new F.Notice(i("feat_build_complete"));else{this._embedStatusText=null;let R=(this.plugin._embedStderr||"").slice(0,200);new F.Notice(i("feat_build_failed")+(R?": "+R:""),8e3)}this.plugin._embedStderr="",this.display(),this._refreshSnapshots(t)}}),this.display()};if(w){let f=n.createEl("div");f.style.cssText="padding:8px 12px; margin:8px 0; background:var(--background-modifier-warning); border-radius:4px; font-size:12px; display:flex; align-items:center; justify-content:space-between;",f.createEl("span",{text:i("feat_vector_corrupted")});let y=f.createEl("button",{text:i("feat_vector_rebuild_force_btn")});y.className="mod-cta",y.addEventListener("click",()=>D("--force"))}_&&!w&&s.createEl("span",{text:x.chunk_count+" chunks embedded",cls:"setting-item-description"});let S=s.createEl("button");if(S.setText(_?i("feat_rebuild_btn"):i("feat_build_btn")),S.addClass("mod-cta"),S.addEventListener("click",()=>D("--resume")),!w&&_){let f=s.createEl("button");f.setText(i("feat_vector_rebuild_force_btn")),f.style.marginLeft="6px",f.addEventListener("click",()=>D("--force"))}}})()}_getCurrentModelKey(){return this.plugin.settings.vector_db_api_model||"text-embedding-3-small"}_parseEmbedStatus(e){let t={};return e&&(e.split(`
+`).forEach(r=>{let n=r.match(/^\s*([^:]+):\s*(.*)/);n&&(t[n[1].trim()]=n[2].trim())}),t.db_exists!==void 0&&(t.db_exists=t.db_exists==="True"),t.chunk_count!==void 0&&(t.chunk_count=parseInt(t.chunk_count,10)||0)),t}_getPythonDesc(e,t){return t==="stale"?`[!!] ${e} (stale \u2014 path no longer exists, update or clear the override below)`:t==="manual"?`${e} (manual)`:`${e} (auto-detected)`}_refreshPythonInterpDesc(e,t){let r=this._pythonInterpDescEl;r&&(t==="stale"?r.textContent=`[!!] ${e} (stale \u2014 path no longer exists, update or clear the override below)`:t==="manual"?r.textContent=`${e} (manual)`:r.textContent=`${e} (auto-detected)`)}_validatePythonOverride(){let e=this.plugin.settings.python_path?this.plugin.settings.python_path.trim():"",t=this._customPathDescEl;if(!e){let r="\u8BF7\u8F93\u5165\u8DEF\u5F84 / Enter a path first";t&&(t.innerHTML=`\u2717 ${r}`),new F.Notice(r);return}if(!L.existsSync(e)){let r="\u8DEF\u5F84\u4E0D\u5B58\u5728 / Path does not exist";t&&(t.innerHTML=`\u2717 ${r}`),new F.Notice(r,4e3);return}try{L.accessSync(e,L.constants.X_OK)}catch(r){let n="\u4E0D\u53EF\u6267\u884C / Not executable";t&&(t.innerHTML=`\u2717 ${n}`),new F.Notice(n,4e3);return}(0,$.execFile)(e,["--version"],{timeout:8e3},(r,n)=>{if(r||!n){let o="\u65E0\u6CD5\u8FD0\u884C / Cannot run";t&&(t.innerHTML=`\u2717 ${o}`),new F.Notice(o,4e3);return}let a=n.match(/Python (\d+)\.(\d+)/);if(!a){let o="\u65E0\u6CD5\u89E3\u6790\u7248\u672C / Cannot parse version";t&&(t.innerHTML=`\u2717 ${o}`),new F.Notice(o,4e3);return}let s=parseInt(a[1],10),l=parseInt(a[2],10);if(s<3||s===3&&l<10){let o="Python \u7248\u672C\u8FC7\u4F4E\uFF0C\u9700\u8981 3.10+ / Python version too low, need 3.10+";t&&(t.innerHTML=`\u2717 ${o}`),new F.Notice(o,4e3);return}(0,$.execFile)(e,["-m","pip","--version"],{timeout:8e3},o=>{if(o){let c=`\u2713 Python ${s}.${l} \u6709\u6548\uFF0C\u4F46\u672A\u68C0\u6D4B\u5230 pip / Valid, but pip not found`;t&&(t.innerHTML=`\u26A0 ${c}`),new F.Notice(c,4e3)}else{let c=`\u2713 Python ${s}.${l} \u6709\u6548 / Valid`;t&&(t.innerHTML=`${c}`),new F.Notice(c,4e3)}})})}_syncRuntime(e){let t=this.app.vault.adapter.basePath,{path:r,extraArgs:n=[]}=z(t,this.plugin.settings,void 0,void 0),a=this.plugin.manifest.version,s=mt(r,a,n);e.setDisabled(!0),e.setButtonText(i("runtime_health_syncing"));let l=(c,p)=>(console.log(`[PaperForge] Sync Runtime: trying ${p}`),yt(s.cmd,c,t,s.timeout,void 0,be())),o=()=>{let c="opencode";try{let m=L.readFileSync(Z.join(t,"paperforge.json"),"utf-8"),b=JSON.parse(m);b.agent_key&&(c=b.agent_key)}catch(m){}let p=[...n,"-c",'from paperforge.services.skill_deploy import deploy_skills; from pathlib import Path; r=deploy_skills(vault=Path(r"'+t.replace(/\\/g,"\\\\")+'"), agent_key="'+c+'", overwrite=True); print("skills deployed" if r["skill_deployed"] else "skills skipped", flush=True)'],h=(0,$.spawn)(r,p,{cwd:t,timeout:3e4,windowsHide:!0}),d="";h.stdout.on("data",m=>{d+=m.toString("utf-8")}),h.on("close",m=>{console.log(`[PaperForge] Skill deploy: ${d.trim()} (exit ${m})`)})};l(s.pypiArgs,"PyPI").then(c=>{if(c.exitCode===0){console.log("[PaperForge] Sync Runtime: installed via PyPI"),o(),new F.Notice(i("runtime_health_sync_done").replace("{0}",a),5e3),this.display();return}console.warn("[PaperForge] Sync Runtime: PyPI failed, falling back to git..."),l(s.gitArgs,"git").then(p=>{p.exitCode===0?(console.log("[PaperForge] Sync Runtime: installed via git"),o(),new F.Notice(i("runtime_health_sync_done").replace("{0}",a),5e3),this.display()):(e.setDisabled(!1),e.setButtonText(i("runtime_health_sync")),console.error("[PaperForge] git fallback stderr:",p.stderr),new F.Notice(i("runtime_health_sync_fail").replace("{0}","pip exit code "+p.exitCode),8e3))})})}_debouncedSave(){clearTimeout(this._saveTimeout),this._saveTimeout=setTimeout(()=>this.plugin.saveSettings(),500)}_preCheck(e){var a;let t=this.app.vault.adapter.basePath,{path:r,extraArgs:n=[]}=z(t,(a=this.plugin)==null?void 0:a.settings,void 0,void 0);(0,$.execFile)(r,[...n,"--version"],{timeout:8e3},(s,l)=>{let o=[];o.push({label:"Python",ok:!s,detail:s?i("check_python_fail"):l.trim()});let c=!1,p=process.env.HOME||process.env.USERPROFILE||Ke.homedir()||"";if(process.platform==="darwin")c=["/Applications/Zotero.app",Z.join(p,"Applications","Zotero.app")].some(w=>{try{return L.existsSync(w)}catch(D){return!1}});else if(process.platform==="win32"){let _=process.env.ProgramFiles||"",w=process.env.LOCALAPPDATA||"";c=[Z.join(_,"Zotero"),Z.join(_,"(x86)","Zotero"),Z.join(w,"Programs","Zotero"),Z.join(w,"Zotero"),Z.join(p,"AppData","Local","Programs","Zotero")].filter(Boolean).some(S=>{try{return L.existsSync(S)}catch(f){return!1}})}else c=[Z.join(p,".local","share","zotero","zotero"),"/usr/bin/zotero","/usr/local/bin/zotero"].some(w=>{try{return L.existsSync(w)}catch(D){return!1}});let h=this.plugin.settings.zotero_data_dir;if(!c&&h)try{c=L.existsSync(h)}catch(_){}o.push({label:"Zotero",ok:c,detail:c?i("check_zotero_ok"):i("check_zotero_fail")});let d=!1,m=process.env.APPDATA||"";process.platform==="win32"&&m&&(d=$e(Z.join(m,"Zotero","Zotero","Profiles"))),!d&&process.platform==="darwin"&&p&&(d=$e(Z.join(p,"Library","Application Support","Zotero","Profiles"))),!d&&process.platform!=="win32"&&process.platform!=="darwin"&&p&&(d=$e(Z.join(p,".zotero","zotero","Profiles"))),!d&&h&&String(h).trim()&&(d=et(h.trim())),!d&&p&&(d=et(Z.join(p,"Zotero"))),o.push({label:"Better BibTeX",ok:d,detail:d?i("check_bbt_ok"):i("check_bbt_fail")});let b={true:"\u2713",false:"\u2717"};if(this._checkEl){this._checkEl.setText(o.map(w=>`${b[String(w.ok)]} ${w.label}: ${w.detail}`).join(`
+`));let _=o.some(w=>!w.ok);this._checkEl.className=`paperforge-message msg-${_?"error":"ok"}`}let x=o.filter(_=>!_.ok);x.length>0&&new F.Notice(`[!!] \u672A\u901A\u8FC7: ${x.map(_=>_.label).join(", ")}`,6e3),e()})}_renderMaintenanceTab(e){e.createEl("h2",{text:i("tab_maintenance")||"\u7EF4\u62A4"});let t=this.app.vault.adapter.basePath,r=z(t,this.plugin.settings,L,$.execFileSync);if(!r.path){e.createEl("p",{text:"\u26A0 Python \u672A\u914D\u7F6E\uFF0C\u8BF7\u5148\u5728\u201C\u5B89\u88C5\u201D\u6807\u7B7E\u9875\u914D\u7F6E\u3002",cls:"setting-item-description"});return}let n=e.createEl("div");n.createEl("p",{text:"\u6B63\u5728\u52A0\u8F7D OCR \u7EF4\u62A4\u6570\u636E\u2026"});let a=Z.join(Ke.tmpdir(),`pf_ocr_maintenance_${Date.now()}.json`),s=["-m","paperforge","ocr","list","--json","--output",a];(0,$.execFile)(r.path,s,{cwd:t,timeout:3e4,windowsHide:!0},(l,o,c)=>{if(n.empty(),!L.existsSync(a)){n.createEl("p",{text:"\u274C \u65E0\u6CD5\u52A0\u8F7D OCR \u6570\u636E\u3002\u8BF7\u786E\u4FDD\u5DF2\u5B89\u88C5 paperforge \u5E76\u8FD0\u884C\u8FC7 OCR\u3002",cls:"setting-item-description"});return}let p=[];try{p=JSON.parse(L.readFileSync(a,"utf-8"))}catch(v){p=[]}try{L.unlinkSync(a)}catch(v){}if(!p.length){n.createEl("p",{text:"\u6CA1\u6709 OCR \u8BBA\u6587\u3002\u8BF7\u5148\u8FD0\u884C OCR\u3002"});return}let h=p.map(v=>({row:v,ui:St(v)})),d=Pt(h.map(v=>v.ui));n.empty();let m=n.createEl("div",{cls:"pf-maint-hero pf-card"});m.createEl("h3",{text:d.tone==="warn"?i("ocr_maint_hero_warn").replace("{rebuild}",String(d.counts.rebuild)).replace("{failed}",String(d.counts.failed)):i("ocr_maint_hero_ok")}),m.createEl("p",{text:i("ocr_maint_hero_note"),cls:"setting-item-description"});let b=m.createEl("div",{cls:"pf-maint-counts"});for(let[v,k]of[[i("ocr_maint_no_action"),d.counts.ok],[i("ocr_maint_rebuild"),d.counts.rebuild],[i("ocr_maint_failed"),d.counts.failed]]){let E=b.createEl("div",{cls:"pf-maint-stat"});E.createEl("strong",{text:String(k)}),E.createEl("span",{text:v})}let x=h.filter(v=>v.ui.category==="rebuild"||v.ui.category==="failed");if(x.length>0){n.createEl("h3",{text:i("ocr_maint_needs_attention")});let v=n.createEl("div",{cls:"pf-maint-section"});for(let k of x){let E=v.createEl("div",{cls:"pf-maint-card"});E.createEl("strong",{text:k.row.title_short||k.row.title||k.row.key});let P=E.createEl("span",{cls:"pf-maint-chip pf-maint-chip--"+k.ui.category,text:k.ui.label});P.style.marginLeft="8px",E.createEl("p",{text:k.ui.reason,cls:"setting-item-description"});let N=E.createEl("button",{text:k.ui.primaryAction==="rebuild"?i("ocr_maint_rebuild_btn"):i("ocr_maint_redo_btn")});N.style.cssText="padding:4px 10px; border-radius:4px; cursor:pointer; font-size:12px;",N.addEventListener("click",()=>{let M=[k.row.key];k.ui.primaryAction==="rebuild"?(0,$.execFile)(r.path,["-m","paperforge","ocr","rebuild",...M],{cwd:t,timeout:12e4,windowsHide:!0},()=>{new F.Notice(i("ocr_maint_rebuild_btn")+" \u2014 "+k.row.key)}):k.ui.primaryAction==="redo"&&(0,$.execFile)(r.path,["-m","paperforge","ocr","redo",...M],{cwd:t,timeout:3e5,windowsHide:!0},()=>{new F.Notice(i("ocr_maint_redo_btn")+" \u2014 "+k.row.key)})})}}let _=h.filter(v=>v.ui.category==="limited");if(_.length>0){n.createEl("h3",{text:i("ocr_maint_limitations")}),n.createEl("p",{text:i("ocr_maint_limitations_intro"),cls:"setting-item-description"});for(let v of _){let k=n.createEl("div",{cls:"pf-maint-card"});k.createEl("strong",{text:v.row.title_short||v.row.title||v.row.key});let E=k.createEl("span",{cls:"pf-maint-chip pf-maint-chip--limited",text:v.ui.label});E.style.marginLeft="8px",k.createEl("p",{text:v.ui.reason,cls:"setting-item-description"})}}let w=n.createEl("details",{cls:"pf-maint-advanced"});w.createEl("summary",{text:i("ocr_maint_all_papers")+" ("+p.length+")"});let D=v=>{let k=v.status,E=v.health;return k==="done"&&v.version==="v1"?{badge:"? \u672A\u8BC4\u4F30",color:"#9e9e9e"}:k==="done"&&E==="green"?{badge:"\u2713 \u5B8C\u6210",color:"#4caf50"}:k==="done"&&E==="yellow"?{badge:"\u26A0 \u8D28\u91CF\u95EE\u9898",color:"#ff9800"}:k==="done"&&E==="red"?{badge:"\u26A0 \u4E25\u91CD\u5F02\u5E38",color:"#f44336"}:k==="done_degraded"?{badge:"\u26A0 \u8D28\u91CF\u95EE\u9898",color:"#ff9800"}:k==="failed"||k==="fatal_error"?{badge:"\u2717 \u5931\u8D25",color:"#f44336"}:k==="pending"||k==="nopdf"||k==="blocked"?{badge:"\u25CB \u5F85\u5904\u7406",color:"#9e9e9e"}:k==="running"||k==="queued"?{badge:"\u25CF \u5904\u7406\u4E2D",color:"#2196f3"}:k==="retryable_error"?{badge:"\u2717 \u53EF\u91CD\u8BD5",color:"#ff9800"}:{badge:k,color:"#9e9e9e"}},S=v=>v.recommended_action==="redo"?"\u91CD\u65B0OCR":v.recommended_action==="rebuild"?"\u91CD\u5EFA\u7D22\u5F15":"",f={};for(let v of p){let k=D(v).badge;f[k]=(f[k]||0)+1}let y=["\u2713 \u5B8C\u6210","? \u672A\u8BC4\u4F30","\u26A0 \u8D28\u91CF\u95EE\u9898","\u26A0 \u4E25\u91CD\u5F02\u5E38","\u2717 \u5931\u8D25","\u25CB \u5F85\u5904\u7406","\u25CF \u5904\u7406\u4E2D"],C=w.createEl("div");C.style.cssText="display:flex; align-items:center; gap:8px; margin-bottom:8px; flex-wrap:wrap;";let T={};for(let v of p)T[v.key]={sel:!1,action:v.recommended_action||""};let R="all",B=p,A=()=>{B=R==="all"?p:p.filter(v=>D(v).badge===R),re.empty(),Pe(B),U()},V=C.createEl("select");V.style.cssText="padding:4px 8px; border-radius:4px;",V.createEl("option",{text:"\u5168\u90E8",value:"all"});for(let v of y)f[v]&&V.createEl("option",{text:v+" "+f[v],value:v});V.addEventListener("change",()=>{R=V.value,A()});let Y=C.createEl("button",{text:"\u5168\u9009"}),O=C.createEl("button",{text:"\u53D6\u6D88\u5168\u9009"});Object.assign(Y.style,{padding:"4px 10px",borderRadius:"4px",cursor:"pointer"}),Object.assign(O.style,{padding:"4px 10px",borderRadius:"4px",cursor:"pointer"});let J=C.createEl("button",{text:"\u25B8 \u6267\u884C\u5DF2\u9009"});J.style.cssText="padding:4px 12px; border-radius:4px; cursor:pointer; font-weight:600; margin-left:auto;";let W=C.createEl("span",{cls:"setting-item-description"});W.style.cssText="font-size:11px;";let U=()=>{let v=0;for(let k of B)T[k.key].action&&v++;W.setText("\u5F85\u4FEE\u590D "+v+" \u7BC7")};Y.addEventListener("click",()=>{for(let v of B)T[v.key].sel=!0,T[v.key].action||(T[v.key].action=v.recommended_action||"");A()}),O.addEventListener("click",()=>{for(let v of p)T[v.key].sel=!1,T[v.key].action="";A()}),J.addEventListener("click",()=>{let v=[],k=[];for(let E of p){let P=T[E.key].action;P==="redo"?v.push(E.key):P==="rebuild"&&k.push(E.key)}if(!v.length&&!k.length){new F.Notice("\u8BF7\u5148\u9009\u62E9\u8981\u4FEE\u590D\u7684\u8BBA\u6587\u3002");return}n.empty(),n.createEl("p",{text:"\u6267\u884C\u4E2D\u2026"}),v.length&&(0,$.execFile)(r.path,["-m","paperforge","ocr","redo",...v],{cwd:t,timeout:3e5,windowsHide:!0},()=>{new F.Notice("\u91CD\u65B0OCR\u5DF2\u89E6\u53D1\uFF0C\u5171 "+v.length+" \u7BC7\u3002")}),k.length&&(0,$.execFile)(r.path,["-m","paperforge","ocr","rebuild",...k],{cwd:t,timeout:12e4,windowsHide:!0},()=>{new F.Notice("\u91CD\u5EFA\u5B8C\u6210\uFF0C\u5171 "+k.length+" \u7BC7\u3002")})});let te=w.createEl("div");te.style.cssText="max-height:60vh; overflow-y:auto; border:1px solid var(--background-modifier-border); border-radius:6px; margin-bottom:16px;";let ne=te.createEl("table");ne.style.cssText="width:100%; border-collapse:collapse; font-size:12px;";let ge=ne.createEl("thead"),re=ne.createEl("tbody"),he=ge.insertRow();["","Key","Title","\u72B6\u6001","\u5EFA\u8BAE","Model","Time","\u4FEE\u590D"].forEach(v=>{let k=document.createElement("th");k.textContent=v,k.style.cssText="padding:4px 6px; text-align:left; border-bottom:1px solid var(--background-modifier-border); position:sticky; top:0; background:var(--background-primary); z-index:1; white-space:nowrap;",he.appendChild(k)});let fe=(v,k)=>`${v}`,Pe=v=>{var k,E;for(let P of v){let N=T[P.key],M=D(P),Q=S(P),G=re.insertRow();G.style.cssText="border-bottom:1px solid var(--background-modifier-border);";let ke=G.insertCell();ke.style.cssText="padding:3px 4px;";let De=document.createElement("input");De.type="checkbox",De.checked=N.sel,De.addEventListener("change",()=>{N.sel=De.checked,!N.sel&&N.action&&(N.action=""),N.sel&&!N.action&&(N.action=P.recommended_action||"")}),ke.appendChild(De);let at=G.insertCell();at.style.cssText="padding:3px 4px; white-space:nowrap; font-size:11px; max-width:90px; overflow:hidden; text-overflow:ellipsis;",at.textContent=P.key;let We=G.insertCell();We.style.cssText="padding:3px 4px; white-space:nowrap; max-width:220px; overflow:hidden; text-overflow:ellipsis;",We.textContent=P.title_short||P.title||P.key,We.title=P.title||P.key;let it=G.insertCell();it.style.cssText="padding:3px 4px; white-space:nowrap;",it.innerHTML=fe(M.badge,M.color);let ot=G.insertCell();ot.style.cssText="padding:3px 4px; white-space:nowrap; max-width:160px; overflow:hidden; text-overflow:ellipsis; font-size:11px; color:var(--text-muted);";let _e="";Q?_e=Q:M.badge==="\u2713 \u5B8C\u6210"?_e="\u5DF2\u5B8C\u6210":M.badge.includes("\u5F85\u5904\u7406")?_e="\u7B49\u5F85OCR":M.badge.includes("\u5931\u8D25")?_e=((k=P.error_summary)==null?void 0:k.substring(0,50))||"":M.badge.includes("\u672A\u8BC4\u4F30")?_e="\u5EFA\u8BAE\u91CD\u65B0\u5904\u7406":(E=P.degraded_reasons)!=null&&E.length&&(_e=P.degraded_reasons[0].substring(0,50)),ot.textContent=_e;let lt=G.insertCell();lt.style.cssText="padding:3px 4px; white-space:nowrap; max-width:140px; overflow:hidden; text-overflow:ellipsis; font-size:11px;",lt.textContent=P.model||"-";let ct=G.insertCell();ct.style.cssText="padding:3px 4px; white-space:nowrap; font-size:11px; color:var(--text-muted);",ct.textContent=P.finished_at||"-";let Re=G.insertCell();if(Re.style.cssText="padding:3px 4px; text-align:center; white-space:nowrap;",Q){let me=document.createElement("input");me.type="checkbox",me.checked=!!N.action,me.title=Q,me.addEventListener("change",()=>{N.action=me.checked?P.recommended_action:"",N.sel=me.checked,A()}),Re.appendChild(me);let qe=document.createElement("span");qe.style.cssText="font-size:10px; color:var(--text-faint); margin-left:2px;",qe.textContent=Q,Re.appendChild(qe)}else Re.textContent="-",Re.style.cssText="padding:3px 4px; text-align:center; font-size:11px; color:var(--text-faint);"}};Pe(p),U(),e.createEl("hr"),e.createEl("h3",{text:"\u5168\u5C40\u64CD\u4F5C"});let Ee=e.createEl("div");Ee.style.cssText="display:flex; gap:8px; flex-wrap:wrap;";let Fe=Ee.createEl("button",{text:"\u91CD\u5EFA\u641C\u7D22\u7D22\u5F15"});Fe.style.cssText="padding:6px 14px; border-radius:4px; cursor:pointer;",Fe.addEventListener("click",()=>{new F.Notice("\u6B63\u5728\u91CD\u5EFA\u641C\u7D22\u7D22\u5F15\u2026"),(0,$.execFile)(r.path,["-m","paperforge","embed","build","--force"],{cwd:t,timeout:3e5,windowsHide:!0},(v,k,E)=>{new F.Notice("\u641C\u7D22\u7D22\u5F15\u91CD\u5EFA\u5B8C\u6210\u3002")})});let Te=Ee.createEl("button",{text:"\u91CD\u5EFA\u8BB0\u5FC6\u5E93"});Te.style.cssText="padding:6px 14px; border-radius:4px; cursor:pointer;",Te.addEventListener("click",()=>{new F.Notice("\u6B63\u5728\u91CD\u5EFA\u8BB0\u5FC6\u5E93\u2026"),(0,$.execFile)(r.path,["-m","paperforge","repair","--fix"],{cwd:t,timeout:12e4,windowsHide:!0},(v,k,E)=>{new F.Notice("\u8BB0\u5FC6\u5E93\u91CD\u5EFA\u5B8C\u6210\u3002")})})})}_renderReleaseNotesTab(e){e.createEl("h2",{text:"\u66F4\u65B0\u4E0E\u624B\u518C"}),e.createEl("h3",{text:"\u7248\u672C\u66F4\u65B0\u8BB0\u5F55"});let t=Ft.default.versions||[];for(let a of t){let s=e.createEl("div",{cls:"paperforge-release-card"}),l=s.createEl("div",{cls:"paperforge-release-header"});if(l.createEl("strong",{text:`v${a.version} \u2014 ${a.title}`}),l.createEl("span",{cls:"paperforge-release-date",text:` (${a.date})`}),a.breaking_or_migration&&a.breaking_or_migration.length>0){let o=s.createEl("div",{cls:"paperforge-release-section"});o.createEl("div",{cls:"paperforge-release-label",text:"\u884C\u4E3A\u53D8\u66F4 / \u8FC1\u79FB\u6CE8\u610F"});for(let c of a.breaking_or_migration)o.createEl("div",{cls:"paperforge-release-item",text:`\u2022 ${c}`})}if(a.new_features&&a.new_features.length>0){let o=s.createEl("div",{cls:"paperforge-release-section"});o.createEl("div",{cls:"paperforge-release-label",text:"\u65B0\u529F\u80FD"});for(let c of a.new_features)o.createEl("div",{cls:"paperforge-release-item",text:`\u2022 ${c}`})}if(a.fixes&&a.fixes.length>0){let o=s.createEl("div",{cls:"paperforge-release-section"});o.createEl("div",{cls:"paperforge-release-label",text:"\u4FEE\u590D"});for(let c of a.fixes)o.createEl("div",{cls:"paperforge-release-item",text:`\u2022 ${c}`})}if(a.recommended_actions&&a.recommended_actions.length>0){let o=s.createEl("div",{cls:"paperforge-release-section paperforge-release-recommended"});o.createEl("div",{cls:"paperforge-release-label",text:"\u5EFA\u8BAE\u64CD\u4F5C"});for(let c of a.recommended_actions)o.createEl("div",{cls:"paperforge-release-item paperforge-release-item-bold",text:`\u2022 ${c}`})}}e.createEl("h3",{text:"\u4F7F\u7528\u624B\u518C"}),e.createEl("div",{cls:"paperforge-manual-links"}).createEl("a",{text:"\u2192 \u67E5\u770B\u5B8C\u6574\u4F7F\u7528\u624B\u518C\uFF08GitHub\uFF09",href:"https://github.com/LLLin000/PaperForge/blob/master/docs/user-manual.md"}).setAttr("target","_blank")}};var I=require("obsidian"),ue=q(require("fs")),Ne=q(require("path")),xe=require("child_process");var Ie=q(require("path"));function Tt(g){if(!g)return null;let u=Ie.dirname(g);for(;;){let e=Ie.basename(u);if(!e||e===".")break;let t=e.match(/^([A-Z0-9]{8})(?:\s*-\s*.*)?$/i);if(t)return t[1];let r=Ie.dirname(u);if(r===u)break;u=r}return null}var Ce=class extends I.ItemView{constructor(e){super(e);this._currentMode=null;this._currentDomain=null;this._currentPaperKey=null;this._currentPaperEntry=null;this._currentFilePath=null;this._cachedItems=null;this._modeSubscribers=[];this._leafChangeTimer=null;this._ocrPrivacyShown=!1;this._cachedStats=null;this._techDetailsExpanded=!1;this._paperforgeVersion="";this._dashboardPermissions={};this._headerTitle=null;this._versionBadge=null;this._messageEl=null;this._metricsEl=null;this._ocrSection=null;this._ocrEmpty=null;this._ocrBadge=null;this._ocrTrack=null;this._ocrCounts=null;this._driftBannerEl=null;this._currentMode=null,this._currentDomain=null,this._currentPaperKey=null,this._currentPaperEntry=null,this._currentFilePath=null,this._cachedItems=null,this._modeSubscribers=[],this._leafChangeTimer=null,this._ocrPrivacyShown=!1}getViewType(){return ye}getDisplayText(){return"PaperForge"}getIcon(){return Be}async onOpen(){this._buildPanel(),this._modeSubscribers=[],this._leafChangeTimer=null,this._setupEventSubscriptions(),this._fetchVersion(),this._detectAndSwitch()}async onClose(){if(this._modeSubscribers&&this._modeSubscribers.length>0){for(let e of this._modeSubscribers)e.event==="active-leaf-change"?this.app.workspace.off("active-leaf-change",e.ref):e.event==="modify"&&this.app.vault.off("modify",e.ref);this._modeSubscribers=[]}this._leafChangeTimer&&(clearTimeout(this._leafChangeTimer),this._leafChangeTimer=null),this._cachedItems=null,this._cachedStats=null}_buildPanel(){let e=this.containerEl;e.empty(),e.addClass("paperforge-status-panel");let t=e.createEl("div",{cls:"paperforge-header"}),r=t.createEl("div",{cls:"paperforge-header-left"});r.createEl("div",{cls:"paperforge-header-logo",text:"P"}),this._modeContextEl=r.createEl("div",{cls:"paperforge-mode-context"}),this._headerTitle=r.createEl("h3",{cls:"paperforge-header-title",text:"PaperForge"}),this._versionBadge=r.createEl("span",{cls:"paperforge-header-badge",text:"v\u2014"});let n=t.createEl("button",{cls:"paperforge-header-refresh",attr:{"aria-label":"Refresh"}});n.innerHTML="\u21BB",n.addEventListener("click",()=>{this._invalidateIndex(),this._detectAndSwitch()}),this._messageEl=e.createEl("div",{cls:"paperforge-message"}),this._contentEl=e.createEl("div",{cls:"paperforge-content-area"})}_fetchVersion(){var s,l;let e=this.app.vault.adapter.basePath,t=this.app.plugins.plugins.paperforge,r=((s=t==null?void 0:t.manifest)==null?void 0:s.version)||"?",{path:n,extraArgs:a=[]}=z(e,(l=t==null?void 0:t.settings)!=null?l:null,void 0,void 0);_t(n,r,e,1e4,void 0).then(o=>{if(o.status==="not-installed")return;let c=o.pyVersion||"";this._paperforgeVersion=c.startsWith("v")?c:"v"+c,this._versionBadge&&this._versionBadge.setText(this._paperforgeVersion),this._driftBannerEl&&r&&this._paperforgeVersion!=="v"+r.replace(/^v/,"")?(this._driftBannerEl.style.display="block",this._driftBannerEl.setText(i("dashboard_drift_warning").replace("{0}",this._paperforgeVersion).replace("{1}","v"+r.replace(/^v/,"")))):this._driftBannerEl&&(this._driftBannerEl.style.display="none")})}_fetchStats(e){var s;if(!this._metricsEl)return;if(!e&&!this._cachedStats)this._metricsEl.empty(),this._metricsEl.createEl("div",{cls:"paperforge-status-loading",text:"Loading..."});else if(e&&!this._cachedStats)return;let t=this.app.vault.adapter.basePath,r=this.app.plugins.plugins.paperforge,{path:n,extraArgs:a=[]}=z(t,(s=r==null?void 0:r.settings)!=null?s:null,void 0,void 0);(0,xe.execFile)(n,[...a,"-m","paperforge","dashboard","--json"],{cwd:t,timeout:3e4},(l,o)=>{if(!l)try{let c=JSON.parse(o);if(c.ok&&c.data){let p=this._normalizeDashboardData(c.data);this._cachedStats=p,this._metricsEl.empty(),this._renderStats(p),this._renderOcr(p),this._dashboardPermissions=c.data.permissions||{};return}}catch(c){}this._fallbackFetchStats(e,t,r)})}_normalizeDashboardData(e){let t=e.stats||{},r=t.ocr_health||{},n=t.pdf_health||{},a=e.ocr_version_state||{},s=(r.done||0)+(r.pending||0)+(r.failed||0);return{total_papers:t.papers||0,formal_notes:t.papers||0,exports:0,bases:0,ocr:{total:s,pending:r.pending||0,processing:0,done:r.done||0,failed:r.failed||0},path_errors:(n.broken||0)+(n.missing||0),ocr_version_state:{total_papers:a.total_papers||0,derived_stale_count:a.derived_stale_count||0,raw_upgradable_count:a.raw_upgradable_count||0}}}_fallbackFetchStats(e,t,r){var s,l,o;let n=((s=r==null?void 0:r.settings)==null?void 0:s.system_dir)||"System",a=Ne.join(t,n,"PaperForge","indexes","formal-library.json");try{let c=ue.readFileSync(a,"utf-8"),p=JSON.parse(c),h=p.items||[],d={},m={pdf_health:{healthy:0,unhealthy:0},ocr_health:{healthy:0,unhealthy:0},note_health:{healthy:0,unhealthy:0},asset_health:{healthy:0,unhealthy:0}},b=0,x=0,_=0,w=0,D=0,S=0;for(let f of h){f.note_path&&S++;let y=f.lifecycle||"pdf_ready";d[y]=(d[y]||0)+1;let C=f.health||{};for(let R of["pdf_health","ocr_health","note_health","asset_health"])(C[R]||"healthy")==="healthy"?m[R].healthy++:m[R].unhealthy++;let T=f.ocr_status||"";b++,T==="done"?x++:T==="pending"?_++:T==="processing"||T==="queued"||T==="running"?w++:D++}this._cachedStats={version:p.paperforge_version||((l=this._cachedStats)==null?void 0:l.version)||"\u2014",total_papers:h.length,formal_notes:S,exports:0,bases:0,ocr:{total:b,pending:_,processing:w,done:x,failed:D},path_errors:0,lifecycle_level_counts:d,health_aggregate:m},this._metricsEl.empty(),this._renderStats(this._cachedStats),this._renderOcr(this._cachedStats)}catch(c){!e&&!this._cachedStats&&this._metricsEl.createEl("div",{cls:"paperforge-status-loading",text:"No index \u2014 trying CLI..."});let{path:p,extraArgs:h=[]}=z(t,(o=r==null?void 0:r.settings)!=null?o:null,void 0,void 0);(0,xe.execFile)(p,[...h,"-m","paperforge","status","--json"],{cwd:t,timeout:3e4},(d,m)=>{if(d){if(this._cachedStats)return;this._metricsEl.createEl("div",{cls:"paperforge-status-error",text:`Cannot reach PaperForge CLI.
+Make sure paperforge is installed and in your PATH.`});return}try{let b=JSON.parse(m);this._cachedStats=b,this._metricsEl.empty(),this._renderStats(b),this._renderOcr(b)}catch(b){this._cachedStats||this._metricsEl.createEl("div",{cls:"paperforge-status-error",text:"Invalid response from paperforge status."})}})}}_renderSkeleton(e){e.addClass("paperforge-loading")}_renderEmptyState(e,t){e.createEl("div",{cls:"paperforge-empty-state",text:t||"No data"})}_buildMetricBar(e,t,r){if(r<=0)return;let n=Math.min(100,t/r*100);e.createEl("div",{cls:"paperforge-metric-progress"}).createEl("div",{cls:"paperforge-metric-progress-fill",attr:{style:`width:${n.toFixed(1)}%`}})}_loadIndex(){var a;let e=this.app.vault.adapter.basePath,t=this.app.plugins.plugins.paperforge,r=((a=t==null?void 0:t.settings)==null?void 0:a.system_dir)||"System",n=Ne.join(e,r,"PaperForge","indexes","formal-library.json");try{let s=ue.readFileSync(n,"utf-8");return JSON.parse(s)}catch(s){return null}}_getCachedIndex(){if(!this._cachedItems){let e=this._loadIndex();this._cachedItems=e?e.items||[]:[]}return this._cachedItems}_findEntry(e){if(!e)return null;let t=this._getCachedIndex().find(r=>r.zotero_key===e)||null;return ut(this.app,t)}_patchCachedEntry(e,t){if(!e||!this._cachedItems)return;let r=this._cachedItems.findIndex(n=>n.zotero_key===e);r!==-1&&(this._cachedItems[r]=Je(this._cachedItems[r],t))}_filterByDomain(e){return e?this._getCachedIndex().filter(t=>t.domain===e):[]}_renderStats(e){var s;if(this._versionBadge&&this._versionBadge.setText(this._paperforgeVersion||(e.version?"v"+e.version:"v\u2014")),!e||typeof e.total_papers=="undefined"){this._metricsEl&&this._renderSkeleton(this._metricsEl);return}if(!this._metricsEl)return;this._metricsEl.removeClass("paperforge-loading");let t=e.total_papers||0,r=e.formal_notes||0,n=[{value:t,label:"Papers",color:"var(--color-cyan)",barMax:0},{value:r,label:"Formal Notes",color:"var(--color-blue)",barMax:t},{value:e.exports||0,label:"Exports",color:"var(--color-purple)",barMax:0}];for(let l of n){let o=this._metricsEl.createEl("div",{cls:"paperforge-metric-card"});o.style.setProperty("--metric-color",l.color),o.createEl("div",{cls:"paperforge-metric-value",text:((s=l.value)==null?void 0:s.toString())||"\u2014"}),o.createEl("div",{cls:"paperforge-metric-label",text:l.label}),l.barMax>0&&this._buildMetricBar(o,l.value,l.barMax)}let a=e.ocr_version_state||{};if(a.total_papers>0&&(a.derived_stale_count>0||a.raw_upgradable_count>0)){let l=[];a.derived_stale_count>0&&l.push(`${a.derived_stale_count} stale`),a.raw_upgradable_count>0&&l.push(`${a.raw_upgradable_count} upgradable`);let o=this._metricsEl.createEl("div",{cls:"paperforge-metric-card"});o.style.setProperty("--metric-color","var(--color-yellow)"),o.createEl("div",{cls:"paperforge-metric-value",text:l.join(", ")}),o.createEl("div",{cls:"paperforge-metric-label",text:"OCR Version"})}}_renderOcr(e){if(!this._ocrSection)return;let t=e.ocr||{},r=t.total||0;if(r===0){this._ocrSection.style.display="none";return}this._ocrSection.style.display="block",this._ocrEmpty&&(this._ocrEmpty.style.display="none");let n=t.done||0,a=t.pending||0,s=t.processing||0,l=t.failed||0;if(this._ocrBadge&&(this._ocrBadge.removeClass("active","idle"),s>0?(this._ocrBadge.addClass("active"),this._ocrBadge.setText("Processing")):a>0?(this._ocrBadge.addClass("idle"),this._ocrBadge.setText("Pending")):(this._ocrBadge.addClass("idle"),this._ocrBadge.setText("Idle"))),this._ocrTrack){this._ocrTrack.empty(),s>0?this._ocrTrack.addClass("paperforge-processing"):this._ocrTrack.removeClass("paperforge-processing");let o=[{cls:"pending",count:a},{cls:"active",count:s},{cls:"done",count:n},{cls:"failed",count:l}];for(let c of o)if(c.count>0){let p=(c.count/r*100).toFixed(1);this._ocrTrack.createEl("div",{cls:`paperforge-progress-seg ${c.cls}`,attr:{style:`width:${p}%`}})}}if(this._ocrCounts){this._ocrCounts.empty();let o=[{cls:"pending",value:a,label:"Pending"},{cls:"active",value:s,label:"Processing"},{cls:"done",value:n,label:"Done"},{cls:"failed",value:l,label:"Failed"}];for(let c of o){let p=this._ocrCounts.createEl("div",{cls:"paperforge-ocr-count"});p.createEl("div",{cls:"paperforge-ocr-count-value",text:c.value.toString()}),p.createEl("div",{cls:"paperforge-ocr-count-label",text:c.label})}}}_renderLifecycleStepper(e,t,r){if(!t||!r){this._renderSkeleton(e);return}let n=[{key:"indexed",label:"Indexed"},{key:"pdf_ready",label:"PDF Ready"},{key:"fulltext_ready",label:"Fulltext Ready"},{key:"deep_read_done",label:"Deep Read"}],a=e.createEl("div",{cls:"paperforge-lifecycle-stepper"}),s=!1;for(let l of n){let o=a.createEl("div",{cls:"step"});o.createEl("div",{cls:"step-indicator"}),o.createEl("div",{cls:"step-label",text:l.label}),l.key===r?(o.addClass("current"),s=!0):s?o.addClass("pending"):o.addClass("completed")}}_renderHealthMatrix(e,t){if(!t){this._renderSkeleton(e);return}let r=[{key:"pdf_health",label:"PDF Health",iconOk:"\u2713",iconWarn:"\u26A0",iconFail:"\u2717"},{key:"ocr_health",label:"OCR Health",iconOk:"\u2713",iconWarn:"\u26A0",iconFail:"\u2717"},{key:"note_health",label:"Note Health",iconOk:"\u2713",iconWarn:"\u26A0",iconFail:"\u2717"},{key:"asset_health",label:"Asset Health",iconOk:"\u2713",iconWarn:"\u26A0",iconFail:"\u2717"}],n=e.createEl("div",{cls:"paperforge-health-matrix"});for(let a of r){let s=t[a.key]||"healthy",l=n.createEl("div",{cls:"paperforge-health-cell"}),o,c,p;s==="healthy"||s==="ok"?(o=a.iconOk,c="ok",p=`${a.label}: OK`):s==="warn"||s==="warning"||s==="degraded"?(o=a.iconWarn,c="warn",p=`${a.label}: Needs Attention`):(o=a.iconFail,c="fail",p=`${a.label}: Failed`),l.addClass(c),l.setAttribute("title",p),l.createEl("div",{cls:"paperforge-health-cell-icon",text:o}),l.createEl("div",{cls:"paperforge-health-cell-label",text:a.label})}}_renderMaturityGauge(e,t,r){if(t==null||t===void 0){this._renderSkeleton(e);return}let n=e.createEl("div",{cls:"paperforge-maturity-gauge"}),a=n.createEl("div",{cls:"gauge-track"}),s=4,l=Math.max(1,Math.min(s,Math.round(t)));for(let o=1;o<=s;o++){let c=a.createEl("div",{cls:"gauge-segment"});o<=l&&(c.addClass("filled"),c.addClass(`level-${o}`))}if(n.createEl("div",{cls:"gauge-level",text:`Level ${l} / ${s}`}),l0){let c=n.createEl("ul",{cls:"gauge-blockers"});for(let p of o)c.createEl("li",{text:p})}}}_renderBarChart(e,t){if(!t||Object.keys(t).length===0){this._renderEmptyState(e,"No lifecycle data");return}let r=[{key:"indexed",label:"Indexed",cls:"stage-indexed"},{key:"pdf_ready",label:"PDF Ready",cls:"stage-pdf-ready"},{key:"fulltext_ready",label:"Fulltext Ready",cls:"stage-fulltext-ready"},{key:"deep_read_done",label:"Deep Read",cls:"stage-deep-read"}],n=e.createEl("div",{cls:"paperforge-bar-chart"}),a=Math.max(1,...r.map(s=>t[s.key]||0));for(let s of r){let l=t[s.key]||0,o=l/a*100,c=n.createEl("div",{cls:"bar-row"});c.createEl("div",{cls:"bar-label",text:s.label}),c.createEl("div",{cls:"bar-track"}).createEl("div",{cls:`bar-fill ${s.cls}`,attr:{style:`width:${o.toFixed(1)}%`}}),c.createEl("div",{cls:"bar-count",text:l.toString()})}}_invalidateIndex(){this._cachedItems=null}_extractZoteroKeyFromPath(e){return Tt(e)}_resolveModeForFile(e){if(!e)return{mode:"global",filePath:null,key:null,domain:null};let t=e.extension,r=e.path;if(t==="base")return{mode:"collection",filePath:r,key:null,domain:e.basename.trim()};if(t==="md"){let a=this.app.metadataCache.getFileCache(e),s=a&&a.frontmatter&&a.frontmatter.zotero_key;if(s)return{mode:"paper",filePath:r,key:s,domain:null}}if(t==="pdf"){let a=this._getCachedIndex();for(let s of a){let l=(s.pdf_path||"").match(/\[\[([^\]]+)\]\]/);if((l?l[1]:s.pdf_path)===r)return{mode:"paper",filePath:r,key:s.zotero_key,domain:null}}}let n=this._extractZoteroKeyFromPath(r);return n?{mode:"paper",filePath:r,key:n,domain:null}:{mode:"global",filePath:r,key:null,domain:null}}_detectAndSwitch(){let e=this._resolveModeForFile(this.app.workspace.getActiveFile());this._currentDomain=e.domain||null,this._currentPaperKey=e.key||null,this._currentPaperEntry=e.key?this._findEntry(e.key):null,this._switchMode(e.mode,e.filePath)}_switchMode(e,t){if(this._currentMode===e&&this._currentFilePath===t){this._refreshCurrentMode();return}if(this._currentMode=e,this._currentFilePath=t,this._techDetailsExpanded=!1,!!this._contentEl)switch(this._contentEl.empty(),this._contentEl.removeClass("switching"),this._renderModeHeader(e),e){case"global":this._renderGlobalMode();break;case"paper":this._renderPaperMode();break;case"collection":this._renderCollectionMode();break}}_renderGlobalMode(){var fe,Pe,Ee,Fe,Te,v,k;if(!this._contentEl)return;let e=this._contentEl.createEl("div",{cls:"paperforge-global-view"});this._driftBannerEl=e.createEl("div",{cls:"paperforge-drift-banner"}),this._driftBannerEl.style.display="none";let t=this._getCachedIndex(),r=t.length,n=0,a=0,s=0;for(let E of t)E.has_pdf&&n++,E.ocr_status==="done"&&a++,E.deep_reading_status==="done"&&s++;let l=e.createEl("div",{cls:"paperforge-library-snapshot"});l.createEl("div",{cls:"paperforge-section-label",text:"Library Snapshot"});let o=l.createEl("div",{cls:"paperforge-snapshot-pills"}),c=[{value:r,label:"papers"},{value:n,label:"PDFs ready"},{value:a,label:"OCR done"},{value:s,label:"deep-read done"}];for(let E of c){let P=o.createEl("div",{cls:"paperforge-snapshot-pill"});P.createEl("span",{cls:"paperforge-snapshot-value",text:String(E.value)}),P.createEl("span",{cls:"paperforge-snapshot-label",text:" "+E.label})}let p=e.createEl("div",{cls:"paperforge-system-status"});p.createEl("div",{cls:"paperforge-section-label",text:"System Status"});let h=p.createEl("div",{cls:"paperforge-status-grid"}),d=this.app.plugins.plugins.paperforge,m=((fe=d==null?void 0:d.manifest)==null?void 0:fe.version)||"?",b=this._paperforgeVersion;if(!b)try{let E=this.app.vault.adapter.basePath,{path:P,extraArgs:N=[]}=z(E,(Pe=d==null?void 0:d.settings)!=null?Pe:null,void 0,void 0),M=(0,xe.execFileSync)(P,[...N,"-c","import paperforge; print(paperforge.__version__)"],{cwd:E,timeout:5e3,encoding:"utf-8",windowsHide:!0}).trim();M&&(b=M.startsWith("v")?M:"v"+M,this._paperforgeVersion=b)}catch(E){}b=b||"\u2014";let x=b==="v"+m;this._renderSystemStatusRow(h,"Runtime",x?"healthy":"mismatch",x?"v"+m:"plugin v"+m+" \u2260 CLI "+b);let _=this._loadIndex(),w=_&&_.items&&_.items.length>0;this._renderSystemStatusRow(h,"Index",w?"healthy":"missing",w?_.items.length+" entries":"formal-library.json not found");let D=((Ee=d==null?void 0:d.settings)==null?void 0:Ee.system_dir)||"System",S=this.app.vault.adapter.basePath,f=!1,y="No exports found";try{let E=Ne.join(S,D,"PaperForge","exports");if(ue.existsSync(E)){let P=ue.readdirSync(E).filter(N=>N.endsWith(".json"));f=P.length>0,y=f?P.length+" export(s)":"No JSON exports"}}catch(E){}this._renderSystemStatusRow(h,"Zotero Export",f?"healthy":"missing",y);let C=!!((Fe=d==null?void 0:d.settings)!=null&&Fe.paddleocr_api_key);if(!C)try{let E=((Te=d==null?void 0:d.settings)==null?void 0:Te.system_dir)||"System",P=Ne.join(S,E,"PaperForge",".env");if(ue.existsSync(P)){let M=ue.readFileSync(P,"utf-8").match(/^PADDLEOCR_API_TOKEN\s*=\s*(.+)$/m);C=!!(M&&M[1]&&M[1].trim())}}catch(E){}C||(C=!!(process.env.PADDLEOCR_API_TOKEN||process.env.PADDLEOCR_API_KEY||process.env.OCR_TOKEN)),this._renderSystemStatusRow(h,"OCR Token",C?"configured":"missing",C?"Configured":"Not set");let T=!1,R="",B=this.app.vault.adapter.basePath,A=rt(B);T=xt(B),R=A&&((v=A.summary)==null?void 0:v.reason)||A&&((k=A.summary)==null?void 0:k.status)||"Unknown",this._renderSystemStatusRow(h,"Memory Layer",T?"healthy":"fail",R);let V=!x&&b!=="\u2014";if(V||!w||!f||!C){let E=e.createEl("div",{cls:"paperforge-issue-summary"});E.createEl("div",{cls:"paperforge-section-label",text:"\u9700\u8981\u5904\u7406"});let P=E.createEl("div",{cls:"paperforge-issue-list"});V&&P.createEl("div",{cls:"paperforge-issue-item",text:"Runtime version mismatch"}),w||P.createEl("div",{cls:"paperforge-issue-item",text:"Index missing or corrupted"}),f||P.createEl("div",{cls:"paperforge-issue-item",text:"No Zotero export found"}),C||P.createEl("div",{cls:"paperforge-issue-item",text:"PaddleOCR API key not configured"});let N=E.createEl("div",{cls:"paperforge-issue-actions"}),M=N.createEl("button",{cls:"paperforge-contextual-btn"});M.createEl("span",{text:"Run Doctor"}),M.addEventListener("click",()=>{let G=X.find(ke=>ke.id==="paperforge-doctor");G&&this._runAction(G,M)});let Q=N.createEl("button",{cls:"paperforge-contextual-btn"});Q.createEl("span",{text:"Repair Issues"}),Q.addEventListener("click",()=>{let G=X.find(ke=>ke.id==="paperforge-repair");G&&this._runAction(G,Q)})}let O=e.createEl("div",{cls:"paperforge-global-actions"});O.createEl("div",{cls:"paperforge-section-label",text:"Start Working"});let J=O.createEl("div",{cls:"paperforge-global-actions-row"}),W=J.createEl("button",{cls:"paperforge-contextual-btn primary"});W.createEl("span",{cls:"paperforge-contextual-btn-icon",text:"\u{1F4C1}"}),W.createEl("span",{text:"Open Literature Hub"}),W.addEventListener("click",()=>{var N;let E=((N=d==null?void 0:d.settings)==null?void 0:N.base_dir)||"Bases",P=this.app.vault.getAbstractFileByPath(E);if(P){let M=null;if(P.children&&(M=P.children.find(Q=>Q.extension==="base")),M){let Q=this.app.workspace.getLeaf(!1);Q&&Q.openFile(M)}else new I.Notice("[!!] No .base file found in "+E,6e3)}else new I.Notice("[!!] Base directory not found: "+E,6e3)});let U=J.createEl("button",{cls:"paperforge-contextual-btn"});U.createEl("span",{cls:"paperforge-contextual-btn-icon",text:"\u21BB"}),U.createEl("span",{text:"Sync Library"}),U.addEventListener("click",()=>{let E=X.find(P=>P.id==="paperforge-sync");E&&this._runAction(E,U)});let te=J.createEl("button",{cls:"paperforge-contextual-btn"});te.createEl("span",{cls:"paperforge-contextual-btn-icon",text:"\u229E"}),te.createEl("span",{text:"Run OCR"}),te.addEventListener("click",()=>{let E=X.find(P=>P.id==="paperforge-ocr");E&&this._runAction(E,te)});let ne=J.createEl("button",{cls:"paperforge-contextual-btn"});ne.createEl("span",{cls:"paperforge-contextual-btn-icon",text:"\u2695"}),ne.createEl("span",{text:"Run Doctor"}),ne.addEventListener("click",()=>{let E=X.find(P=>P.id==="paperforge-doctor");E&&this._runAction(E,ne)});let ge=J.createEl("button",{cls:"paperforge-contextual-btn"});ge.createEl("span",{cls:"paperforge-contextual-btn-icon",text:"\u2139"}),ge.createEl("span",{text:"Refresh Status"}),ge.addEventListener("click",()=>{this._fetchStats(!1)});let re=J.createEl("button",{cls:"paperforge-contextual-btn warn"});re.createEl("span",{cls:"paperforge-contextual-btn-icon",text:"\u21BA"}),re.createEl("span",{text:"Redo OCR"}),re.addEventListener("click",()=>{let E=X.find(P=>P.id==="paperforge-ocr-redo");E&&this._runAction(E,re)});let he=J.createEl("button",{cls:"paperforge-contextual-btn"});he.createEl("span",{cls:"paperforge-contextual-btn-icon",text:"\u21BA"}),he.createEl("span",{text:"Repair Issues"}),he.addEventListener("click",()=>{let E=X.find(P=>P.id==="paperforge-repair");E&&this._runAction(E,he)})}_renderSystemStatusRow(e,t,r,n){let a=e.createEl("div",{cls:"paperforge-status-row"});a.createEl("span",{cls:"paperforge-status-dot"}).addClass(r==="healthy"||r==="configured"?"ok":"fail"),a.createEl("span",{cls:"paperforge-status-label",text:t}),a.createEl("span",{cls:"paperforge-status-detail",text:n||""})}_renderPaperMode(){let e=this._currentPaperEntry,t=this._currentPaperKey;if(!this._contentEl)return;if(!t){this._renderEmptyState(this._contentEl,"No paper data available.");return}if(!e){this._contentEl.createEl("div",{cls:"paperforge-content-placeholder",text:'Paper "'+t+'" not found in canonical index. Sync first.'});return}let r=this._contentEl.createEl("div",{cls:"paperforge-paper-view"}),n=r.createEl("div",{cls:"paperforge-paper-header"});n.createEl("div",{cls:"paperforge-paper-title",text:e.title||"Untitled"});let a=n.createEl("div",{cls:"paperforge-paper-meta"});e.authors&&e.authors.length>0&&a.createEl("span",{cls:"paperforge-paper-authors",text:e.authors.join(", ")}),e.year&&a.createEl("span",{cls:"paperforge-paper-year",text:String(e.year)});let s=r.createEl("div",{cls:"paperforge-status-strip"}),l=s.createEl("div",{cls:"paperforge-status-strip-left"}),o=s.createEl("div",{cls:"paperforge-status-strip-right"}),c=[{key:"pdf",label:"PDF",ok:e.has_pdf===!0},{key:"ocr",label:"OCR",ok:e.ocr_status==="done",pending:["pending","queued","processing"].includes(e.ocr_status||""),fail:["failed","blocked","done_incomplete","nopdf"].includes(e.ocr_status||"")},{key:"deep",label:"\u7CBE\u8BFB",ok:e.deep_reading_status==="done"}];for(let p of c){let h=l.createEl("span",{cls:"paperforge-status-pill"}),d="pending";p.ok?d="ok":p.fail?d="fail":p.pending&&(d="pending"),h.addClass(d);let m=p.ok?"\u2713":p.fail?"\u2717":"\u25CB";h.createEl("span",{cls:"paperforge-status-pill-icon",text:m}),h.createEl("span",{text:" "+p.label})}if(e.pdf_path){let p=o.createEl("button",{cls:"paperforge-contextual-btn"});p.createEl("span",{cls:"paperforge-contextual-btn-icon",text:"\u{1F4C4}"}),p.createEl("span",{text:"\u6253\u5F00 PDF"}),p.addEventListener("click",()=>{let h=e.pdf_path.match(/\[\[([^\]]+)\]\]/),d=h?h[1]:e.pdf_path;this.app.vault.getAbstractFileByPath(d)?this.app.workspace.openLinkText(d,""):new I.Notice("[!!] PDF not found: "+d,6e3)})}if(e.fulltext_path){let p=o.createEl("button",{cls:"paperforge-contextual-btn"});p.createEl("span",{cls:"paperforge-contextual-btn-icon",text:"\u{1F4DD}"}),p.createEl("span",{text:"\u6253\u5F00\u5168\u6587"}),p.addEventListener("click",()=>this._openFulltext(e.fulltext_path))}if(this._renderPaperOverviewCard(r,e),e.next_step==="ready"&&e.deep_reading_status==="done"){let p=r.createEl("div",{cls:"paperforge-complete-row"});p.createEl("span",{text:"\u2713"}),p.createEl("span",{text:"\u5DF2\u5B8C\u6210\uFF0C\u53EF\u76F4\u63A5\u4F7F\u7528"})}else this._renderNextStepCard(r,e,t);this._renderRecentDiscussionCard(r,e),this._renderPaperTechnicalDetails(r,e)}_renderPaperOverviewCard(e,t){let r=e.createEl("div",{cls:"paperforge-paper-overview"});r.createEl("div",{cls:"paperforge-paper-overview-header"}).createEl("span",{cls:"paperforge-paper-overview-title",text:"\u6587\u7AE0\u6982\u89C8"});let a=r.createEl("div",{cls:"paperforge-paper-overview-body"}),s=a.createEl("div",{cls:"paperforge-paper-overview-excerpt",text:"\u52A0\u8F7D\u4E2D..."});if(t.note_path){let l=this.app.vault.getAbstractFileByPath(t.note_path);l?this.app.vault.read(l).then(o=>{let c=this._extractOverviewFromNote(o);if(c){let p=c.length>200?c.slice(0,200)+"...":c;if(s.setText(p),c.length>200){let h=a.createEl("div",{cls:"paperforge-expand-container"}),d=h.createEl("button",{cls:"paperforge-expand-icon",title:"\u5C55\u5F00/\u6536\u8D77"});d.innerHTML='';let m=!1;h.addEventListener("click",()=>{s.setText(m?p:c),d.innerHTML=m?'':'',m=!m})}}else s.setText("\u5C1A\u672A\u751F\u6210\u6587\u7AE0\u6982\u89C8\u3002\u8FD0\u884C /pf-deep \u5F00\u59CB\u7CBE\u8BFB\u3002")}).catch(()=>{s.setText("\u65E0\u6CD5\u8BFB\u53D6\u7B14\u8BB0\u5185\u5BB9")}):s.setText("\u7B14\u8BB0\u6587\u4EF6\u4E0D\u5B58\u5728")}else s.setText("\u5C1A\u672A\u751F\u6210\u6587\u7AE0\u6982\u89C8")}_extractOverviewFromNote(e){if(!e)return null;let t=e.indexOf("## \u{1F50D} \u7CBE\u8BFB");if(t===-1)return null;let r=e.slice(t),n=["**\u4E00\u53E5\u8BDD\u603B\u89C8:**","**\u4E00\u53E5\u8BDD\u603B\u89C8**","**\u6587\u7AE0\u6458\u8981:**","**\u6587\u7AE0\u6458\u8981**"];for(let l of n){let o=r.indexOf(l);if(o!==-1){let c=r.slice(o+l.length),p=["**5 Cs","**Figure","**\u8BC1\u636E","### Pass 2","## "],h=c.length;for(let b of p){let x=c.indexOf(b);x!==-1&&x300?s.slice(0,300)+"...":s}_renderRecentDiscussionCard(e,t){let r=e.createEl("div",{cls:"paperforge-discussion-card"});if(r.style.display="none",!t.note_path)return;let n=t.note_path.lastIndexOf("/"),s=(n!==-1?t.note_path.substring(0,n):".")+"/ai/discussion.md";this.app.vault.adapter.exists(s).then(l=>{if(l)return this.app.vault.adapter.read(s)}).then(async l=>{if(!l)return;let o=this._parseDiscussionMD(l);if(!o||o.length===0)return;r.style.display="block",r.createEl("div",{cls:"paperforge-discussion-header"}).createEl("span",{cls:"paperforge-discussion-title",text:"\u6700\u8FD1\u8BA8\u8BBA"});for(let h of o){let d=r.createEl("div",{cls:"paperforge-discussion-item"}),m=d.createEl("div",{cls:"paperforge-discussion-q"});m.createEl("span",{cls:"paperforge-discussion-q-label",text:"\u63D0\u95EE\uFF1A"}),m.createEl("span",{cls:"paperforge-discussion-q-text",text:h.question});let b=d.createEl("div",{cls:"paperforge-discussion-a"}),x=!1;if(h.answer&&h.answer.length>500&&(x=!0,b.classList.add("paperforge-discussion-a-collapsed")),await I.MarkdownRenderer.render(this.app,h.answer||"",b,s,this),x){let _=!1;d.style.cursor="pointer",d.addEventListener("click",()=>{_=!_,b.classList.toggle("paperforge-discussion-a-collapsed",!_),b.classList.toggle("paperforge-discussion-a-expanded",_)})}}r.createEl("a",{cls:"paperforge-discussion-viewall",text:"\u67E5\u770B\u5168\u90E8\u8BA8\u8BBA \u2192"}).addEventListener("click",h=>{h.preventDefault(),this.app.vault.getAbstractFileByPath(s)?this.app.workspace.openLinkText(s,""):new I.Notice("\u8BA8\u8BBA\u6587\u4EF6\u5C1A\u672A\u751F\u6210")})}).catch(l=>{console.error("PaperForge: discussion.md read error",s,l.message)})}_parseDiscussionMD(e){let t=e.split(/\n## /).slice(1);if(t.length===0)return null;let r=t[t.length-1],n=[],a=r.split(/\*\*\u95EE\u9898:\*\*/).slice(1);for(let s of a){let l=s.match(/\*\*\u89E3\u7B54:\*\*/);if(!l)continue;let o=s.substring(0,l.index).trim(),c=s.substring(l.index+3+4).trim();n.push({question:o,answer:c})}return n.slice(-3)}_renderPaperTechnicalDetails(e,t){let r=this._currentPaperKey,n=e.createEl("div",{cls:"paperforge-technical-details"}),a=n.createEl("button",{cls:"paperforge-technical-details-toggle"}),s=n.createEl("div",{cls:"paperforge-technical-details-body"});s.style.display="none",this._techDetailsExpanded?(s.style.display="block",a.setText("\u6280\u672F\u8BE6\u60C5 \u25BE")):a.setText("\u6280\u672F\u8BE6\u60C5 \u25B8"),a.addEventListener("click",()=>{let h=s.style.display!=="none";s.style.display=h?"none":"block",a.setText(h?"\u6280\u672F\u8BE6\u60C5 \u25B8":"\u6280\u672F\u8BE6\u60C5 \u25BE"),this._techDetailsExpanded=!h});let l=s.createEl("div",{cls:"paperforge-workflow-toggles"}),o=[{key:"do_ocr",label:"OCR",hint:"\u52A0\u5165 OCR"},{key:"analyze",label:"\u7CBE\u8BFB",hint:"\u6807\u8BB0\u7CBE\u8BFB"}];for(let h of o){let d=l.createEl("label",{cls:"paperforge-workflow-toggle"}),m=d.createEl("input",{type:"checkbox",cls:"paperforge-workflow-checkbox"});m.checked=t[h.key]===!0,d.createEl("span",{cls:"paperforge-workflow-toggle-label",text:h.label}),d.createEl("span",{cls:"paperforge-workflow-toggle-hint",text:h.hint}),m.addEventListener("change",async()=>{let b=t.note_path?this.app.vault.getAbstractFileByPath(t.note_path):null;if(!b){new I.Notice("[!!] Note file not found",6e3);return}let x=m.checked;await this.app.fileManager.processFrontMatter(b,_=>{_[h.key]=x}),this._patchCachedEntry(r,{[h.key]:x}),this._currentPaperEntry=Je(this._currentPaperEntry,{[h.key]:x})})}let c=t.health||{},p=[["PDF Health",c.pdf_health||"\u2014"],["OCR Status",t.ocr_status||"\u2014"],["Asset Health",c.asset_health||"\u2014"],["Note Path",t.note_path||"\u2014"],["Fulltext Path",t.fulltext_path||"\u2014"]];for(let[h,d]of p){let m=s.createEl("div",{cls:"paperforge-technical-row"});m.createEl("span",{cls:"paperforge-technical-label",text:h}),m.createEl("span",{cls:"paperforge-technical-value",text:String(d)})}}_renderNextStepCard(e,t,r){var o,c;let n=t.next_step||"ready",a={sync:{label:"Sync Needed",text:"This paper needs to be synced from Zotero. Click to run sync.",cmd:"sync",icon:"\u21BB"},ocr:{label:"OCR Needed",text:"Fulltext is missing but PDF is present. Click to run OCR.",cmd:"ocr",icon:"\u229E"},repair:{label:"Repair Needed",text:"State divergence or path errors detected. Click to repair.",cmd:"repair",icon:"\u21BA"},"rebuild index":{label:"Rebuild Needed",text:"Index may be stale. Click to run sync to rebuild.",cmd:"sync",icon:"\u21BB"},"/pf-deep":{label:"Ready for Deep Reading",text:"Fulltext is ready. Copy /pf-deep command and run in your agent.",cmd:null,icon:"\u{1F50D}"},ready:{label:"All Set",text:"This paper is fully processed and ready for use.",cmd:"ready",icon:"\u2713"}},s=a[n]||a.ready,l=e.createEl("div",{cls:"paperforge-next-step-card"});if(n==="ready"&&l.addClass("ready"),l.createEl("div",{cls:"paperforge-next-step-label",text:"Recommended Next Step"}),l.createEl("div",{cls:"paperforge-next-step-text",text:s.text}),s.cmd&&s.cmd!=="ready"){let p=l.createEl("button",{cls:"paperforge-next-step-trigger"});p.createEl("span",{text:s.icon+" "+s.label}),p.addEventListener("click",()=>{let h=X.find(d=>d.cmd===s.cmd);h&&this._runAction(h,p)})}else if(n==="/pf-deep"){let p=l.createEl("button",{cls:"paperforge-next-step-trigger"});p.createEl("span",{text:"\u{1F4CB} "+i("copy_pf_deep_cmd")}),p.addEventListener("click",()=>{let x="/pf-deep "+r;navigator.clipboard.writeText(x).then(()=>{p.setText("\u2713 "+i("copied")),new I.Notice(x+" copied")}).catch(()=>{new I.Notice("[!!] Clipboard write failed",6e3)})});let h=((c=(o=this.app.plugins.plugins.paperforge)==null?void 0:o.settings)==null?void 0:c.agent_platform)||"opencode",m={opencode:"OpenCode",claude:"Claude Code",cursor:"Cursor",github_copilot:"GitHub Copilot",windsurf:"Windsurf",codex:"Codex",gemini:"Gemini CLI",cline:"Cline"}[h]||h;l.createEl("div",{cls:"paperforge-agent-platform-label"}).setText(i("run_in_agent").replace("{0}",m))}else n==="ready"&&l.createEl("button",{cls:"paperforge-next-step-trigger"}).createEl("span",{text:"\u2713 "+s.label})}_openFulltext(e){if(!e){new I.Notice("[!!] No fulltext path available for this paper",6e3);return}let t=this.app.vault.getAbstractFileByPath(e);t?this.app.workspace.openLinkText(t.path,""):new I.Notice("[!!] Fulltext file not found: "+e,6e3)}_renderCollectionMode(){let e=this._currentDomain||"Unknown",t=this._filterByDomain(e);if(t.length===0){this._renderGlobalMode();return}if(!this._contentEl)return;let r=this._contentEl.createEl("div",{cls:"paperforge-collection-view"}),n=t.length,a=0,s=0,l=0,o=0,c=0,p=0,h=0;for(let f of t){f.has_pdf&&a++,f.ocr_status==="done"&&s++,f.ocr_status==="done"&&f.analyze===!0&&l++,f.deep_reading_status==="done"&&o++;let y=f.ocr_status||"";y==="pending"||y==="queued"?c++:y==="processing"?p++:(y==="failed"||y==="blocked"||y==="done_incomplete"||y==="nopdf")&&h++}r.createEl("div",{cls:"paperforge-collection-header"}).createEl("div",{cls:"paperforge-collection-title",text:e});let m=r.createEl("div",{cls:"paperforge-workflow-overview"});m.createEl("div",{cls:"paperforge-section-label",text:"Workflow Overview"});let b=m.createEl("div",{cls:"paperforge-workflow-funnel"}),x=[{value:n,label:"Total"},{value:a,label:"PDF Ready"},{value:s,label:"OCR Done"},{value:o,label:"Deep Read"}];for(let f=0;f0){let f=r.createEl("div",{cls:"paperforge-ocr-section"}),y=f.createEl("div",{cls:"paperforge-collection-ocr-header"});y.createEl("h4",{cls:"paperforge-ocr-title",text:"OCR Pipeline"});let w=y.createEl("span",{cls:"paperforge-ocr-badge idle"});p>0?(w.addClass("active"),w.setText("Processing")):c>0?w.setText("Pending"):(w.addClass("idle"),w.setText("Idle"));let T=f.createEl("div",{cls:"paperforge-progress-track"});p>0&&T.addClass("paperforge-processing");let R=c+p+s+h,B=[{cls:"pending",count:c},{cls:"active",count:p},{cls:"done",count:s},{cls:"failed",count:h}];for(let Y of B)if(Y.count>0){let O=(Y.count/R*100).toFixed(1);T.createEl("div",{cls:`paperforge-progress-seg ${Y.cls}`,attr:{style:`width:${O}%`}})}let A=f.createEl("div",{cls:"paperforge-ocr-counts"}),V=[{cls:"pending",value:c,label:"Pending"},{cls:"active",value:p,label:"Processing"},{cls:"done",value:s,label:"Done"},{cls:"failed",value:h,label:"Attention"}];for(let Y of V){let O=A.createEl("div",{cls:"paperforge-ocr-count"});O.createEl("div",{cls:"paperforge-ocr-count-value",text:Y.value.toString()}),O.createEl("div",{cls:"paperforge-ocr-count-label",text:Y.label})}}let _=r.createEl("div",{cls:"paperforge-collection-actions"}),k=_.createEl("button",{cls:"paperforge-contextual-btn primary"});k.createEl("span",{cls:"paperforge-contextual-btn-icon",text:"\u229E"}),k.createEl("span",{text:"Run OCR"}),k.addEventListener("click",()=>{let f=X.find(y=>y.id==="paperforge-ocr");f&&this._runAction(f,k)});let D=_.createEl("button",{cls:"paperforge-contextual-btn"});D.createEl("span",{cls:"paperforge-contextual-btn-icon",text:"\u21BB"}),D.createEl("span",{text:"Sync Library"}),D.addEventListener("click",()=>{let f=X.find(y=>y.id==="paperforge-sync");f&&this._runAction(f,D)});let S=_.createEl("button",{cls:"paperforge-contextual-btn warn"});S.createEl("span",{cls:"paperforge-contextual-btn-icon",text:"\u21BA"}),S.createEl("span",{text:"Redo OCR"}),S.addEventListener("click",()=>{let f=X.find(y=>y.id==="paperforge-ocr-redo");f&&this._runAction(f,S)})}_refreshCurrentMode(){if(!(!this._currentMode||!this._contentEl)){this._contentEl.empty(),this._contentEl.addClass("switching"),this._invalidateIndex(),this._currentPaperEntry=this._currentPaperKey?this._findEntry(this._currentPaperKey):null,this._renderModeHeader(this._currentMode);try{switch(this._currentMode){case"global":this._renderGlobalMode();break;case"paper":this._renderPaperMode();break;case"collection":this._renderCollectionMode();break}}finally{setTimeout(()=>{this._contentEl&&this._contentEl.removeClass("switching")},50)}}}_runAction(e,t){var d,m;if(e.disabled){new I.Notice(`[i] ${e.disabledMsg||"This action is not yet available."}`,6e3);return}if(t.classList.contains("running"))return;t.addClass("running");let r=this.app.vault.adapter.basePath;this._showMessage("Processing...","running");let n=Array.isArray(e.args)?[...e.args]:[];if(e.needsKey){let b=this.app.workspace.getActiveFile(),x=null;if(b){let _=this.app.metadataCache.getFileCache(b);if(_&&_.frontmatter&&_.frontmatter.zotero_key?x=_.frontmatter.zotero_key:x=this._extractZoteroKeyFromPath(b.path),x)n=[...n,x];else if(_&&_.frontmatter){this._showMessage("[!!] No zotero_key in active note frontmatter","error"),new I.Notice("[!!] Open a paper note with a zotero_key in its frontmatter first",6e3),t.removeClass("running");return}else{this._showMessage("[!!] No frontmatter in active note","error"),new I.Notice("[!!] The active note has no frontmatter with a zotero_key",6e3),t.removeClass("running");return}}else{this._showMessage("[!!] No active note open","error"),new I.Notice("[!!] Open a paper note with a zotero_key in its frontmatter first",6e3),t.removeClass("running");return}}e.needsFilter&&(n=[...n,"--all"]);let a=e.needsFilter?6e4:e.needsKey?3e4:6e5,{path:s,extraArgs:l=[]}=N(r,(m=(d=this.app.plugins.plugins.paperforge)==null?void 0:d.settings)!=null?m:null,void 0,void 0),o=(0,xe.spawn)(s,[...l,"-m","paperforge",e.cmd,...n],{cwd:r,timeout:a}),c=[],p=Date.now(),h=setInterval(()=>this._fetchStats(!0),4e3);o.stdout.on("data",b=>{let x=b.toString("utf-8").split(`
-`).filter(Boolean);for(let _ of x){let k=_.trim();k&&(c.push(k),this._showMessage(c.slice(-8).join(`
+`)[0].trim();return!s||s.startsWith("###")||s.startsWith("##")?null:s.length>300?s.slice(0,300)+"...":s}_renderRecentDiscussionCard(e,t){let r=e.createEl("div",{cls:"paperforge-discussion-card"});if(r.style.display="none",!t.note_path)return;let n=t.note_path.lastIndexOf("/"),s=(n!==-1?t.note_path.substring(0,n):".")+"/ai/discussion.md";this.app.vault.adapter.exists(s).then(l=>{if(l)return this.app.vault.adapter.read(s)}).then(async l=>{if(!l)return;let o=this._parseDiscussionMD(l);if(!o||o.length===0)return;r.style.display="block",r.createEl("div",{cls:"paperforge-discussion-header"}).createEl("span",{cls:"paperforge-discussion-title",text:"\u6700\u8FD1\u8BA8\u8BBA"});for(let h of o){let d=r.createEl("div",{cls:"paperforge-discussion-item"}),m=d.createEl("div",{cls:"paperforge-discussion-q"});m.createEl("span",{cls:"paperforge-discussion-q-label",text:"\u63D0\u95EE\uFF1A"}),m.createEl("span",{cls:"paperforge-discussion-q-text",text:h.question});let b=d.createEl("div",{cls:"paperforge-discussion-a"}),x=!1;if(h.answer&&h.answer.length>500&&(x=!0,b.classList.add("paperforge-discussion-a-collapsed")),await I.MarkdownRenderer.render(this.app,h.answer||"",b,s,this),x){let _=!1;d.style.cursor="pointer",d.addEventListener("click",()=>{_=!_,b.classList.toggle("paperforge-discussion-a-collapsed",!_),b.classList.toggle("paperforge-discussion-a-expanded",_)})}}r.createEl("a",{cls:"paperforge-discussion-viewall",text:"\u67E5\u770B\u5168\u90E8\u8BA8\u8BBA \u2192"}).addEventListener("click",h=>{h.preventDefault(),this.app.vault.getAbstractFileByPath(s)?this.app.workspace.openLinkText(s,""):new I.Notice("\u8BA8\u8BBA\u6587\u4EF6\u5C1A\u672A\u751F\u6210")})}).catch(l=>{console.error("PaperForge: discussion.md read error",s,l.message)})}_parseDiscussionMD(e){let t=e.split(/\n## /).slice(1);if(t.length===0)return null;let r=t[t.length-1],n=[],a=r.split(/\*\*\u95EE\u9898:\*\*/).slice(1);for(let s of a){let l=s.match(/\*\*\u89E3\u7B54:\*\*/);if(!l)continue;let o=s.substring(0,l.index).trim(),c=s.substring(l.index+3+4).trim();n.push({question:o,answer:c})}return n.slice(-3)}_renderPaperTechnicalDetails(e,t){let r=this._currentPaperKey,n=e.createEl("div",{cls:"paperforge-technical-details"}),a=n.createEl("button",{cls:"paperforge-technical-details-toggle"}),s=n.createEl("div",{cls:"paperforge-technical-details-body"});s.style.display="none",this._techDetailsExpanded?(s.style.display="block",a.setText("\u6280\u672F\u8BE6\u60C5 \u25BE")):a.setText("\u6280\u672F\u8BE6\u60C5 \u25B8"),a.addEventListener("click",()=>{let h=s.style.display!=="none";s.style.display=h?"none":"block",a.setText(h?"\u6280\u672F\u8BE6\u60C5 \u25B8":"\u6280\u672F\u8BE6\u60C5 \u25BE"),this._techDetailsExpanded=!h});let l=s.createEl("div",{cls:"paperforge-workflow-toggles"}),o=[{key:"do_ocr",label:"OCR",hint:"\u52A0\u5165 OCR"},{key:"analyze",label:"\u7CBE\u8BFB",hint:"\u6807\u8BB0\u7CBE\u8BFB"}];for(let h of o){let d=l.createEl("label",{cls:"paperforge-workflow-toggle"}),m=d.createEl("input",{type:"checkbox",cls:"paperforge-workflow-checkbox"});m.checked=t[h.key]===!0,d.createEl("span",{cls:"paperforge-workflow-toggle-label",text:h.label}),d.createEl("span",{cls:"paperforge-workflow-toggle-hint",text:h.hint}),m.addEventListener("change",async()=>{let b=t.note_path?this.app.vault.getAbstractFileByPath(t.note_path):null;if(!b){new I.Notice("[!!] Note file not found",6e3);return}let x=m.checked;await this.app.fileManager.processFrontMatter(b,_=>{_[h.key]=x}),this._patchCachedEntry(r,{[h.key]:x}),this._currentPaperEntry=Je(this._currentPaperEntry,{[h.key]:x})})}let c=t.health||{},p=[["PDF Health",c.pdf_health||"\u2014"],["OCR Status",t.ocr_status||"\u2014"],["Asset Health",c.asset_health||"\u2014"],["Note Path",t.note_path||"\u2014"],["Fulltext Path",t.fulltext_path||"\u2014"]];for(let[h,d]of p){let m=s.createEl("div",{cls:"paperforge-technical-row"});m.createEl("span",{cls:"paperforge-technical-label",text:h}),m.createEl("span",{cls:"paperforge-technical-value",text:String(d)})}}_renderNextStepCard(e,t,r){var o,c;let n=t.next_step||"ready",a={sync:{label:"Sync Needed",text:"This paper needs to be synced from Zotero. Click to run sync.",cmd:"sync",icon:"\u21BB"},ocr:{label:"OCR Needed",text:"Fulltext is missing but PDF is present. Click to run OCR.",cmd:"ocr",icon:"\u229E"},repair:{label:"Repair Needed",text:"State divergence or path errors detected. Click to repair.",cmd:"repair",icon:"\u21BA"},"rebuild index":{label:"Rebuild Needed",text:"Index may be stale. Click to run sync to rebuild.",cmd:"sync",icon:"\u21BB"},"/pf-deep":{label:"Ready for Deep Reading",text:"Fulltext is ready. Copy /pf-deep command and run in your agent.",cmd:null,icon:"\u{1F50D}"},ready:{label:"All Set",text:"This paper is fully processed and ready for use.",cmd:"ready",icon:"\u2713"}},s=a[n]||a.ready,l=e.createEl("div",{cls:"paperforge-next-step-card"});if(n==="ready"&&l.addClass("ready"),l.createEl("div",{cls:"paperforge-next-step-label",text:"Recommended Next Step"}),l.createEl("div",{cls:"paperforge-next-step-text",text:s.text}),s.cmd&&s.cmd!=="ready"){let p=l.createEl("button",{cls:"paperforge-next-step-trigger"});p.createEl("span",{text:s.icon+" "+s.label}),p.addEventListener("click",()=>{let h=X.find(d=>d.cmd===s.cmd);h&&this._runAction(h,p)})}else if(n==="/pf-deep"){let p=l.createEl("button",{cls:"paperforge-next-step-trigger"});p.createEl("span",{text:"\u{1F4CB} "+i("copy_pf_deep_cmd")}),p.addEventListener("click",()=>{let x="/pf-deep "+r;navigator.clipboard.writeText(x).then(()=>{p.setText("\u2713 "+i("copied")),new I.Notice(x+" copied")}).catch(()=>{new I.Notice("[!!] Clipboard write failed",6e3)})});let h=((c=(o=this.app.plugins.plugins.paperforge)==null?void 0:o.settings)==null?void 0:c.agent_platform)||"opencode",m={opencode:"OpenCode",claude:"Claude Code",cursor:"Cursor",github_copilot:"GitHub Copilot",windsurf:"Windsurf",codex:"Codex",gemini:"Gemini CLI",cline:"Cline"}[h]||h;l.createEl("div",{cls:"paperforge-agent-platform-label"}).setText(i("run_in_agent").replace("{0}",m))}else n==="ready"&&l.createEl("button",{cls:"paperforge-next-step-trigger"}).createEl("span",{text:"\u2713 "+s.label})}_openFulltext(e){if(!e){new I.Notice("[!!] No fulltext path available for this paper",6e3);return}let t=this.app.vault.getAbstractFileByPath(e);t?this.app.workspace.openLinkText(t.path,""):new I.Notice("[!!] Fulltext file not found: "+e,6e3)}_renderCollectionMode(){let e=this._currentDomain||"Unknown",t=this._filterByDomain(e);if(t.length===0){this._renderGlobalMode();return}if(!this._contentEl)return;let r=this._contentEl.createEl("div",{cls:"paperforge-collection-view"}),n=t.length,a=0,s=0,l=0,o=0,c=0,p=0,h=0;for(let f of t){f.has_pdf&&a++,f.ocr_status==="done"&&s++,f.ocr_status==="done"&&f.analyze===!0&&l++,f.deep_reading_status==="done"&&o++;let y=f.ocr_status||"";y==="pending"||y==="queued"?c++:y==="processing"?p++:(y==="failed"||y==="blocked"||y==="done_incomplete"||y==="nopdf")&&h++}r.createEl("div",{cls:"paperforge-collection-header"}).createEl("div",{cls:"paperforge-collection-title",text:e});let m=r.createEl("div",{cls:"paperforge-workflow-overview"});m.createEl("div",{cls:"paperforge-section-label",text:"Workflow Overview"});let b=m.createEl("div",{cls:"paperforge-workflow-funnel"}),x=[{value:n,label:"Total"},{value:a,label:"PDF Ready"},{value:s,label:"OCR Done"},{value:o,label:"Deep Read"}];for(let f=0;f0){let f=r.createEl("div",{cls:"paperforge-ocr-section"}),y=f.createEl("div",{cls:"paperforge-collection-ocr-header"});y.createEl("h4",{cls:"paperforge-ocr-title",text:"OCR Pipeline"});let C=y.createEl("span",{cls:"paperforge-ocr-badge idle"});p>0?(C.addClass("active"),C.setText("Processing")):c>0?C.setText("Pending"):(C.addClass("idle"),C.setText("Idle"));let T=f.createEl("div",{cls:"paperforge-progress-track"});p>0&&T.addClass("paperforge-processing");let R=c+p+s+h,B=[{cls:"pending",count:c},{cls:"active",count:p},{cls:"done",count:s},{cls:"failed",count:h}];for(let Y of B)if(Y.count>0){let O=(Y.count/R*100).toFixed(1);T.createEl("div",{cls:`paperforge-progress-seg ${Y.cls}`,attr:{style:`width:${O}%`}})}let A=f.createEl("div",{cls:"paperforge-ocr-counts"}),V=[{cls:"pending",value:c,label:"Pending"},{cls:"active",value:p,label:"Processing"},{cls:"done",value:s,label:"Done"},{cls:"failed",value:h,label:"Attention"}];for(let Y of V){let O=A.createEl("div",{cls:"paperforge-ocr-count"});O.createEl("div",{cls:"paperforge-ocr-count-value",text:Y.value.toString()}),O.createEl("div",{cls:"paperforge-ocr-count-label",text:Y.label})}}let _=r.createEl("div",{cls:"paperforge-collection-actions"}),w=_.createEl("button",{cls:"paperforge-contextual-btn primary"});w.createEl("span",{cls:"paperforge-contextual-btn-icon",text:"\u229E"}),w.createEl("span",{text:"Run OCR"}),w.addEventListener("click",()=>{let f=X.find(y=>y.id==="paperforge-ocr");f&&this._runAction(f,w)});let D=_.createEl("button",{cls:"paperforge-contextual-btn"});D.createEl("span",{cls:"paperforge-contextual-btn-icon",text:"\u21BB"}),D.createEl("span",{text:"Sync Library"}),D.addEventListener("click",()=>{let f=X.find(y=>y.id==="paperforge-sync");f&&this._runAction(f,D)});let S=_.createEl("button",{cls:"paperforge-contextual-btn warn"});S.createEl("span",{cls:"paperforge-contextual-btn-icon",text:"\u21BA"}),S.createEl("span",{text:"Redo OCR"}),S.addEventListener("click",()=>{let f=X.find(y=>y.id==="paperforge-ocr-redo");f&&this._runAction(f,S)})}_refreshCurrentMode(){if(!(!this._currentMode||!this._contentEl)){this._contentEl.empty(),this._contentEl.addClass("switching"),this._invalidateIndex(),this._currentPaperEntry=this._currentPaperKey?this._findEntry(this._currentPaperKey):null,this._renderModeHeader(this._currentMode);try{switch(this._currentMode){case"global":this._renderGlobalMode();break;case"paper":this._renderPaperMode();break;case"collection":this._renderCollectionMode();break}}finally{setTimeout(()=>{this._contentEl&&this._contentEl.removeClass("switching")},50)}}}_runAction(e,t){var d,m;if(e.disabled){new I.Notice(`[i] ${e.disabledMsg||"This action is not yet available."}`,6e3);return}if(t.classList.contains("running"))return;t.addClass("running");let r=this.app.vault.adapter.basePath;this._showMessage("Processing...","running");let n=Array.isArray(e.args)?[...e.args]:[];if(e.needsKey){let b=this.app.workspace.getActiveFile(),x=null;if(b){let _=this.app.metadataCache.getFileCache(b);if(_&&_.frontmatter&&_.frontmatter.zotero_key?x=_.frontmatter.zotero_key:x=this._extractZoteroKeyFromPath(b.path),x)n=[...n,x];else if(_&&_.frontmatter){this._showMessage("[!!] No zotero_key in active note frontmatter","error"),new I.Notice("[!!] Open a paper note with a zotero_key in its frontmatter first",6e3),t.removeClass("running");return}else{this._showMessage("[!!] No frontmatter in active note","error"),new I.Notice("[!!] The active note has no frontmatter with a zotero_key",6e3),t.removeClass("running");return}}else{this._showMessage("[!!] No active note open","error"),new I.Notice("[!!] Open a paper note with a zotero_key in its frontmatter first",6e3),t.removeClass("running");return}}e.needsFilter&&(n=[...n,"--all"]);let a=e.needsFilter?6e4:e.needsKey?3e4:6e5,{path:s,extraArgs:l=[]}=z(r,(m=(d=this.app.plugins.plugins.paperforge)==null?void 0:d.settings)!=null?m:null,void 0,void 0),o=(0,xe.spawn)(s,[...l,"-m","paperforge",e.cmd,...n],{cwd:r,timeout:a}),c=[],p=Date.now(),h=setInterval(()=>this._fetchStats(!0),4e3);o.stdout.on("data",b=>{let x=b.toString("utf-8").split(`
+`).filter(Boolean);for(let _ of x){let w=_.trim();w&&(c.push(w),this._showMessage(c.slice(-8).join(`
`),"running"))}}),o.stderr.on("data",b=>{let x=b.toString("utf-8").split(`
-`).filter(Boolean);for(let _ of x){if(_.includes("\r")||_.includes("%")||_.includes("\u2588"))continue;let k=_.trim();k&&!k.match(/^\d+%|^\|/)&&(c.push(k),this._showMessage(c.slice(-8).join(`
+`).filter(Boolean);for(let _ of x){if(_.includes("\r")||_.includes("%")||_.includes("\u2588"))continue;let w=_.trim();w&&!w.match(/^\d+%|^\|/)&&(c.push(w),this._showMessage(c.slice(-8).join(`
`),"running"))}}),o.on("close",b=>{clearInterval(h),t.removeClass("running");let x=((Date.now()-p)/1e3).toFixed(1);if(b!==0){let _=c.slice(-3).join(" | ")||"exit code "+b;(e.cmd==="repair"||e.cmd==="ocr")&&b===1?(this._showMessage("[WARN] "+_,"running"),new I.Notice("[WARN] "+e.cmd+" partial: "+_,8e3),this._fetchStats(!0)):(this._showMessage("[!!] "+_,"error"),new I.Notice("[!!] "+e.cmd+" failed: "+_,8e3))}else if(e.needsKey||e.needsFilter){let _=c.join(`
-`);if(_.trim())try{JSON.parse(_),navigator.clipboard.writeText(_).then(()=>{let k=`${x}s \u2014 ${_.length} chars copied`;this._showMessage("[OK] "+e.title+": "+k,"ok"),new I.Notice("[OK] "+e.okMsg+" \u2014 "+_.length+" chars")}).catch(k=>{this._showMessage("[!!] Clipboard write failed: "+k.message,"error"),new I.Notice("[!!] Clipboard error",6e3)})}catch(k){this._showMessage("[!!] Invalid JSON from "+e.title,"error"),new I.Notice("[!!] "+e.title+" returned invalid JSON: "+k.message.slice(0,100),8e3)}else this._showMessage("[!!] No output from context command","error"),new I.Notice("[!!] Context command returned empty output",8e3);this._fetchStats(!0)}else{let k=c.filter(S=>S.match(/updated \d+/)).pop()||c[c.length-1]||"",D=`${x}s \u2014 ${k}`;this._showMessage("[OK] "+e.title+": "+D,"ok"),new I.Notice("[OK] "+e.okMsg),this._contentEl&&this._contentEl.removeClass("switching"),this._cachedStats=null;try{this._fetchStats(!1)}catch(S){console.log("[PF] fetchStats error:",S)}console.log("[PF] close cmd="+e.cmd+" id="+e.id),e.cmd==="sync"&&He(this.app,this.app.plugins.plugins.paperforge,r)}}),o.on("error",b=>{t.removeClass("running"),this._contentEl&&this._contentEl.removeClass("switching"),this._showMessage("[!!] "+b.message,"error"),new I.Notice("[!!] Cannot start: "+b.message,8e3)})}_showMessage(e,t){this._messageEl&&(this._messageEl.setText(e),this._messageEl.className=`paperforge-message msg-${t}`)}_renderModeHeader(e){if(!this._modeContextEl)return;this._modeContextEl.empty();let t=this._modeContextEl.createEl("span",{cls:"paperforge-mode-badge"}),r="";switch(e){case"global":t.addClass("global"),t.setText("Global"),this._headerTitle&&this._headerTitle.setText("PaperForge");break;case"paper":t.addClass("paper"),t.setText("Paper"),this._headerTitle&&this._headerTitle.setText("Paper"),this._currentPaperEntry&&this._currentPaperEntry.title?r=this._currentPaperEntry.title:this._currentPaperKey?(r=this._currentPaperKey,this._modeContextEl.createEl("span",{cls:"paperforge-mode-warning",text:"Not found in index"})):r="Unknown paper";break;case"collection":t.addClass("collection"),t.setText("Collection"),this._headerTitle&&this._headerTitle.setText("Collection"),r=this._currentDomain||"Unknown Domain";break}r&&this._modeContextEl.createEl("span",{cls:"paperforge-mode-name",text:r})}_setupEventSubscriptions(){let e=this.app.workspace.on("active-leaf-change",()=>{this._leafChangeTimer&&clearTimeout(this._leafChangeTimer),this._leafChangeTimer=setTimeout(()=>{let r=this._resolveModeForFile(this.app.workspace.getActiveFile()),n=r.mode,a=r.filePath;this._currentMode===n&&this._currentFilePath===a||this._detectAndSwitch()},300)});this._modeSubscribers.push({event:"active-leaf-change",ref:e});let t=this.app.vault.on("modify",r=>{r&&r.path&&r.path.endsWith("formal-library.json")&&(this._invalidateIndex(),this._refreshCurrentMode())});this._modeSubscribers.push({event:"modify",ref:t})}static async open(e){let t=e.app.workspace.getLeavesOfType(ye);if(t.length>0){e.app.workspace.revealLeaf(t[0]);return}let r=e.app.workspace.getRightLeaf(!1);r&&(await r.setViewState({type:ye,active:!0}),e.app.workspace.revealLeaf(r))}};var Ze=class extends H.Plugin{constructor(){super(...arguments);this._lastExportMtime=0;this._lastOcrMtimes={};this._autoSyncRunning=!1;this._lastSyncTime=null;this._pollTimer=null;this._embedProcess=null;this._embedProgress={current:0,total:0,key:""};this._embedStderr="";this._memoryStatusText=null}async onload(){await this.loadSettings(),this.saveSettings(),gt(this.app),this.registerView(ye,t=>new Ce(t));try{(0,H.addIcon)(Be,dt)}catch(t){}this.addRibbonIcon(Be,"PaperForge Dashboard",()=>Ce.open(this)),X.find(t=>t.id==="paperforge-ocr-redo")&&this.addRibbonIcon("reset","PaperForge: Redo OCR",()=>{let t=this.app.vault.adapter.basePath;new H.Notice("PaperForge: Redo OCR starting...");let{path:r,extraArgs:n}=N(t,this.settings,void 0,void 0);(0,ce.execFile)(r,[...n,"-m","paperforge","ocr","redo"],{cwd:t,timeout:6e5},(a,s,l)=>{if(a){new H.Notice("PaperForge: Redo OCR failed");return}new H.Notice("PaperForge: Redo OCR done")})}),this.addSettingTab(new Ve(this.app,this)),this.addCommand({id:"paperforge-status-panel",name:`PaperForge: ${i("guide_open")}`,callback:()=>Ce.open(this)});for(let t of X)this.addCommand({id:t.id,name:`PaperForge: ${t.title}`,callback:()=>{if(t.disabled){new H.Notice(`[i] ${t.disabledMsg||"This action is not yet available."}`,6e3);return}let r=this.app.vault.adapter.basePath;new H.Notice(`PaperForge: running ${t.cmd}...`);let{path:n,extraArgs:a=[]}=N(r,this.settings,void 0,void 0),s=Array.isArray(t.args)?[...t.args]:[];(0,ce.execFile)(n,[...a,"-m","paperforge",t.cmd,...s],{cwd:r,timeout:3e5},(l,o,c)=>{if(l){new H.Notice(`[!!] ${t.cmd} failed: ${(c||l.message).slice(0,120)}`,8e3);return}new H.Notice(`[OK] ${t.okMsg||o.trim().split(`
-`)[0].slice(0,80)}`)})}});this.settings.auto_update_on_startup===!0&&this.settings.setup_complete&&setTimeout(()=>this._autoUpdate(),3e3),this._startFilePolling(),this._firstLaunchSnapshotMigration(),this._checkReleaseNotes()}_firstLaunchSnapshotMigration(){let e=this.app.vault.adapter.basePath;if(!e)return;let r=le(e).memoryStatePath;if(!j.existsSync(r)){let n=N(e,this.settings,void 0,void 0);[["runtime-health","--json"],["memory","status","--json"],["embed","status","--json"]].forEach(s=>{let l=[...n.extraArgs,"-m","paperforge","--vault",e,...s];(0,ce.execFile)(n.path,l,{cwd:e,timeout:6e4,windowsHide:!0},()=>{})})}}_autoUpdate(){let e=this.app.vault.adapter.basePath,{path:t,extraArgs:r=[]}=N(e,this.settings,void 0,void 0),n=this.manifest.version,a=`paperforge==${n}`,s=`git+https://github.com/LLLin000/PaperForge.git@${n}`,l=(o,c)=>{(0,ce.spawn)(t,[...r,"-m","pip","install","--upgrade",o],{cwd:e,timeout:12e4,env:be()}).on("close",h=>c(h===0))};(0,ce.execFile)(t,[...r,"-c","import paperforge; print(paperforge.__version__)"],{cwd:e,timeout:1e4},(o,c)=>{let p=d=>{console.log(`[PaperForge] Auto-update: trying PyPI (paperforge==${n})`),l(a,m=>{if(m){console.log("[PaperForge] Auto-update: installed via PyPI"),new H.Notice(`[OK] PaperForge CLI ${d}`,5e3);return}console.warn("[PaperForge] Auto-update: PyPI failed, falling back to git..."),l(s,b=>{b&&(console.log("[PaperForge] Auto-update: installed via git"),new H.Notice(`[OK] PaperForge CLI ${d} (via git)`,5e3))})})};if(o){p("installed");return}let h=c.trim();h!==n&&p(`${h} -> ${n}`)})}_startFilePolling(){let e=this.app.vault.adapter.basePath;this._pollTimer=setInterval(()=>{this._checkExports(e),this._checkOcr(e)},12e4)}_checkExports(e){if(this._autoSyncRunning)return;let t=le(e).exportsDir;if(!j.existsSync(t))return;let r=0;try{j.readdirSync(t).forEach(n=>{if(!n.endsWith(".json"))return;let a=j.statSync(Se.join(t,n));a.mtimeMs>r&&(r=a.mtimeMs)})}catch(n){return}r>this._lastExportMtime&&(this._lastExportMtime=r,this._autoSync(e))}_autoSync(e){if(this._autoSyncRunning)return;this._autoSyncRunning=!0;let t=N(e,this.settings,void 0,void 0);if(!t.path){this._autoSyncRunning=!1;return}let r=`"${t.path}" -m paperforge --vault "${e}" sync`;(0,ce.exec)(r,{timeout:12e4,encoding:"utf-8"},(n,a,s)=>{this._autoSyncRunning=!1,this._memoryStatusText=null,n||(this._lastSyncTime=new Date().toLocaleTimeString());try{let l=le(e).exportsDir,o=0;j.readdirSync(l).forEach(c=>{c.endsWith(".json")&&(o=Math.max(o,j.statSync(Se.join(l,c)).mtimeMs))}),this._lastExportMtime=o}catch(l){}})}_checkOcr(e){if(this._autoSyncRunning)return;let t=le(e).ocrDir;if(j.existsSync(t))try{j.readdirSync(t,{withFileTypes:!0}).forEach(r=>{if(!r.isDirectory())return;let n=Se.join(t,r.name,"meta.json");if(!j.existsSync(n))return;let a=j.statSync(n),s=this._lastOcrMtimes[r.name]||0;if(a.mtimeMs<=s||(this._lastOcrMtimes[r.name]=a.mtimeMs,this._autoSyncRunning))return;this._autoSyncRunning=!0;let l=N(e,this.settings,void 0,void 0);if(!l.path){this._autoSyncRunning=!1;return}let o=`"${l.path}" -m paperforge --vault "${e}" sync`;(0,ce.exec)(o,{timeout:3e4,encoding:"utf-8"},()=>{this._autoSyncRunning=!1,this._memoryStatusText=null})})}catch(r){}}readPaperforgeJson(){let e=this.app.vault.adapter.basePath,t=Se.join(e,"paperforge.json"),r={system_dir:"System",resources_dir:"Resources",literature_dir:"Literature",base_dir:"Bases"};try{if(!j.existsSync(t))return r;let n=j.readFileSync(t,"utf-8"),a=JSON.parse(n),s=a.vault_config||{};return{system_dir:s.system_dir||a.system_dir||r.system_dir,resources_dir:s.resources_dir||a.resources_dir||r.resources_dir,literature_dir:s.literature_dir||a.literature_dir||r.literature_dir,base_dir:s.base_dir||a.base_dir||r.base_dir}}catch(n){return console.warn("PaperForge: Failed to read paperforge.json, using defaults",n),r}}savePaperforgeJson(e){let t=this.app.vault.adapter.basePath,r=Se.join(t,"paperforge.json"),n={};try{j.existsSync(r)&&(n=JSON.parse(j.readFileSync(r,"utf-8")))}catch(s){console.warn("PaperForge: Failed to read paperforge.json for update",s)}(!n.vault_config||typeof n.vault_config!="object")&&(n.vault_config={});let a=["system_dir","resources_dir","literature_dir","base_dir"];for(let s of a)e[s]!==void 0&&(n.vault_config[s]=e[s]);n.schema_version||(n.schema_version="2");for(let s of a)delete n[s];try{if(j.writeFileSync(r,JSON.stringify(n,null,2),"utf-8"),this.settings){let s=this.readPaperforgeJson();this.settings.system_dir=s.system_dir,this.settings.resources_dir=s.resources_dir,this.settings.literature_dir=s.literature_dir,this.settings.base_dir=s.base_dir}}catch(s){console.error("PaperForge: Failed to write paperforge.json",s),new H.Notice("PaperForge: Failed to save configuration to paperforge.json")}}onunload(){this._pollTimer&&clearInterval(this._pollTimer),this.app.workspace.detachLeavesOfType(ye)}async loadSettings(){this.settings=Object.assign({},Ae,await this.loadData()),this.settings.features&&Ae.features&&(this.settings.features=Object.assign({},Ae.features,this.settings.features||{})),this.settings.frozen_skills||(this.settings.frozen_skills={});let e=this.readPaperforgeJson();if(this.settings.system_dir=e.system_dir,this.settings.resources_dir=e.resources_dir,this.settings.literature_dir=e.literature_dir,this.settings.base_dir=e.base_dir,this.settings.python_path&&this.settings.python_path.trim()){let t=this.settings.python_path.trim();j.existsSync(t)?this.settings._python_path_stale=!1:(console.warn(`PaperForge: Saved python_path "${t}" no longer exists - showing stale warning`),this.settings._python_path_stale=!0)}}async saveSettings(){let e={};for(let t of Object.keys(Ae))t in this.settings&&(e[t]=this.settings[t]);await this.saveData(e)}_checkReleaseNotes(){let e=this.manifest.version;if(this.settings.last_seen_version===e)return;let a=(Xe().versions||[]).find(l=>l.version===e);class s extends H.Modal{constructor(o,c){super(o),this._entry=c}onOpen(){let{contentEl:o}=this;if(o.createEl("h2",{text:`PaperForge v${e} \u66F4\u65B0\u8BF4\u660E`}),this._entry){if(o.createEl("p",{text:this._entry.title,cls:"paperforge-modal-subtitle"}),this._entry.breaking_or_migration&&this._entry.breaking_or_migration.length>0){o.createEl("h4",{text:"\u884C\u4E3A\u53D8\u66F4 / \u8FC1\u79FB\u6CE8\u610F"});for(let c of this._entry.breaking_or_migration)o.createEl("p",{text:`\u2022 ${c}`,cls:"paperforge-modal-item"})}if(this._entry.new_features&&this._entry.new_features.length>0){o.createEl("h4",{text:"\u65B0\u529F\u80FD"});for(let c of this._entry.new_features)o.createEl("p",{text:`\u2022 ${c}`,cls:"paperforge-modal-item"})}if(this._entry.fixes&&this._entry.fixes.length>0){o.createEl("h4",{text:"\u4FEE\u590D"});for(let c of this._entry.fixes)o.createEl("p",{text:`\u2022 ${c}`,cls:"paperforge-modal-item"})}if(this._entry.recommended_actions&&this._entry.recommended_actions.length>0){let c=o.createEl("div",{cls:"paperforge-release-recommended"});c.createEl("h4",{text:"\u5EFA\u8BAE\u64CD\u4F5C",cls:""}),c.style.marginBottom="8px";for(let p of this._entry.recommended_actions)c.createEl("p",{text:`\u2022 ${p}`,cls:"paperforge-release-item-bold"})}}else o.createEl("p",{text:"\u7248\u672C\u5DF2\u66F4\u65B0\u81F3 v"+e+"\uFF0C\u8BF7\u524D\u5F80\u8BBE\u7F6E \u2192 \u66F4\u65B0\u4E0E\u624B\u518C \u67E5\u770B\u5B8C\u6574\u66F4\u65B0\u8BB0\u5F55\u3002"});new H.Setting(o).addButton(c=>c.setButtonText("\u77E5\u9053\u4E86").setCta().onClick(()=>{this.close()}))}onClose(){let{contentEl:o}=this;o.empty()}}new s(this.app,a).open(),this.settings.last_seen_version=e,this.saveSettings()}};
+`);if(_.trim())try{JSON.parse(_),navigator.clipboard.writeText(_).then(()=>{let w=`${x}s \u2014 ${_.length} chars copied`;this._showMessage("[OK] "+e.title+": "+w,"ok"),new I.Notice("[OK] "+e.okMsg+" \u2014 "+_.length+" chars")}).catch(w=>{this._showMessage("[!!] Clipboard write failed: "+w.message,"error"),new I.Notice("[!!] Clipboard error",6e3)})}catch(w){this._showMessage("[!!] Invalid JSON from "+e.title,"error"),new I.Notice("[!!] "+e.title+" returned invalid JSON: "+w.message.slice(0,100),8e3)}else this._showMessage("[!!] No output from context command","error"),new I.Notice("[!!] Context command returned empty output",8e3);this._fetchStats(!0)}else{let w=c.filter(S=>S.match(/updated \d+/)).pop()||c[c.length-1]||"",D=`${x}s \u2014 ${w}`;this._showMessage("[OK] "+e.title+": "+D,"ok"),new I.Notice("[OK] "+e.okMsg),this._contentEl&&this._contentEl.removeClass("switching"),this._cachedStats=null;try{this._fetchStats(!1)}catch(S){console.log("[PF] fetchStats error:",S)}console.log("[PF] close cmd="+e.cmd+" id="+e.id),e.cmd==="sync"&&He(this.app,this.app.plugins.plugins.paperforge,r)}}),o.on("error",b=>{t.removeClass("running"),this._contentEl&&this._contentEl.removeClass("switching"),this._showMessage("[!!] "+b.message,"error"),new I.Notice("[!!] Cannot start: "+b.message,8e3)})}_showMessage(e,t){this._messageEl&&(this._messageEl.setText(e),this._messageEl.className=`paperforge-message msg-${t}`)}_renderModeHeader(e){if(!this._modeContextEl)return;this._modeContextEl.empty();let t=this._modeContextEl.createEl("span",{cls:"paperforge-mode-badge"}),r="";switch(e){case"global":t.addClass("global"),t.setText("Global"),this._headerTitle&&this._headerTitle.setText("PaperForge");break;case"paper":t.addClass("paper"),t.setText("Paper"),this._headerTitle&&this._headerTitle.setText("Paper"),this._currentPaperEntry&&this._currentPaperEntry.title?r=this._currentPaperEntry.title:this._currentPaperKey?(r=this._currentPaperKey,this._modeContextEl.createEl("span",{cls:"paperforge-mode-warning",text:"Not found in index"})):r="Unknown paper";break;case"collection":t.addClass("collection"),t.setText("Collection"),this._headerTitle&&this._headerTitle.setText("Collection"),r=this._currentDomain||"Unknown Domain";break}r&&this._modeContextEl.createEl("span",{cls:"paperforge-mode-name",text:r})}_setupEventSubscriptions(){let e=this.app.workspace.on("active-leaf-change",()=>{this._leafChangeTimer&&clearTimeout(this._leafChangeTimer),this._leafChangeTimer=setTimeout(()=>{let r=this._resolveModeForFile(this.app.workspace.getActiveFile()),n=r.mode,a=r.filePath;this._currentMode===n&&this._currentFilePath===a||this._detectAndSwitch()},300)});this._modeSubscribers.push({event:"active-leaf-change",ref:e});let t=this.app.vault.on("modify",r=>{r&&r.path&&r.path.endsWith("formal-library.json")&&(this._invalidateIndex(),this._refreshCurrentMode())});this._modeSubscribers.push({event:"modify",ref:t})}static async open(e){let t=e.app.workspace.getLeavesOfType(ye);if(t.length>0){e.app.workspace.revealLeaf(t[0]);return}let r=e.app.workspace.getRightLeaf(!1);r&&(await r.setViewState({type:ye,active:!0}),e.app.workspace.revealLeaf(r))}};var Ze=class extends H.Plugin{constructor(){super(...arguments);this._lastExportMtime=0;this._lastOcrMtimes={};this._autoSyncRunning=!1;this._lastSyncTime=null;this._pollTimer=null;this._embedProcess=null;this._embedProgress={current:0,total:0,key:""};this._embedStderr="";this._memoryStatusText=null}async onload(){await this.loadSettings(),this.saveSettings(),gt(this.app),this.registerView(ye,t=>new Ce(t));try{(0,H.addIcon)(Be,dt)}catch(t){}this.addRibbonIcon(Be,"PaperForge Dashboard",()=>Ce.open(this)),X.find(t=>t.id==="paperforge-ocr-redo")&&this.addRibbonIcon("reset","PaperForge: Redo OCR",()=>{let t=this.app.vault.adapter.basePath;new H.Notice("PaperForge: Redo OCR starting...");let{path:r,extraArgs:n}=z(t,this.settings,void 0,void 0);(0,ce.execFile)(r,[...n,"-m","paperforge","ocr","redo"],{cwd:t,timeout:6e5},(a,s,l)=>{if(a){new H.Notice("PaperForge: Redo OCR failed");return}new H.Notice("PaperForge: Redo OCR done")})}),this.addSettingTab(new Ve(this.app,this)),this.addCommand({id:"paperforge-status-panel",name:`PaperForge: ${i("guide_open")}`,callback:()=>Ce.open(this)});for(let t of X)this.addCommand({id:t.id,name:`PaperForge: ${t.title}`,callback:()=>{if(t.disabled){new H.Notice(`[i] ${t.disabledMsg||"This action is not yet available."}`,6e3);return}let r=this.app.vault.adapter.basePath;new H.Notice(`PaperForge: running ${t.cmd}...`);let{path:n,extraArgs:a=[]}=z(r,this.settings,void 0,void 0),s=Array.isArray(t.args)?[...t.args]:[];(0,ce.execFile)(n,[...a,"-m","paperforge",t.cmd,...s],{cwd:r,timeout:3e5},(l,o,c)=>{if(l){new H.Notice(`[!!] ${t.cmd} failed: ${(c||l.message).slice(0,120)}`,8e3);return}new H.Notice(`[OK] ${t.okMsg||o.trim().split(`
+`)[0].slice(0,80)}`)})}});this.settings.auto_update_on_startup===!0&&this.settings.setup_complete&&setTimeout(()=>this._autoUpdate(),3e3),this._startFilePolling(),this._firstLaunchSnapshotMigration(),this._checkReleaseNotes()}_firstLaunchSnapshotMigration(){let e=this.app.vault.adapter.basePath;if(!e)return;let r=le(e).memoryStatePath;if(!j.existsSync(r)){let n=z(e,this.settings,void 0,void 0);[["runtime-health","--json"],["memory","status","--json"],["embed","status","--json"]].forEach(s=>{let l=[...n.extraArgs,"-m","paperforge","--vault",e,...s];(0,ce.execFile)(n.path,l,{cwd:e,timeout:6e4,windowsHide:!0},()=>{})})}}_autoUpdate(){let e=this.app.vault.adapter.basePath,{path:t,extraArgs:r=[]}=z(e,this.settings,void 0,void 0),n=this.manifest.version,a=`paperforge==${n}`,s=`git+https://github.com/LLLin000/PaperForge.git@${n}`,l=(o,c)=>{(0,ce.spawn)(t,[...r,"-m","pip","install","--upgrade",o],{cwd:e,timeout:12e4,env:be()}).on("close",h=>c(h===0))};(0,ce.execFile)(t,[...r,"-c","import paperforge; print(paperforge.__version__)"],{cwd:e,timeout:1e4},(o,c)=>{let p=d=>{console.log(`[PaperForge] Auto-update: trying PyPI (paperforge==${n})`),l(a,m=>{if(m){console.log("[PaperForge] Auto-update: installed via PyPI"),new H.Notice(`[OK] PaperForge CLI ${d}`,5e3);return}console.warn("[PaperForge] Auto-update: PyPI failed, falling back to git..."),l(s,b=>{b&&(console.log("[PaperForge] Auto-update: installed via git"),new H.Notice(`[OK] PaperForge CLI ${d} (via git)`,5e3))})})};if(o){p("installed");return}let h=c.trim();h!==n&&p(`${h} -> ${n}`)})}_startFilePolling(){let e=this.app.vault.adapter.basePath;this._pollTimer=setInterval(()=>{this._checkExports(e),this._checkOcr(e)},12e4)}_checkExports(e){if(this._autoSyncRunning)return;let t=le(e).exportsDir;if(!j.existsSync(t))return;let r=0;try{j.readdirSync(t).forEach(n=>{if(!n.endsWith(".json"))return;let a=j.statSync(Se.join(t,n));a.mtimeMs>r&&(r=a.mtimeMs)})}catch(n){return}r>this._lastExportMtime&&(this._lastExportMtime=r,this._autoSync(e))}_autoSync(e){if(this._autoSyncRunning)return;this._autoSyncRunning=!0;let t=z(e,this.settings,void 0,void 0);if(!t.path){this._autoSyncRunning=!1;return}let r=`"${t.path}" -m paperforge --vault "${e}" sync`;(0,ce.exec)(r,{timeout:12e4,encoding:"utf-8"},(n,a,s)=>{this._autoSyncRunning=!1,this._memoryStatusText=null,n||(this._lastSyncTime=new Date().toLocaleTimeString());try{let l=le(e).exportsDir,o=0;j.readdirSync(l).forEach(c=>{c.endsWith(".json")&&(o=Math.max(o,j.statSync(Se.join(l,c)).mtimeMs))}),this._lastExportMtime=o}catch(l){}})}_checkOcr(e){if(this._autoSyncRunning)return;let t=le(e).ocrDir;if(j.existsSync(t))try{j.readdirSync(t,{withFileTypes:!0}).forEach(r=>{if(!r.isDirectory())return;let n=Se.join(t,r.name,"meta.json");if(!j.existsSync(n))return;let a=j.statSync(n),s=this._lastOcrMtimes[r.name]||0;if(a.mtimeMs<=s||(this._lastOcrMtimes[r.name]=a.mtimeMs,this._autoSyncRunning))return;this._autoSyncRunning=!0;let l=z(e,this.settings,void 0,void 0);if(!l.path){this._autoSyncRunning=!1;return}let o=`"${l.path}" -m paperforge --vault "${e}" sync`;(0,ce.exec)(o,{timeout:3e4,encoding:"utf-8"},()=>{this._autoSyncRunning=!1,this._memoryStatusText=null})})}catch(r){}}readPaperforgeJson(){let e=this.app.vault.adapter.basePath,t=Se.join(e,"paperforge.json"),r={system_dir:"System",resources_dir:"Resources",literature_dir:"Literature",base_dir:"Bases"};try{if(!j.existsSync(t))return r;let n=j.readFileSync(t,"utf-8"),a=JSON.parse(n),s=a.vault_config||{};return{system_dir:s.system_dir||a.system_dir||r.system_dir,resources_dir:s.resources_dir||a.resources_dir||r.resources_dir,literature_dir:s.literature_dir||a.literature_dir||r.literature_dir,base_dir:s.base_dir||a.base_dir||r.base_dir}}catch(n){return console.warn("PaperForge: Failed to read paperforge.json, using defaults",n),r}}savePaperforgeJson(e){let t=this.app.vault.adapter.basePath,r=Se.join(t,"paperforge.json"),n={};try{j.existsSync(r)&&(n=JSON.parse(j.readFileSync(r,"utf-8")))}catch(s){console.warn("PaperForge: Failed to read paperforge.json for update",s)}(!n.vault_config||typeof n.vault_config!="object")&&(n.vault_config={});let a=["system_dir","resources_dir","literature_dir","base_dir"];for(let s of a)e[s]!==void 0&&(n.vault_config[s]=e[s]);n.schema_version||(n.schema_version="2");for(let s of a)delete n[s];try{if(j.writeFileSync(r,JSON.stringify(n,null,2),"utf-8"),this.settings){let s=this.readPaperforgeJson();this.settings.system_dir=s.system_dir,this.settings.resources_dir=s.resources_dir,this.settings.literature_dir=s.literature_dir,this.settings.base_dir=s.base_dir}}catch(s){console.error("PaperForge: Failed to write paperforge.json",s),new H.Notice("PaperForge: Failed to save configuration to paperforge.json")}}onunload(){this._pollTimer&&clearInterval(this._pollTimer),this.app.workspace.detachLeavesOfType(ye)}async loadSettings(){this.settings=Object.assign({},Ae,await this.loadData()),this.settings.features&&Ae.features&&(this.settings.features=Object.assign({},Ae.features,this.settings.features||{})),this.settings.frozen_skills||(this.settings.frozen_skills={});let e=this.readPaperforgeJson();if(this.settings.system_dir=e.system_dir,this.settings.resources_dir=e.resources_dir,this.settings.literature_dir=e.literature_dir,this.settings.base_dir=e.base_dir,this.settings.python_path&&this.settings.python_path.trim()){let t=this.settings.python_path.trim();j.existsSync(t)?this.settings._python_path_stale=!1:(console.warn(`PaperForge: Saved python_path "${t}" no longer exists - showing stale warning`),this.settings._python_path_stale=!0)}}async saveSettings(){let e={};for(let t of Object.keys(Ae))t in this.settings&&(e[t]=this.settings[t]);await this.saveData(e)}_checkReleaseNotes(){let e=this.manifest.version;if(this.settings.last_seen_version===e)return;let a=(Xe().versions||[]).find(l=>l.version===e);class s extends H.Modal{constructor(o,c){super(o),this._entry=c}onOpen(){let{contentEl:o}=this;if(o.createEl("h2",{text:`PaperForge v${e} \u66F4\u65B0\u8BF4\u660E`}),this._entry){if(o.createEl("p",{text:this._entry.title,cls:"paperforge-modal-subtitle"}),this._entry.breaking_or_migration&&this._entry.breaking_or_migration.length>0){o.createEl("h4",{text:"\u884C\u4E3A\u53D8\u66F4 / \u8FC1\u79FB\u6CE8\u610F"});for(let c of this._entry.breaking_or_migration)o.createEl("p",{text:`\u2022 ${c}`,cls:"paperforge-modal-item"})}if(this._entry.new_features&&this._entry.new_features.length>0){o.createEl("h4",{text:"\u65B0\u529F\u80FD"});for(let c of this._entry.new_features)o.createEl("p",{text:`\u2022 ${c}`,cls:"paperforge-modal-item"})}if(this._entry.fixes&&this._entry.fixes.length>0){o.createEl("h4",{text:"\u4FEE\u590D"});for(let c of this._entry.fixes)o.createEl("p",{text:`\u2022 ${c}`,cls:"paperforge-modal-item"})}if(this._entry.recommended_actions&&this._entry.recommended_actions.length>0){let c=o.createEl("div",{cls:"paperforge-release-recommended"});c.createEl("h4",{text:"\u5EFA\u8BAE\u64CD\u4F5C",cls:""}),c.style.marginBottom="8px";for(let p of this._entry.recommended_actions)c.createEl("p",{text:`\u2022 ${p}`,cls:"paperforge-release-item-bold"})}}else o.createEl("p",{text:"\u7248\u672C\u5DF2\u66F4\u65B0\u81F3 v"+e+"\uFF0C\u8BF7\u524D\u5F80\u8BBE\u7F6E \u2192 \u66F4\u65B0\u4E0E\u624B\u518C \u67E5\u770B\u5B8C\u6574\u66F4\u65B0\u8BB0\u5F55\u3002"});new H.Setting(o).addButton(c=>c.setButtonText("\u77E5\u9053\u4E86").setCta().onClick(()=>{this.close()}))}onClose(){let{contentEl:o}=this;o.empty()}}new s(this.app,a).open(),this.settings.last_seen_version=e,this.saveSettings()}};
diff --git a/paperforge/plugin/src/settings.ts b/paperforge/plugin/src/settings.ts
index 1ccdf6ae..266dbd95 100644
--- a/paperforge/plugin/src/settings.ts
+++ b/paperforge/plugin/src/settings.ts
@@ -1342,8 +1342,14 @@ export class PaperForgeSettingTab extends PluginSettingTab {
card.createEl("p", { text: item.ui.reason, cls: "setting-item-description" });
const btn = card.createEl("button", { text: item.ui.primaryAction === "rebuild" ? t("ocr_maint_rebuild_btn") : t("ocr_maint_redo_btn") });
btn.style.cssText = "padding:4px 10px; border-radius:4px; cursor:pointer; font-size:12px;";
- btn.dataset.action = item.ui.primaryAction || "";
- btn.dataset.key = item.row.key;
+ btn.addEventListener("click", () => {
+ const keys = [item.row.key];
+ if (item.ui.primaryAction === "rebuild") {
+ execFile(py.path, ["-m", "paperforge", "ocr", "rebuild", ...keys], { cwd: vaultPath, timeout: 120000, windowsHide: true }, () => { new Notice(t("ocr_maint_rebuild_btn") + " — " + item.row.key); });
+ } else if (item.ui.primaryAction === "redo") {
+ execFile(py.path, ["-m", "paperforge", "ocr", "redo", ...keys], { cwd: vaultPath, timeout: 300000, windowsHide: true }, () => { new Notice(t("ocr_maint_redo_btn") + " — " + item.row.key); });
+ }
+ });
}
}