mirror of
https://github.com/lllin000/PaperForge.git
synced 2026-07-22 06:50:53 +00:00
- Remove paperforge/plugin/src/services/db.ts (sql.js wrapper, initDatabase/searchMetadata/SearchResultItem) - Remove paperforge/plugin/sql-wasm.wasm (644KB binary) - Remove sql.js and @types/sql.js from package.json; npm install to update lockfile - dashboard.ts: remove import of db.ts, remove _sqlJsInitialized/_sqlJsFailed state, remove the sql.js search path block entirely — all searches go straight to CLI spawn. Clean up stale comments. - Bundle drops from 346KB to 167KB; 6 test files / 58 tests still pass
54 lines
167 KiB
JavaScript
54 lines
167 KiB
JavaScript
"use strict";var Rt=Object.create;var Le=Object.defineProperty;var Tt=Object.getOwnPropertyDescriptor;var Dt=Object.getOwnPropertyNames;var Bt=Object.getPrototypeOf,At=Object.prototype.hasOwnProperty;var Ot=(h,u)=>()=>(u||h((u={exports:{}}).exports,u),u.exports),Lt=(h,u)=>{for(var e in u)Le(h,e,{get:u[e],enumerable:!0})},rt=(h,u,e,t)=>{if(u&&typeof u=="object"||typeof u=="function")for(let r of Dt(u))!At.call(h,r)&&r!==e&&Le(h,r,{get:()=>u[r],enumerable:!(t=Tt(u,r))||t.enumerable});return h};var $=(h,u,e)=>(e=h!=null?Rt(Bt(h)):{},rt(u||!h||!h.__esModule?Le(e,"default",{value:h,enumerable:!0}):e,h)),Mt=h=>rt(Le({},"__esModule",{value:!0}),h);var qe=Ot((qt,Nt)=>{Nt.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 Vt={};Lt(Vt,{default:()=>He});module.exports=Mt(Vt);var K=require("obsidian"),H=$(require("fs")),ke=$(require("path")),ie=require("child_process");var _e="paperforge-status",Ce="paperforge",st='<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M4 19.5A2.5 2.5 0 0 1 6.5 17H20"></path><path d="M6.5 2H20v20H6.5A2.5 2.5 0 0 1 4 19.5v-15A2.5 2.5 0 0 1 6.5 2z"></path><line x1="8" y1="7" x2="16" y2="7"></line><line x1="8" y1="11" x2="14" y2="11"></line></svg>',Y=[{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"}],Fe={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 nt(h,u){if(!u||!u.note_path)return u;let e=h.vault.getAbstractFileByPath(u.note_path);if(!e)return u;let t=h.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 Ke(h,u){return h&&{...h,...u}}var We={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",maintenance_group_retry:"Needs Retry",maintenance_group_rebuild:"Can Rebuild",maintenance_group_legacy:"Upgrade Available (Optional)",maintenance_btn_retry:"Retry",maintenance_btn_rebuild:"Rebuild",maintenance_btn_upgrade:"Upgrade",maintenance_refresh_spinning:"Updating\u2026",maintenance_all_good:"\u2705 All good \u2014 no action needed",maintenance_n_pending:"{n} need attention",version_panel_title:"Version History",version_panel_back:"Back",version_filter_placeholder:"Filter papers...",version_papers_count:"{n} papers",version_current:"current",version_restore_btn:"Restore",version_compare_btn:"Compare",version_restore_selected:"Restore selected",version_clear_old:"Clear old versions (free {size})",version_no_backups:"No version history available",version_restore_confirm:"Restore {label} for {paper}?",version_restore_done:"Restored {label}",version_compare_title:"{vA} vs {vB}",version_compare_paragraphs:"{n} paragraphs changed",version_error_read:"Cannot read version data"},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",maintenance_group_retry:"\u9700\u8981\u91CD\u8BD5",maintenance_group_rebuild:"\u53EF\u91CD\u5EFA\u7ED3\u679C",maintenance_group_legacy:"\u53EF\u5347\u7EA7\u65E7\u7ED3\u679C\uFF08\u53EF\u9009\uFF09",maintenance_btn_retry:"\u91CD\u8BD5",maintenance_btn_rebuild:"\u91CD\u5EFA",maintenance_btn_upgrade:"\u5347\u7EA7",maintenance_refresh_spinning:"\u6B63\u5728\u66F4\u65B0\u2026",maintenance_all_good:"\u2705 \u5168\u90E8\u6B63\u5E38",maintenance_n_pending:"{n} \u7BC7\u9700\u8981\u5904\u7406",version_panel_title:"\u7248\u672C\u5386\u53F2",version_panel_back:"\u8FD4\u56DE",version_filter_placeholder:"\u641C\u7D22\u8BBA\u6587...",version_papers_count:"{n} \u7BC7\u8BBA\u6587",version_current:"\u5F53\u524D",version_restore_btn:"\u6062\u590D",version_compare_btn:"\u5BF9\u6BD4",version_restore_selected:"\u6062\u590D\u9009\u4E2D\u7248\u672C",version_clear_old:"\u6E05\u9664\u65E7\u7248\u672C (\u91CA\u653E {size})",version_no_backups:"\u6CA1\u6709\u53EF\u6062\u590D\u7684\u5386\u53F2\u7248\u672C",version_restore_confirm:"\u786E\u8BA4\u5C06 {paper} \u6062\u590D\u5230 {label}\uFF1F",version_restore_done:"\u5DF2\u6062\u590D\u5230 {label}",version_compare_title:"{vA} vs {vB}",version_compare_paragraphs:"{n} \u6BB5\u6709\u53D8\u5316",version_error_read:"\u65E0\u6CD5\u8BFB\u53D6\u7248\u672C\u6570\u636E"}},Ze=null;function It(h){try{let u=h.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 at(h){Ze=It(h)==="zh"?We.zh:We.en}function o(h){return Ze&&Ze[h]||We.en[h]||h}var C=require("obsidian"),N=$(require("fs")),Z=$(require("path")),kt=$(require("os")),j=require("child_process");var wt=$(qe());var ne=$(require("fs")),se=$(require("path")),ot=$(require("os")),le=require("child_process"),Je=null,it=!1;function L(h,u,e,t){let r=e||ne,n=t||le.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=[se.join(h,".paperforge-test-venv","Scripts","python.exe"),se.join(h,".venv","Scripts","python.exe"),se.join(h,"venv","Scripts","python.exe")];for(let l of a)try{if(r.existsSync(l))return{path:l,source:"auto-detected",extraArgs:[]}}catch(i){}let s=[{path:"py",extraArgs:["-3"]},{path:"python",extraArgs:[]},{path:"python3",extraArgs:[]}];for(let l of s)try{let i=n(l.path,[...l.extraArgs,"--version"],{encoding:"utf-8",timeout:5e3,windowsHide:!0});if(i&&i.toLowerCase().includes("python"))return{path:l.path,source:"auto-detected",extraArgs:l.extraArgs}}catch(i){}return{path:"python",source:"auto-detected",extraArgs:[]}}function lt(h,u,e,t,r){t===void 0&&(t=1e4);let n=r||le.execFile;return new Promise(a=>{n(h,["-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 i=l&&l.trim()||null;a(i===u?{status:"match",pyVersion:i,pluginVersion:u,error:null}:{status:"mismatch",pyVersion:i,pluginVersion:u,error:null})})})}function ct(h,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:h,url:r,args:a,pypiArgs:n,gitArgs:a,timeout:12e4}}function pt(h,u,e,t,r,n){let a=r||le.spawn;return new Promise(s=>{let l=Date.now(),i={cwd:e,timeout:t,windowsHide:!0};n&&(i.env=n);let c=a(h,u,i),d=[],g=[];c.stdout.on("data",p=>{d.push(p.toString("utf-8"))}),c.stderr.on("data",p=>{g.push(p.toString("utf-8"))}),c.on("close",p=>{s({stdout:d.join(""),stderr:g.join(""),exitCode:p,elapsed:Date.now()-l})}),c.on("error",p=>{s({stdout:d.join(""),stderr:g.join("")+`
|
|
`+p.message,exitCode:-1,elapsed:Date.now()-l})})})}function Ue(){if(it)return Je;it=!0;try{let h;if(process.platform==="win32"){let u=process.env.ComSpec||"C:\\Windows\\System32\\cmd.exe";h=(0,le.execFileSync)(u,["/c","where","git"],{timeout:5e3,windowsHide:!0,encoding:"utf-8"})}else h=(0,le.execFileSync)("which",["git"],{timeout:5e3,encoding:"utf-8"});if(h){let u=h.split(`
|
|
`)[0].trim();u&&(Je=se.dirname(u))}}catch(h){}return Je}function me(){let h={...process.env},u=process.platform,e=ot.homedir(),t=[],r=Ue();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=h.PATH||"";return h.PATH=[...t,n].filter(Boolean).join(se.delimiter),h}function dt(h){return String(h).toLowerCase().replace(/[^a-z0-9]/g,"").includes("betterbibtex")}function Ge(h){if(!h)return!1;try{if(!ne.existsSync(h))return!1;for(let u of ne.readdirSync(h))if(dt(u))return!0}catch(u){}return!1}function Me(h){if(!h)return!1;try{if(!ne.existsSync(h))return!1;for(let u of ne.readdirSync(h)){let e=se.join(h,u,"extensions");try{if(!ne.existsSync(e))continue;for(let t of ne.readdirSync(e))if(dt(t))return!0}catch(t){}}}catch(u){}return!1}var ye=$(require("fs")),W=$(require("path")),ut=require("child_process"),ae=null;function zt(h,u){let e=u||ye,t=W.join(h,"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 Q(h,u){let e=zt(h,u),t=W.join(h,e.system_dir,"PaperForge");return{vault:h,systemDir:t,indexesDir:W.join(t,"indexes"),logsDir:W.join(t,"logs"),dbPath:W.join(t,"indexes","paperforge.db"),memoryStatePath:W.join(t,"indexes","memory-runtime-state.json"),vectorStatePath:W.join(t,"indexes","vector-runtime-state.json"),healthStatePath:W.join(t,"indexes","runtime-health.json"),buildStatePath:W.join(t,"indexes","vector-build-state.json"),orphanStatePath:W.join(t,"indexes","sync-orphan-state.json"),exportsDir:W.join(t,"exports"),ocrDir:W.join(t,"ocr"),pluginDataPath:W.join(h,".obsidian","plugins","paperforge","data.json"),pfJsonPath:W.join(h,"paperforge.json"),configWarning:e._warning}}function Xe(h){try{return ye.existsSync(h)?JSON.parse(ye.readFileSync(h,"utf-8")):null}catch(u){return null}}function $t(h){let u=Q(h);return Xe(u.memoryStatePath)}function Re(h){let u=Q(h);return Xe(u.vectorStatePath)}function Ye(h){let u=Q(h);return Xe(u.healthStatePath)}function ht(h){var e;let u=Ye(h);return!!(u&&((e=u.summary)==null?void 0:e.status)==="ok")}function Ie(h){let u=$t(h);return!u||u.paper_count_db===0?"DB not found. Run paperforge memory build.":"Papers: "+u.paper_count_db+" | "+(u.fresh?"fresh":"stale")}function be(h){var t,r,n;let u=Re(h);return u?u.healthy===!1?"Vector index unreadable - rebuild required":"Chunks: "+(((t=u.chunk_count)!=null?t:0)+((r=u.body_chunk_count)!=null?r:0)+((n=u.object_chunk_count)!=null?n:0))+" | "+u.model+" | "+u.mode:"Status unavailable"}function ce(h,u){if(ae)return ae;if(u&&u.python_path&&u.python_path.trim()){let r=u.python_path.trim();if(ye.existsSync(r))return ae={path:r,source:"manual",extraArgs:[]},ae}let e=[W.join(h,".paperforge-test-venv","Scripts","python.exe"),W.join(h,".venv","Scripts","python.exe"),W.join(h,"venv","Scripts","python.exe")];for(let r=0;r<e.length;r++)if(ye.existsSync(e[r]))return ae={path:e[r],source:"auto-detected",extraArgs:[]},ae;let t=[{path:"py",extraArgs:["-3"]},{path:"python",extraArgs:[]},{path:"python3",extraArgs:[]}];for(let r=0;r<t.length;r++)try{let n=t[r],a=(0,ut.execFileSync)(n.path,n.extraArgs.concat(["--version"]),{encoding:"utf-8",timeout:5e3,windowsHide:!0});if(a&&a.toLowerCase().indexOf("python")!==-1)return ae={path:n.path,source:"auto-detected",extraArgs:n.extraArgs},ae}catch(n){}return ae={path:"python",source:"auto-detected",extraArgs:[]},ae}function Qe(h,u,e){return!h||typeof h!="object"||!Object.prototype.hasOwnProperty.call(h,u)?!!e:!!h[u]}function ft(h,u,e){let t=!Qe(h,u,e);return h&&typeof h=="object"&&(h[u]=t),t}var G=require("obsidian"),te=$(require("fs")),_t=$(require("path")),mt=$(require("https")),De=require("child_process");function gt(h,u){return!u||!u.trim()?{blocked:!0,reason:"zotero"}:h?{blocked:!1}:{blocked:!0,reason:"ocr"}}var et=class extends G.Modal{constructor(e,t,r,n){super(e);this._rowEls=[];this.orphans=t.map((a,s)=>({...a,_selected:!0,_idx:s})),this.vaultPath=r,this.py=n}_updateUI(){let e=this.orphans.filter(t=>t._selected);this._countEl.setText(o("orphan_delete_selected").replace("{count}",String(e.length))),this._selectAllBtn.setText(e.length===this.orphans.length?o("orphan_deselect_all"):o("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:o("orphan_title").replace("{count}",String(this.orphans.length))}),e.createEl("p",{cls:"paperforge-modal-desc",text:o("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 i=l.createEl("span",{cls:"paperforge-orphan-tags"});i.createEl("span",{cls:"paperforge-tag "+(n.has_pdf?"tag-pdf":"tag-nopdf"),text:n.has_pdf?"PDF":"no PDF"}),n.collection_path&&i.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:o("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 G.Notice(o("orphan_none_selected"));return}if(this._countEl.setText("Deleting..."),this._countEl.setAttr("disabled",""),this._selectAllBtn.setAttr("disabled",""),!this.py||!this.py.path){new G.Notice("PaperForge: Python not found"),this.close();return}let a=n.map(s=>s.key);(0,De.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 G.Notice("PaperForge: prune failed"),this.close();return}try{let i=JSON.parse(l),c=i.data&&i.data.deleted||[];new G.Notice("Deleted "+c.length+" orphan workspace(s)")}catch(i){new G.Notice("PaperForge: prune done")}this.close()})})}onClose(){this.contentEl.empty()}};function Ne(h,u,e){console.log("[PF] checkOrphanState called");try{let r=Q(e).orphanStatePath;if(!te.existsSync(r)){console.log("[PF] orphan file NOT FOUND");return}console.log("[PF] orphan file FOUND");let n=te.readFileSync(r,"utf-8"),s=JSON.parse(n).orphans||[];if(console.log("[PF] orphans count:",s.length),s.length===0)return;let l=ce(e,u.settings);console.log("[PF] py.path:",l?l.path:"null"),new et(h,s,e,l).open(),te.unlinkSync(r),console.log("[PF] orphan file cleaned")}catch(t){console.log("[PF] checkOrphanState exception:",t.message||t)}}var Te=class extends G.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=[o("wizard_step1"),o("wizard_step2"),o("wizard_step3"),o("wizard_step4"),o("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":""} ${a<this._step?"done":""}`});s.createEl("span",{cls:"paperforge-step-num",text:`${a}`}),s.createEl("span",{cls:"paperforge-step-label",text:r})})}_renderStepContent(){let e=this.contentEl.createEl("div",{cls:"paperforge-step-content"});switch(this._step){case 1:this._stepOverview(e);break;case 2:this._stepDirectories(e);break;case 3:this._stepKeys(e);break;case 4:this._stepInstall(e);break;case 5:this._stepComplete(e);break}}_renderNavigation(){let e=this.contentEl.createEl("div",{cls:"paperforge-step-nav"});this._step>1&&e.createEl("button",{cls:"paperforge-step-btn",text:o("nav_prev")}).addEventListener("click",()=>{this._step--,this._showSkipConfirm=!1,this._render()}),this._step<5?e.createEl("button",{cls:"paperforge-step-btn mod-cta",text:o("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:o("nav_close")}).addEventListener("click",()=>this.close())}_validateStep3(){let e=this.plugin.settings,t=gt(this._apiKeyValidated,e.zotero_data_dir);if(t.reason==="ocr")return t;let r=(e.zotero_data_dir||"").trim();if(!r)return new G.Notice("Zotero \u6570\u636E\u76EE\u5F55\u4E3A\u5FC5\u586B\u9879\uFF0C\u8BF7\u586B\u5199\u8DEF\u5F84"),{blocked:!0,reason:"zotero"};if(!te.existsSync(r))return new G.Notice("Zotero \u6570\u636E\u76EE\u5F55\u8DEF\u5F84\u4E0D\u5B58\u5728"),{blocked:!0,reason:"zotero"};if(!te.statSync(r).isDirectory())return new G.Notice("Zotero \u6570\u636E\u76EE\u5F55\u8DEF\u5F84\u4E0D\u662F\u4E00\u4E2A\u76EE\u5F55"),{blocked:!0,reason:"zotero"};let n=_t.join(r,"storage");return!te.existsSync(n)||!te.statSync(n).isDirectory()?(new G.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:o("wizard_title")}),e.createEl("p",{text:o("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:o("wizard_preview"),cls:"paperforge-modal-hint"}),e.createEl("p",{text:o("wizard_safety"),cls:"paperforge-modal-hint"});let c=e.createEl("div",{cls:"paperforge-summary"}),d=[{label:o("dir_resources"),val:`${r}/${t.resources_dir||"Resources"}`},{label:o("dir_notes"),val:`${r}/${t.resources_dir||"Resources"}/${t.literature_dir||"Literature"}`},{label:o("dir_base"),val:`${r}/${t.base_dir||"Bases"}`},{label:o("dir_system"),val:`${r}/${t.system_dir||"System"}`}];for(let g of d){let p=c.createEl("div",{cls:"paperforge-summary-row"});p.createEl("span",{cls:"paperforge-summary-label",text:g.label}),p.createEl("span",{cls:"paperforge-summary-value",text:g.val})}}_stepDirectories(e){e.createEl("h2",{text:o("wizard_step2")}),e.createEl("p",{text:o("wizard_intro")});let t=this.plugin.settings,r=this.app.vault.adapter.basePath;this._modalField(e,o("dir_vault"),r,!0),e.createEl("p",{text:o("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:o("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:o("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:o("wizard_safety"),cls:"paperforge-modal-hint"});let n=e.createEl("div",{cls:"paperforge-summary"}),a=[{label:o("dir_resources"),val:`${r}/${t.resources_dir||""}`},{label:o("dir_notes"),val:`${r}/${t.resources_dir||""}/${t.literature_dir||""}`},{label:o("dir_system"),val:`${r}/${t.system_dir||""}`},{label:o("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:o("wizard_step3")}),this._showSkipConfirm){this._renderSkipConfirm(e);return}let t=this.plugin.settings;e.createEl("p",{text:o("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:o("label_agent")});let a=n.createEl("select",{cls:"paperforge-modal-select"});for(let g of r){let p=a.createEl("option",{text:g.name,attr:{value:g.key}});g.key===(t.agent_platform||"opencode")&&(p.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:o("wizard_keys_hint"),cls:"paperforge-modal-hint"});let s=e.createEl("div",{cls:"paperforge-modal-field"});s.createEl("label",{cls:"paperforge-modal-label",text:o("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 i=s.createEl("button",{cls:"paperforge-step-btn",text:"\u9A8C\u8BC1"});i.addEventListener("click",()=>this._validateApiKey(l.value,i)),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:o("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:o("field_zotero_data")});let d=c.createEl("input",{cls:"paperforge-modal-input",attr:{type:"text",placeholder:o("field_zotero_placeholder")}});d.value=t.zotero_data_dir||"",d.addEventListener("input",()=>{t.zotero_data_dir=d.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=mt.request(n,s=>{t.disabled=!1,t.textContent="\u9A8C\u8BC1";let l="";s.on("data",i=>l+=i),s.on("end",()=>{try{let i=JSON.parse(l);s.statusCode===400&&i.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(i){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:o("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:o("wizard_skip_ocr_continue")}).addEventListener("click",()=>{this._showSkipConfirm=!1,this._step++,this._render()}),t.createEl("button",{cls:"paperforge-step-btn",text:o("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 i=this.plugin.settings;l.addEventListener("input",()=>{i[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 i=this.plugin.settings;l.addEventListener("input",()=>{i[r]=l.value,this._pendingSave&&clearTimeout(this._pendingSave),this._pendingSave=setTimeout(()=>{this.plugin.saveSettings(),this._pendingSave=null},500)})}_stepInstall(e){e.createEl("h2",{text:o("wizard_step4")}),this._installLog=e.createEl("div",{cls:"paperforge-install-log"});let t=e.createEl("button",{cls:"paperforge-step-btn mod-cta",text:o("install_btn")});t.addEventListener("click",()=>this._runInstall(t))}async _runInstall(e){var s,l,i,c,d,g;e.disabled=!0,e.textContent=o("install_btn_running"),this._installLog.setText(o("install_validating")+`
|
|
`),this._log(o("install_validating"));let t=this.plugin.settings,r=this._validate();if(r.length>0){this._log(o("validate_fail")+":"),r.forEach(p=>this._log(" \u2717 "+p)),e.disabled=!1,e.textContent=o("install_btn_retry");return}let n=(p,f={})=>new Promise((y,b)=>{let{path:m,extraArgs:x=[]}=L(t.vault_path.trim(),this.plugin.settings,void 0,void 0),w=(0,De.spawn)(m,[...x,...p],{cwd:t.vault_path.trim(),env:me(),timeout:12e4,...f}),E="",_="";w.stdout.on("data",v=>{let k=v.toString("utf-8");E+=k,f.logStdout&&this._processSetupOutput(k)}),w.stderr.on("data",v=>{let k=v.toString("utf-8");_+=k,this._log("[stderr] "+k.trim())}),w.on("close",v=>{v===0?y({stdout:E,stderr:_}):b(new Error(_.trim()||E.trim()||`exit code ${v}`))}),w.on("error",v=>b(v))}),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 p=!0;try{await n(["-c","import paperforge"])}catch(f){p=!1}if(!p){this._log(o("install_bootstrapping"));let f=this.plugin.manifest.version;this._log(`[install] Trying PyPI: pip install paperforge==${f}`);let y=["-m","pip","install","--upgrade"];process.platform!=="win32"&&y.push("--user"),y.push(`paperforge==${f}`);try{await n(y,{logStdout:!0})}catch(b){this._log(`[install] PyPI failed, falling back to git: git+https://...@v${f}`),console.warn("[PaperForge] PyPI install failed, falling back to git:",(s=b.message)==null?void 0:s.slice(0,200));let m=["-m","pip","install","--upgrade"];process.platform!=="win32"&&m.push("--user"),m.push(`git+https://github.com/LLLin000/PaperForge.git@v${f}`),await n(m,{logStdout:!0})}}await n(a,{logStdout:!0,env:me()}),this._log(o("install_complete")),t.setup_complete=!0,await this.plugin.saveSettings(),setTimeout(()=>{this._step=5,this._render()},800)}catch(p){console.error("PaperForge setup failed:",p.message);let f=this._formatSetupError(p.message);this._log(o("install_failed")+f);let y=(l=this._installLog.parentElement)==null?void 0:l.createEl("button",{cls:"paperforge-copy-diag-btn",text:o("error_copy_diagnostic")||"Copy diagnostic"});if(y){let b=p.message,m=((c=(i=this.plugin)==null?void 0:i.settings)==null?void 0:c.python_path)||"auto",x=((g=(d=this.plugin)==null?void 0:d.manifest)==null?void 0:g.version)||"?",w=process.platform+" "+process.arch,E,_;try{E=Ue()||"(not found)"}catch(P){E="(error)"}try{_=L(t.vault_path.trim(),this.plugin.settings,void 0,void 0)}catch(P){_=null}let v=(process.env.PATH||"").length,k=(process.env.PATH||"").toLowerCase().includes("git"),S=["[PaperForge Diagnostic]","Category: "+f,"Plugin version: "+x,"Python: "+m,"Resolved Python: "+((_==null?void 0:_.path)||"?"),"OS: "+w,"Vault path: "+(t.vault_path||"?"),"--- Git ---","Git dir (resolved): "+E,"PATH length: "+v+" chars","PATH contains git: "+k,"--- Raw error ---",b.slice(0,2e3)].join(`
|
|
`);y.addEventListener("click",()=>{navigator.clipboard.writeText(S).then(()=>{y.setText(o("error_copied")||"Copied!"),setTimeout(()=>{y.setText(o("error_copy_diagnostic")||"Copy diagnostic")},3e3)}).catch(()=>{new G.Notice("[!!] Clipboard write failed",6e3)})})}e.disabled=!1,e.textContent=o("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(o("validate_vault")),(!t.resources_dir||!t.resources_dir.trim())&&e.push(o("validate_resources")),(!t.literature_dir||!t.literature_dir.trim())&&e.push(o("validate_notes")),(!t.base_dir||!t.base_dir.trim())&&e.push(o("validate_base")),(!t.paddleocr_api_key||!t.paddleocr_api_key.trim())&&this._log(" ! "+o("validate_key")+" "+o("optional_later")),(!t.zotero_data_dir||!t.zotero_data_dir.trim())&&this._log(" ! "+o("validate_zotero")+" "+o("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:o("complete_title")});let t=e.createEl("div",{cls:"paperforge-summary"});t.createEl("div",{cls:"paperforge-summary-title",text:o("complete_summary")});let r=this.plugin.settings,n=this.app.vault.adapter.basePath,a=[{label:o("dir_vault"),val:n},{label:o("dir_resources"),val:`${n}/${r.resources_dir}`},{label:o("dir_notes"),val:`${n}/${r.resources_dir}/${r.literature_dir}`},{label:o("dir_base"),val:`${n}/${r.base_dir}`},{label:o("dir_system"),val:`${n}/${r.system_dir}`},{label:"API Key",val:r.paddleocr_api_key?o("api_key_set"):o("api_key_missing")},{label:o("field_zotero_data"),val:r.zotero_data_dir||o("not_set")}];for(let d of a){let g=t.createEl("div",{cls:"paperforge-summary-row"});g.createEl("span",{cls:"paperforge-summary-label",text:d.label}),g.createEl("span",{cls:"paperforge-summary-value",text:d.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 d=n,{path:g,extraArgs:p=[]}=L(d,this.plugin.settings,void 0,void 0);(0,De.execFile)(g,[...p,"-c","import paperforge; print(paperforge.__version__)"],{cwd:d,timeout:1e4},(f,y)=>{!f&&y&&(l.textContent="v"+y.trim())})}for(let d of a){let g=t.createEl("div",{cls:"paperforge-summary-row"});g.createEl("span",{cls:"paperforge-summary-label",text:d.label}),g.createEl("span",{cls:"paperforge-summary-value",text:d.val})}e.createEl("h3",{text:o("complete_next")});let i=e.createEl("div",{cls:"paperforge-nextsteps"}),c=[[o("complete_step4"),o("complete_step4_desc")],["",`${o("complete_export_path")} ${n}/${r.system_dir}/PaperForge/exports/`],[o("complete_step1"),o("complete_step1_desc")],[o("complete_step2"),o("complete_step2_desc")],[o("complete_step3"),o("complete_step3_desc")]];for(let[d,g]of c){let p=i.createEl("div",{cls:"paperforge-nextstep-item"});d&&p.createEl("strong",{text:d}),p.createEl("span",{text:g})}}};var xe=$(require("fs")),ze=$(require("path")),vt=require("child_process");function bt(h){return ze.join(h,"System","PaperForge","cache","ocr_maintenance.json")}function xt(h){try{let u=bt(h),e=xe.readFileSync(u,"utf-8");return JSON.parse(e)}catch(u){return null}}function $e(h,u){let e=bt(h),t=ze.dirname(e);xe.mkdirSync(t,{recursive:!0}),xe.writeFileSync(e,JSON.stringify(u,null,2),"utf-8")}function yt(h,u,e){return new Promise((t,r)=>{(0,vt.execFile)(h,u,e,(n,a)=>{n?r(n):t(a)})})}async function Et(h,u,e,t){let r=await yt(u,[...e,"-m","paperforge","ocr","list","--manifest"],{cwd:h,timeout:3e4}),n=JSON.parse(r);if(t){let d=Object.keys(t.manifest),g=Object.keys(n);if(d.length===g.length&&d.every(f=>t.manifest[f]===n[f]))return{data:Object.values(t.papers).filter(y=>y.visible_in_maintenance),changed:!1}}let a=Object.keys(n).filter(d=>!(t!=null&&t.manifest[d])||t.manifest[d]!==n[d]),s=await yt(u,[...e,"-m","paperforge","ocr","list","--json","--keys",...a],{cwd:h,timeout:3e4}),l=JSON.parse(s),i={manifest:n,papers:{},cached_at:new Date().toISOString()};if(t!=null&&t.papers)for(let d of Object.keys(n))t.papers[d]&&(i.papers[d]=t.papers[d]);for(let d of l)i.papers[d.key]=d;return $e(h,i),{data:Object.values(i.papers).filter(d=>d.visible_in_maintenance),changed:!0}}var je=class extends C.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); }
|
|
.paperforge-tab-content { display: none; }
|
|
.paperforge-tab-content--active { display: block; }
|
|
.paperforge-skills-collapse-header { display: flex !important; align-items: center; cursor: pointer; padding: 6px 0 !important; margin: 0 !important; }
|
|
.paperforge-skills-collapse-header h4 { margin: 0 !important; }
|
|
.paperforge-skills-collapse-content { margin: 0 !important; padding: 0 !important; }
|
|
.paperforge-skills-group { margin-bottom: 10px; }
|
|
.paperforge-skills-group:last-child { margin-bottom: 0; }
|
|
.vertical-tab-content-container { overflow-y: scroll !important; }
|
|
.paperforge-release-card { border: 1px solid var(--background-modifier-border); border-radius: 6px; padding: 12px; margin-bottom: 12px; }
|
|
.paperforge-release-header { margin-bottom: 8px; }
|
|
.paperforge-release-date { color: var(--text-muted); font-size: 12px; }
|
|
.paperforge-release-section { margin-bottom: 6px; }
|
|
.paperforge-release-label { font-weight: 600; color: var(--text-accent); margin-bottom: 2px; font-size: 13px; }
|
|
.paperforge-release-item { font-size: 13px; margin-left: 8px; color: var(--text-muted); }
|
|
.paperforge-release-item-bold { font-size: 13px; margin-left: 8px; font-weight: 600; color: var(--text-normal); }
|
|
.paperforge-release-recommended { background: rgba(var(--color-orange-rgb, 255,166,0), 0.08); border-radius: 4px; padding: 6px 8px; }
|
|
.paperforge-manual-links { margin-top: 8px; }
|
|
.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:o("tab_setup")||"\u5B89\u88C5"},{id:"features",label:o("tab_features")||"\u529F\u80FD"},{id:"maintenance",label:o("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&&(N.existsSync(Z.join(t,"paperforge.json"))||(this.plugin.settings.setup_complete=!1,this._debouncedSave())),e.createEl("h2",{text:o("header_title")||"PaperForge"}),e.createEl("p",{text:o("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(o("setup_done")),n.addClass("paperforge-setup-done")):(n.setText(o("setup_pending")),n.addClass("paperforge-setup-pending"));let a=this.app.vault.adapter.basePath,s=L(a,this.plugin.settings,void 0,void 0),l=s.path,i=this.plugin.settings._python_path_stale?"stale":s.source,c=new C.Setting(e).setName(o("field_python_interp")).setDesc(this._getPythonDesc(l,i));this._pythonInterpDescEl=c.descEl;let d=new C.Setting(e).setName(o("field_python_custom")).setDesc("");this._customPathDescEl=d.descEl,d.addText(E=>{E.setPlaceholder("e.g. C:\\Python310\\python.exe").setValue(this.plugin.settings.python_path||"").onChange(_=>{if(this.plugin.settings.python_path=_,this.plugin.saveSettings(),_&&_.trim()){let S=N.existsSync(_.trim());this.plugin.settings._python_path_stale=!S}else this.plugin.settings._python_path_stale=!1;let v=L(this.app.vault.adapter.basePath,this.plugin.settings,void 0,void 0),k=this.plugin.settings._python_path_stale?"stale":v.source;this._pythonInterpDescEl&&(this._pythonInterpDescEl.textContent=this._getPythonDesc(v.path,k))})}),d.addButton(E=>{E.setButtonText(o("btn_validate")).onClick(()=>this._validatePythonOverride())}),e.createEl("h3",{text:o("runtime_health")}),e.createEl("p",{text:o("runtime_health_desc"),cls:"paperforge-settings-desc"});let g=new C.Setting(e).setName("PaperForge").setDesc(o("runtime_health_checking")),p=g.descEl.createEl("span",{cls:"paperforge-runtime-badge"}),f=null;g.addButton(E=>{f=E,E.setButtonText(o("runtime_health_sync")).setDisabled(!0).onClick(()=>this._syncRuntime(E))});{let E=this.app.vault.adapter.basePath,{path:_,extraArgs:v=[]}=L(E,this.plugin.settings,void 0,void 0),k=this.plugin.manifest.version||"?";(0,j.execFile)(_,[...v,"-c","import paperforge; print(paperforge.__version__)"],{cwd:E,timeout:1e4},(S,P)=>{let A=this.plugin.settings.setup_complete,T=!S&&P?P.trim():null,I=T?`${o("runtime_health_plugin_ver").replace("{0}",k)} \u2192 ${o("runtime_health_package_ver").replace("{0}",T)}`:A?`Plugin v${k} \u2192 Python package not installed. Click "Sync Runtime" to install.`:`Plugin v${k} \u2192 Not configured. Please open the setup wizard first.`;g.setDesc(I),T===k?(p.setText(o("runtime_health_match")),p.className="paperforge-runtime-badge match",f&&f.setDisabled(!0)):T?(p.setText(o("runtime_health_mismatch")),p.className="paperforge-runtime-badge mismatch",f&&f.setDisabled(!1)):(p.setText(A?"Not installed":"Setup needed"),p.className="paperforge-runtime-badge missing",f&&f.setDisabled(!1))})}e.createEl("h3",{text:o("section_prep")}),e.createEl("p",{text:o("section_prep_desc"),cls:"paperforge-settings-desc"});let y=e.createEl("div",{cls:"paperforge-guide"}),b=[["prep_python","prep_python_desc"],["prep_zotero","prep_zotero_desc"],["prep_bbt","prep_bbt_desc"],["prep_key","prep_key_desc"]];for(let[E,_]of b){let v=y.createEl("div",{cls:"paperforge-guide-item"});v.createEl("strong",{text:o(E)}),v.createEl("span",{text:" \u2014 "+o(_)})}this._checkEl=e.createEl("div",{cls:"paperforge-message"});let m=!this.plugin.settings.setup_complete;new C.Setting(e).setName(o(m?"btn_install":"btn_reconfig")).setDesc(o(m?"btn_install_desc":"btn_reconfig_desc")).addButton(E=>{E.setButtonText(o(m?"btn_install":"btn_reconfig")).setCta().onClick(()=>{m?this._preCheck(()=>{new Te(this.app,this.plugin).open()}):new Te(this.app,this.plugin).open()})}),e.createEl("h3",{text:o("section_guide")});let x=e.createEl("div",{cls:"paperforge-guide"}),w=[["guide_open","guide_open_desc"],["guide_sync","guide_sync_desc"],["guide_ocr","guide_ocr_desc"]];for(let[E,_]of w){let v=x.createEl("div",{cls:"paperforge-guide-item"});v.createEl("strong",{text:o(E)}),v.createEl("span",{text:" \u2014 "+o(_)})}if(this.plugin.settings.setup_complete){e.createEl("h3",{text:o("section_config")});let E=e.createEl("div",{cls:"paperforge-summary"}),_=this.plugin.settings,v=this._pfConfig,k=[{label:o("dir_vault"),val:t},{label:o("dir_resources"),val:`${t}/${v==null?void 0:v.resources_dir}`},{label:" "+o("dir_notes"),val:`${t}/${v==null?void 0:v.resources_dir}/${v==null?void 0:v.literature_dir}`},{label:o("dir_base"),val:`${t}/${v==null?void 0:v.base_dir}`},{label:o("dir_system"),val:`${t}/${v==null?void 0:v.system_dir}`},{label:"API Key",val:_.paddleocr_api_key?o("api_key_set"):o("api_key_missing")},{label:o("field_zotero_data"),val:_.zotero_data_dir||o("not_set")}];for(let S of k){let P=E.createEl("div",{cls:"paperforge-summary-row"});P.createEl("span",{cls:"paperforge-summary-label",text:S.label}),P.createEl("span",{cls:"paperforge-summary-value",text:S.val})}}}_execMemoryStatus(e,t,r){(0,j.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,i=l.fresh?"fresh":"stale";r(`Papers: ${l.paper_count_db} | ${i}${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,j.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=ce(r,this.plugin.settings),a=[...n.extraArgs,"-m","paperforge","--vault",r,...e];if(t&&t.stream){let s=(0,j.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,j.execFile)(n.path,a,{cwd:r,timeout:t&&t.timeout||6e4},(s,l,i)=>{t&&t.onClose&&t.onClose(s?1:0,l,i)}),null}_renderMemoryStatusText(e,t,r){e.innerHTML="",e.createEl("span",{text:t,cls:"paperforge-memory-text"}),r==="syncing"?e.createEl("span",{text:"Syncing...",cls:"paperforge-sync-status"}):r&&e.createEl("span",{text:r,cls:"paperforge-sync-status"});let n=e.createEl("button",{cls:"paperforge-rebuild-btn",text:o("feat_memory_rebuild_btn")});n.title="Rebuild memory database",n.onclick=()=>{let s=this.app.vault.adapter.basePath,l=ce(s,this.plugin.settings);if(!l.path){new C.Notice(o("feat_no_python"));return}console.log("[PaperForge] Rebuilding memory:",l.path),n.setText(o("feat_memory_rebuilding")),n.setAttr("disabled",""),this._callPython(["memory","build"],{timeout:6e4,onClose:(i,c,d)=>{console.log("[PaperForge] memory build exit:",i?"FAIL:"+i:"OK",(c||"").slice(0,200),(d||"").slice(0,200)),n.setText(o("feat_memory_rebuild_btn")),n.removeAttribute("disabled"),i===0?new C.Notice(o("feat_memory_rebuild_done")):new C.Notice(o("feat_memory_rebuild_failed")+(d?" "+d.slice(0,80):"")),this._memoryStatusText=Ie(s),this._refreshSnapshots(s)}})};let a=e.createEl("button",{cls:"paperforge-refresh-btn",text:"\u21BB"});a.title="Sync now",a.onclick=()=>{this._memoryStatusText=null,this._runManualSync()}}_getBuildCommand(e){let t=this.app.vault.adapter.basePath,r=L(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(!ce(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),Ne(this.app,this.plugin,e)}})}_refreshSnapshots(e){let t=ce(e,this.plugin.settings),r=[...t.extraArgs,"-m","paperforge","--vault",e,"runtime-health","--json"];this._refreshPending=!0,(0,j.execFile)(t.path,r,{cwd:e,timeout:3e4,windowsHide:!0},(n,a,s)=>{this._refreshPending=!1,this._memoryStatusText=Ie(e),this._embedStatusText=be(e),this.display()})}_renderFeaturesTab(e){e.createEl("h3",{text:"Skills"});let t=e.createEl("div",{cls:"paperforge-desc-box"});t.setText(o("feat_skills_desc")),t.createEl("br"),t.createEl("span",{text:o("feat_skills_system")});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 C.Setting(e).setName(o("feat_agent_platform")).setDesc(o("feat_agent_platform_desc")).addDropdown(_=>{Object.entries(r).forEach(([v,k])=>_.addOption(v,k)),_.setValue(s).onChange(v=>{this.plugin.settings.selected_skill_platform=v,this.plugin.saveSettings(),this.display()})}).addExtraButton(_=>{_.setIcon("folder").setTooltip("Open skills folder").onClick(()=>{let v=n[s]||".opencode/skills",k=Z.join(a,v);N.existsSync(k)?(0,j.exec)(`start "" "${k}"`):new C.Notice(`Skills folder not found: ${v}`)})});let l=Z.join(a,n[s]),i=[],c=[];N.existsSync(l)&&N.readdirSync(l,{withFileTypes:!0}).forEach(_=>{if(!_.isDirectory())return;let v=Z.join(l,_.name,"SKILL.md");if(!N.existsSync(v))return;let k=N.readFileSync(v,"utf-8"),S=k.match(/^name:\s*(.+)$/m),P=k.split(`
|
|
`),A=P.findIndex(q=>/^description:/.test(q)),T="";if(A>=0){let q=P[A].match(/^description:\s*(.+)$/);if(q&&q[1]&&q[1]!==">"&&q[1]!=="|-"&&q[1]!=="|")T=q[1].trim();else{for(let F=A+1;F<P.length&&(/^\s{2,}/.test(P[F])||P[F].trim()==="");F++)T+=P[F].trim()+" ";T=T.trim()}}let I=k.match(/^source:\s*(.+)$/m),z=k.match(/^disable-model-invocation:\s*(.+)$/m),O=k.match(/^version:\s*(.+)$/m),U={name:S?S[1].trim():_.name,desc:T,source:I?I[1].trim():"user",disabled:z&&z[1].trim()==="true",version:O?O[1].trim():"",path:v,content:k,dirName:_.name};U.source==="paperforge"?i.push(U):c.push(U)});let d=e.createEl("div",{cls:"paperforge-skills-box"}),g=(_,v,k)=>{if(v.length===0)return;let S=d.createEl("div",{cls:"paperforge-skills-group"}),P=S.createEl("div",{cls:"paperforge-skills-collapse-header"}),A=S.createEl("div",{cls:"paperforge-skills-collapse-content"}),T=P.createEl("span",{text:"\u25BC",cls:"paperforge-skills-arrow"});P.createEl("h4",{text:`${_} (${v.length})`,cls:"paperforge-skills-subheader"}),v.forEach(O=>{let U=O.name+(O.version?" v"+O.version:""),q=k?" [system]":" [user]",F=O.desc||"",D=new C.Setting(A).setName(U+q).setDesc(F);D.settingEl.style.opacity=O.disabled?"0.4":"1",D.addToggle(X=>{X.setValue(!O.disabled).onChange(ee=>{let oe=!ee,de=O.content.match(/^disable-model-invocation:\s*(.+)$/m)?O.content.replace(/^disable-model-invocation:\s*.+$/m,`disable-model-invocation: ${oe}`):O.content.replace(/^(---\r?\n)/,`$1disable-model-invocation: ${oe}
|
|
`);N.writeFileSync(O.path,de,"utf-8"),O.disabled=oe,O.content=de,D.settingEl.style.opacity=O.disabled?"0.4":"1"})})});let I=k?"system":"user";(this._skillsCollapsed[I]||!1)&&(A.style.display="none",T.style.transform="rotate(-90deg)"),P.addEventListener("click",()=>{A.style.display!=="none"?(A.style.display="none",T.style.transform="rotate(-90deg)"):(A.style.display="",T.style.transform="rotate(0deg)"),this._skillsCollapsed[I]=A.style.display==="none"})};g("System Skills",i,!0),g("User Skills",c,!1),i.length===0&&c.length===0&&d.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 p=e.createEl("div",{cls:"paperforge-collapsible-header"}),f=p.createEl("span",{text:"\u25B6",cls:"paperforge-collapsible-arrow"});f.style.transform=this._advCollapsed?"rotate(0deg)":"rotate(90deg)";let y=p.createEl("span",{cls:"paperforge-collapsible-title",text:"Advanced"}),b=p.createEl("span",{cls:"paperforge-collapsible-sub",text:"Memory + Vector DB + Embedding"}),m=e.createEl("div",{cls:"paperforge-collapsible-content"});m.style.display=this._advCollapsed?"none":"",p.addEventListener("click",()=>{this._advCollapsed=!this._advCollapsed,m.style.display=this._advCollapsed?"none":"",f.style.transform=this._advCollapsed?"rotate(0deg)":"rotate(90deg)"}),m.createEl("h4",{text:"Memory Layer"}),m.createEl("div",{cls:"paperforge-desc-box"}).setText(o("feat_memory_desc"));let w=m.createEl("div",{cls:"paperforge-memory-status"}),E=this.app.vault.adapter.basePath;this.plugin._lastSyncTime&&!this._lastSyncTime&&(this._lastSyncTime=this.plugin._lastSyncTime),this._memoryStatusText===null&&(this._memoryStatusText=Ie(E)),this._renderMemoryStatusText(w,this._memoryStatusText,this._lastSyncTime),this._renderVectorSection(m)}_renderVectorSection(e){var i;if(e.createEl("h4",{text:"Vector Database"}),this.plugin.settings.features||(this.plugin.settings.features={memory_layer:!0,vector_db:!1}),e.createEl("div",{cls:"paperforge-desc-box"}).setText(o("feat_vector_desc")),new C.Setting(e).setName(o("feat_vector_enable")).setDesc(o("feat_vector_enable_desc")).addToggle(c=>{c.setValue(!!this.plugin.settings.features.vector_db).onChange(d=>{this.plugin.settings.features.vector_db=d,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-vec-header"}),a=n.createEl("span",{text:"\u25BC",cls:"paperforge-skills-arrow"});n.createEl("span",{cls:"paperforge-vec-header-label",text:o("feat_vector_config_label")});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(Qe(this._featurePanelsCollapsed,"vectorConfig",!1)),n.addEventListener("click",()=>{let c=ft(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=Re(r);this._vectorDepsOk=c&&(i=c.deps_installed)!=null?i:!1,this._vectorDepsOk&&(this._embedStatusText=be(r)),this.display()}}_renderApiConfig(e){new C.Setting(e).setName(o("feat_openai_key")).setDesc(o("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 C.Setting(e).setName(o("feat_api_base_url")).setDesc(o("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 C.Setting(e).setName(o("feat_api_model")).setDesc(o("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){e.createEl("div",{cls:"paperforge-desc-box"}).setText(o("feat_deps_missing")),new C.Setting(e).setName(o("feat_install_deps")).setDesc(o("feat_install_deps_desc")).addButton(r=>{r.setButtonText(o("feat_install_btn")).setCta().onClick(async()=>{let n=this.app.vault.adapter.basePath,a=ce(n,this.plugin.settings);if(!a.path){new C.Notice(o("feat_no_python"));return}r.setButtonText(o("feat_installing")),r.setDisabled(!0);let s="chromadb openai",l=new C.Notice(o("feat_installing_pkgs").replace("{pkgs}",s),0);try{let i=Object.assign({},process.env,{PYTHONIOENCODING:"utf-8",PYTHONUTF8:"1"}),c=s.split(" ");await new Promise((d,g)=>{(0,j.execFile)(a.path,[...a.extraArgs,"-m","pip","install",...c],{cwd:n,timeout:3e5,env:i,windowsHide:!0},p=>{p?g(p):d()})}),l.hide(),new C.Notice(o("feat_install_done")),this._vectorDepsOk=!0,this._embedStatusText=be(n),this.display()}catch(i){l.hide(),new C.Notice(o("feat_install_failed")+(i.stderr||i.message||i)),r.setButtonText(o("feat_retry_btn")),r.setDisabled(!1)}})})}_renderVectorReady(e,t){e.createEl("div",{cls:"paperforge-desc-box"}).setText(be(t)),this._renderApiConfig(e);let n=e.createEl("div",{cls:"paperforge-embed-section"});n.createEl("div",{cls:"paperforge-embed-header"}).createEl("span",{text:o("feat_rebuild_vectors"),cls:"setting-item-name"});let s=n.createEl("div",{cls:"paperforge-embed-controls"}),l=n.createEl("div",{cls:"paperforge-embed-status-text"});(()=>{var y,b,m;s.empty(),l.empty();let c=(Re(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:d,total:g,key:p}=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 w=g>0?(d/g*100).toFixed(1):"0",E=x.createEl("div",{cls:"paperforge-progress-seg done"});if(E.style.cssText=`width:${w}%; min-width:${d>0?"2px":"0"};`,d<g){let v=x.createEl("div",{cls:"paperforge-progress-seg pending"});v.style.cssText=`width:${(100-parseFloat(w)).toFixed(1)}%;`}l.createEl("span",{cls:"paperforge-embed-progress-text",text:`${d}/${g} papers`}),p&&l.createEl("span",{cls:"paperforge-embed-progress-key",text:` (${p})`});let _=s.createEl("button");_.setText("Stop"),_.className="mod-warning",_.addEventListener("click",()=>{this._callPython(["embed","stop","--json"],{timeout:8e3}),this.plugin._embedProcess&&(this.plugin._embedProcess.kill(),this.plugin._embedProcess=null),this.display()})}else{let x=Re(t),w=((y=x==null?void 0:x.chunk_count)!=null?y:0)+((b=x==null?void 0:x.body_chunk_count)!=null?b:0)+((m=x==null?void 0:x.object_chunk_count)!=null?m:0),E=w>0,_=x?!!x.corrupted:!1,v=S=>{if(!ce(t,this.plugin.settings).path){new C.Notice(o("feat_no_python"));return}let A=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",S],{stream:!0,env:A,onData:T=>{let I=T.toString("utf-8").split(`
|
|
`);for(let z of I)if(z.startsWith("EMBED_START:"))this.plugin._embedProgress.total=parseInt(z.split(":")[1])||0;else if(z.startsWith("EMBED_PROGRESS:")){let O=z.split(":");this.plugin._embedProgress.current=parseInt(O[1])||0,this.plugin._embedProgress.key=O[3]||""}else z.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 C.Notice(o("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=be(t),new C.Notice(o("feat_build_complete"));else{this._embedStatusText=null;let I=(this.plugin._embedStderr||"").slice(0,200);new C.Notice(o("feat_build_failed")+(I?": "+I:""),8e3)}this.plugin._embedStderr="",this.display(),this._refreshSnapshots(t)}}),this.display()};if(_){let S=n.createEl("div");S.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;",S.createEl("span",{text:o("feat_vector_corrupted")});let P=S.createEl("button",{text:o("feat_vector_rebuild_force_btn")});P.className="mod-cta",P.addEventListener("click",()=>v("--force"))}E&&!_&&s.createEl("span",{text:w+" chunks embedded",cls:"setting-item-description"});let k=s.createEl("button");if(k.setText(E?o("feat_rebuild_btn"):o("feat_build_btn")),k.addClass("mod-cta"),k.addEventListener("click",()=>v("--resume")),!_&&E){let S=s.createEl("button");S.setText(o("feat_vector_rebuild_force_btn")),S.style.marginLeft="6px",S.addEventListener("click",()=>v("--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=`<span style="color:var(--text-error)">\u2717 ${r}</span>`),new C.Notice(r);return}if(!N.existsSync(e)){let r="\u8DEF\u5F84\u4E0D\u5B58\u5728 / Path does not exist";t&&(t.innerHTML=`<span style="color:var(--text-error)">\u2717 ${r}</span>`),new C.Notice(r,4e3);return}try{N.accessSync(e,N.constants.X_OK)}catch(r){let n="\u4E0D\u53EF\u6267\u884C / Not executable";t&&(t.innerHTML=`<span style="color:var(--text-error)">\u2717 ${n}</span>`),new C.Notice(n,4e3);return}(0,j.execFile)(e,["--version"],{timeout:8e3},(r,n)=>{if(r||!n){let i="\u65E0\u6CD5\u8FD0\u884C / Cannot run";t&&(t.innerHTML=`<span style="color:var(--text-error)">\u2717 ${i}</span>`),new C.Notice(i,4e3);return}let a=n.match(/Python (\d+)\.(\d+)/);if(!a){let i="\u65E0\u6CD5\u89E3\u6790\u7248\u672C / Cannot parse version";t&&(t.innerHTML=`<span style="color:var(--text-error)">\u2717 ${i}</span>`),new C.Notice(i,4e3);return}let s=parseInt(a[1],10),l=parseInt(a[2],10);if(s<3||s===3&&l<10){let i="Python \u7248\u672C\u8FC7\u4F4E\uFF0C\u9700\u8981 3.10+ / Python version too low, need 3.10+";t&&(t.innerHTML=`<span style="color:var(--text-error)">\u2717 ${i}</span>`),new C.Notice(i,4e3);return}(0,j.execFile)(e,["-m","pip","--version"],{timeout:8e3},i=>{if(i){let c=`\u2713 Python ${s}.${l} \u6709\u6548\uFF0C\u4F46\u672A\u68C0\u6D4B\u5230 pip / Valid, but pip not found`;t&&(t.innerHTML=`<span style="color:var(--text-warning)">\u26A0 ${c}</span>`),new C.Notice(c,4e3)}else{let c=`\u2713 Python ${s}.${l} \u6709\u6548 / Valid`;t&&(t.innerHTML=`<span style="color:var(--text-accent)">${c}</span>`),new C.Notice(c,4e3)}})})}_syncRuntime(e){let t=this.app.vault.adapter.basePath,{path:r,extraArgs:n=[]}=L(t,this.plugin.settings,void 0,void 0),a=this.plugin.manifest.version,s=ct(r,a,n);e.setDisabled(!0),e.setButtonText(o("runtime_health_syncing"));let l=(c,d)=>(console.log(`[PaperForge] Sync Runtime: trying ${d}`),pt(s.cmd,c,t,s.timeout,void 0,me())),i=()=>{let c="opencode";try{let f=N.readFileSync(Z.join(t,"paperforge.json"),"utf-8"),y=JSON.parse(f);y.agent_key&&(c=y.agent_key)}catch(f){}let d=[...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)'],g=(0,j.spawn)(r,d,{cwd:t,timeout:3e4,windowsHide:!0}),p="";g.stdout.on("data",f=>{p+=f.toString("utf-8")}),g.on("close",f=>{console.log(`[PaperForge] Skill deploy: ${p.trim()} (exit ${f})`)})};l(s.pypiArgs,"PyPI").then(c=>{if(c.exitCode===0){console.log("[PaperForge] Sync Runtime: installed via PyPI"),i(),new C.Notice(o("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(d=>{d.exitCode===0?(console.log("[PaperForge] Sync Runtime: installed via git"),i(),new C.Notice(o("runtime_health_sync_done").replace("{0}",a),5e3),this.display()):(e.setDisabled(!1),e.setButtonText(o("runtime_health_sync")),console.error("[PaperForge] git fallback stderr:",d.stderr),new C.Notice(o("runtime_health_sync_fail").replace("{0}","pip exit code "+d.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=[]}=L(t,(a=this.plugin)==null?void 0:a.settings,void 0,void 0);(0,j.execFile)(r,[...n,"--version"],{timeout:8e3},(s,l)=>{let i=[];i.push({label:"Python",ok:!s,detail:s?o("check_python_fail"):l.trim()});let c=!1,d=process.env.HOME||process.env.USERPROFILE||kt.homedir()||"";if(process.platform==="darwin")c=["/Applications/Zotero.app",Z.join(d,"Applications","Zotero.app")].some(x=>{try{return N.existsSync(x)}catch(w){return!1}});else if(process.platform==="win32"){let m=process.env.ProgramFiles||"",x=process.env.LOCALAPPDATA||"";c=[Z.join(m,"Zotero"),Z.join(m,"(x86)","Zotero"),Z.join(x,"Programs","Zotero"),Z.join(x,"Zotero"),Z.join(d,"AppData","Local","Programs","Zotero")].filter(Boolean).some(E=>{try{return N.existsSync(E)}catch(_){return!1}})}else c=[Z.join(d,".local","share","zotero","zotero"),"/usr/bin/zotero","/usr/local/bin/zotero"].some(x=>{try{return N.existsSync(x)}catch(w){return!1}});let g=this.plugin.settings.zotero_data_dir;if(!c&&g)try{c=N.existsSync(g)}catch(m){}i.push({label:"Zotero",ok:c,detail:c?o("check_zotero_ok"):o("check_zotero_fail")});let p=!1,f=process.env.APPDATA||"";process.platform==="win32"&&f&&(p=Me(Z.join(f,"Zotero","Zotero","Profiles"))),!p&&process.platform==="darwin"&&d&&(p=Me(Z.join(d,"Library","Application Support","Zotero","Profiles"))),!p&&process.platform!=="win32"&&process.platform!=="darwin"&&d&&(p=Me(Z.join(d,".zotero","zotero","Profiles"))),!p&&g&&String(g).trim()&&(p=Ge(g.trim())),!p&&d&&(p=Ge(Z.join(d,"Zotero"))),i.push({label:"Better BibTeX",ok:p,detail:p?o("check_bbt_ok"):o("check_bbt_fail")});let y={true:"\u2713",false:"\u2717"};if(this._checkEl){this._checkEl.setText(i.map(x=>`${y[String(x.ok)]} ${x.label}: ${x.detail}`).join(`
|
|
`));let m=i.some(x=>!x.ok);this._checkEl.className=`paperforge-message msg-${m?"error":"ok"}`}let b=i.filter(m=>!m.ok);b.length>0&&new C.Notice(`[!!] \u672A\u901A\u8FC7: ${b.map(m=>m.label).join(", ")}`,6e3),e()})}_renderMaintenanceTab(e){e.createEl("h2",{text:o("tab_maintenance")||"\u7EF4\u62A4"});let t=this.app.vault.adapter.basePath,r=e.createEl("div"),n=(g,p)=>p==="retry_ocr"||p==="upgrade_legacy"?{cmd:["-m","paperforge","ocr","redo",...g],timeout:3e5}:p==="rebuild_result"?{cmd:["-m","paperforge","ocr","rebuild",...g],timeout:12e4}:null,a=null;try{a=xt(t)}catch(g){}let s=L(t,this.plugin.settings,N,j.execFileSync);if(!s.path){r.createEl("p",{text:"\u26A0 Python \u672A\u914D\u7F6E\uFF0C\u8BF7\u5148\u5728\u300C\u5B89\u88C5\u300D\u6807\u7B7E\u9875\u914D\u7F6E\u3002",cls:"setting-item-description"});return}let l=g=>{r.empty();let p=g.filter(m=>m.visible_in_maintenance);if(p.length===0){r.createEl("p",{text:o("maintenance_all_good")||"\u2705 \u5168\u90E8\u6B63\u5E38"});return}let f=s.path,y=s.extraArgs||[],b=[{key:"retry",title:o("maintenance_group_retry")||"\u9700\u8981\u91CD\u8BD5",items:[]},{key:"rebuild",title:o("maintenance_group_rebuild")||"\u53EF\u91CD\u5EFA\u7ED3\u679C",items:[]},{key:"legacy_optional",title:o("maintenance_group_legacy")||"\u53EF\u5347\u7EA7\u65E7\u7ED3\u679C\uFF08\u53EF\u9009\uFF09",items:[]}];for(let m of p){let x=b.find(w=>w.key===m.display_group);x&&x.items.push(m)}for(let m of b){if(m.items.length===0)continue;let x=m.key==="legacy_optional",w=x?r.createEl("details"):r.createEl("div");x?w.createEl("summary").createEl("strong",{text:m.title+" ("+m.items.length+")"}):w.createEl("h3",{text:m.title+" ("+m.items.length+")"});let E=new Map;for(let F of m.items)E.set(F.key,!1);let _=w.createEl("div",{cls:"pf-maint-toolbar"}),v=_.createEl("button",{text:"\u5168\u9009"}),k=_.createEl("button",{text:"\u53D6\u6D88\u5168\u9009"}),S=_.createEl("button",{text:"\u25B6 \u6267\u884C\u5DF2\u9009",cls:"mod-cta"}),P=_.createEl("span",{cls:"pf-maint-exec-label"}),A=()=>{let F=m.items.filter(D=>E.get(D.key)).length;P.setText("\u5DF2\u9009 "+F+" \u7BC7")};A(),v.addEventListener("click",()=>{for(let D of m.items)E.set(D.key,!0);A(),w.querySelectorAll("input[type=checkbox].pf-maint-sel").forEach(D=>{D.checked=!0})}),k.addEventListener("click",()=>{for(let D of m.items)E.set(D.key,!1);A(),w.querySelectorAll("input[type=checkbox].pf-maint-sel").forEach(D=>{D.checked=!1})}),S.addEventListener("click",()=>{let F=m.items.filter(D=>E.get(D.key));if(F.length===0){new C.Notice("\u8BF7\u5148\u9009\u62E9\u8981\u5904\u7406\u7684\u8BBA\u6587\u3002");return}for(let D of F){let X=n([D.key],D.display_action);X&&(0,j.execFile)(f,[...y,...X.cmd],{cwd:t,timeout:X.timeout,windowsHide:!0},()=>{new C.Notice(D.display_label+" \u2014 "+D.key)})}});let I=w.createEl("div",{cls:"pf-maint-table-wrap"}).createEl("table",{cls:"pf-maint-table"}),z=I.createEl("thead"),O=I.createEl("tbody"),U=z.insertRow();["","Key","Title","\u5EFA\u8BAE\u64CD\u4F5C","\u539F\u56E0","\u64CD\u4F5C"].forEach(F=>{let D=document.createElement("th");D.textContent=F,U.appendChild(D)});let q=F=>F==="retry_ocr"?o("maintenance_btn_retry")||"\u91CD\u8BD5":F==="rebuild_result"?o("maintenance_btn_rebuild")||"\u91CD\u5EFA":F==="upgrade_legacy"?o("maintenance_btn_upgrade")||"\u5347\u7EA7":"";for(let F of m.items){let D=O.insertRow(),X=D.insertCell();X.style.cssText="padding:3px 4px;text-align:center;";let ee=document.createElement("input");ee.type="checkbox",ee.className="pf-maint-sel",ee.checked=E.get(F.key)||!1,ee.addEventListener("change",()=>{E.set(F.key,ee.checked),A()}),X.appendChild(ee);let oe=D.insertCell();oe.style.cssText="padding:3px 4px;white-space:nowrap;font-size:11px;max-width:90px;overflow:hidden;text-overflow:ellipsis;",oe.textContent=F.key;let ve=D.insertCell();ve.style.cssText="padding:3px 4px;white-space:nowrap;max-width:220px;overflow:hidden;text-overflow:ellipsis;",ve.textContent=F.title||F.key;let de=D.insertCell();de.style.cssText="padding:3px 4px;white-space:nowrap;",de.textContent=F.display_label;let we=D.insertCell();we.style.cssText="padding:3px 4px;white-space:nowrap;max-width:160px;overflow:hidden;text-overflow:ellipsis;font-size:11px;color:var(--text-muted);",we.textContent=F.display_reason||"";let Se=D.insertCell();Se.style.cssText="padding:3px 4px;text-align:center;white-space:nowrap;";let ge=document.createElement("button");ge.textContent=q(F.display_action),ge.textContent&&(ge.addEventListener("click",()=>{let R=n([F.key],F.display_action);R&&(0,j.execFile)(f,[...y,...R.cmd],{cwd:t,timeout:R.timeout,windowsHide:!0},()=>{new C.Notice(F.display_label+" \u2014 "+F.key)})}),Se.appendChild(ge))}}};if(a){let g=Object.values(a.papers);l(g)}else r.createEl("p",{text:"\u6B63\u5728\u52A0\u8F7D OCR \u7EF4\u62A4\u6570\u636E\u2026"});Et(t,s.path,s.extraArgs||[],a||null).then(g=>{g.changed?(l(g.data),$e(t,{manifest:{},papers:Object.fromEntries(g.data.map(p=>[p.key,p])),cached_at:new Date().toISOString()})):a||(l(g.data),$e(t,{manifest:{},papers:Object.fromEntries(g.data.map(p=>[p.key,p])),cached_at:new Date().toISOString()}))}).catch(()=>{a||(r.empty(),r.createEl("p",{text:"\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"}))}),e.createEl("hr"),e.createEl("h3",{text:"\u5168\u5C40\u64CD\u4F5C"});let i=e.createEl("div",{cls:"pf-maint-global"});i.createEl("button",{text:"\u91CD\u5EFA\u641C\u7D22\u7D22\u5F15"}).addEventListener("click",()=>{new C.Notice("\u6B63\u5728\u91CD\u5EFA\u641C\u7D22\u7D22\u5F15\u2026"),(0,j.execFile)(s.path,[...s.extraArgs||[],"-m","paperforge","embed","build","--force"],{cwd:t,timeout:3e5,windowsHide:!0},()=>{new C.Notice("\u641C\u7D22\u7D22\u5F15\u91CD\u5EFA\u5B8C\u6210\u3002")})}),i.createEl("button",{text:"\u91CD\u5EFA\u8BB0\u5FC6\u5E93"}).addEventListener("click",()=>{new C.Notice("\u6B63\u5728\u91CD\u5EFA\u8BB0\u5FC6\u5E93\u2026"),(0,j.execFile)(s.path,[...s.extraArgs||[],"-m","paperforge","repair","--fix"],{cwd:t,timeout:12e4,windowsHide:!0},()=>{new C.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=wt.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 i=s.createEl("div",{cls:"paperforge-release-section"});i.createEl("div",{cls:"paperforge-release-label",text:"\u884C\u4E3A\u53D8\u66F4 / \u8FC1\u79FB\u6CE8\u610F"});for(let c of a.breaking_or_migration)i.createEl("div",{cls:"paperforge-release-item",text:`\u2022 ${c}`})}if(a.new_features&&a.new_features.length>0){let i=s.createEl("div",{cls:"paperforge-release-section"});i.createEl("div",{cls:"paperforge-release-label",text:"\u65B0\u529F\u80FD"});for(let c of a.new_features)i.createEl("div",{cls:"paperforge-release-item",text:`\u2022 ${c}`})}if(a.fixes&&a.fixes.length>0){let i=s.createEl("div",{cls:"paperforge-release-section"});i.createEl("div",{cls:"paperforge-release-label",text:"\u4FEE\u590D"});for(let c of a.fixes)i.createEl("div",{cls:"paperforge-release-item",text:`\u2022 ${c}`})}if(a.recommended_actions&&a.recommended_actions.length>0){let i=s.createEl("div",{cls:"paperforge-release-section paperforge-release-recommended"});i.createEl("div",{cls:"paperforge-release-label",text:"\u5EFA\u8BAE\u64CD\u4F5C"});for(let c of a.recommended_actions)i.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 B=require("obsidian"),pe=$(require("fs")),Oe=$(require("path")),fe=require("child_process");var Be=$(require("path"));function St(h){if(!h)return null;let u=Be.dirname(h);for(;;){let e=Be.basename(u);if(!e||e===".")break;let t=e.match(/^([A-Z0-9]{8})(?:\s*-\s*.*)?$/i);if(t)return t[1];let r=Be.dirname(u);if(r===u)break;u=r}return null}var V=$(require("fs")),he=$(require("path"));function Ae(h){return Q(h).ocrDir}function jt(h,u){let e=he.join(Ae(h),u,"versions","manifest.json");try{if(!V.existsSync(e))return null;let t=V.readFileSync(e,"utf-8"),r=JSON.parse(t);if(r&&typeof r=="object"&&"versions"in r&&"current"in r){let n=r,a=n.versions,s=n.current;if(Array.isArray(a)&&s&&typeof s=="object"&&"label"in s)return r}return null}catch(t){return null}}function Ht(h){let u=Ae(h);try{return V.existsSync(u)?V.readdirSync(u,{withFileTypes:!0}).filter(e=>e.isDirectory()).map(e=>e.name):[]}catch(e){return[]}}function tt(h){let u=Ht(h),e=[];for(let t of u){let r=jt(h,t);if(!r)continue;let n=r.versions.map(s=>s.label),a=0;for(let s of n){let l=he.join(Ae(h),t,"versions",s,"fulltext.md");try{V.existsSync(l)&&(a+=V.statSync(l).size)}catch(i){}}e.push({key:t,title:t.replace(/_/g," "),versions:r.versions,currentLabel:r.current.label,totalSize:a})}return e.sort((t,r)=>t.title.localeCompare(r.title)),e}function Ct(h,u,e){let t=Ae(h),r=he.join(t,u,"versions",e,"fulltext.md"),n=he.join(t,u,"render"),a=he.join(n,"fulltext.md");try{return V.existsSync(r)?(V.existsSync(n)||V.mkdirSync(n,{recursive:!0}),V.copyFileSync(r,a),!0):!1}catch(s){return!1}}function Ft(h,u,e,t){var p;let r=Ae(h),n=he.join(r,u,"versions",e,"fulltext.md"),a=he.join(r,u,"versions",t,"fulltext.md"),s="",l="";try{V.existsSync(n)&&(s=V.readFileSync(n,"utf-8"))}catch(f){}try{V.existsSync(a)&&(l=V.readFileSync(a,"utf-8"))}catch(f){}let i=Pt(s),c=Pt(l),d=Math.max(i.length,c.length),g=[];for(let f=0;f<d;f++){let y=f<i.length?i[f]:"",b=f<c.length?c[f]:"",m=(p=(y||b).split(`
|
|
`)[0])!=null?p:"",x=m.startsWith("## ")?m.replace(/^##\s+/,""):"",w="unchanged";!y&&b?w="added":y&&!b?w="removed":y!==b&&(w="changed"),w!=="unchanged"&&g.push({paragraphIndex:f,heading:x,type:w,oldText:y||void 0,newText:b||void 0})}return g}function Pt(h){let u=h.split(`
|
|
`),e=[],t=[];for(let r of u)if(r.startsWith("## ")&&t.length>0)e.push(t.join(`
|
|
`).trim()),t=[r];else if(r.trim()===""&&t.length>0){let n=t.join(`
|
|
`).trim();n&&(e.push(n),t=[])}else t.push(r);if(t.length>0){let r=t.join(`
|
|
`).trim();r&&e.push(r)}return e}var Ee=class extends B.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._versionPapers=null;this._versionFilter="";this._searchContainer=null;this._searchInput=null;this._searchResultsEl=null;this._searchTimer=void 0;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 _e}getDisplayText(){return"PaperForge"}getIcon(){return Ce}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=[]}=L(e,(l=t==null?void 0:t.settings)!=null?l:null,void 0,void 0);lt(n,r,e,1e4,void 0).then(i=>{if(i.status==="not-installed")return;let c=i.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(o("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=[]}=L(t,(s=r==null?void 0:r.settings)!=null?s:null,void 0,void 0);(0,fe.execFile)(n,[...a,"-m","paperforge","dashboard","--json"],{cwd:t,timeout:3e4},(l,i)=>{if(!l)try{let c=JSON.parse(i);if(c.ok&&c.data){let d=this._normalizeDashboardData(c.data);this._cachedStats=d,this._metricsEl.empty(),this._renderStats(d),this._renderOcr(d),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,i;let n=((s=r==null?void 0:r.settings)==null?void 0:s.system_dir)||"System",a=Oe.join(t,n,"PaperForge","indexes","formal-library.json");try{let c=pe.readFileSync(a,"utf-8"),d=JSON.parse(c),g=d.items||[],p={},f={pdf_health:{healthy:0,unhealthy:0},ocr_health:{healthy:0,unhealthy:0},note_health:{healthy:0,unhealthy:0},asset_health:{healthy:0,unhealthy:0}},y=0,b=0,m=0,x=0,w=0,E=0;for(let _ of g){_.note_path&&E++;let v=_.lifecycle||"pdf_ready";p[v]=(p[v]||0)+1;let k=_.health||{};for(let P of["pdf_health","ocr_health","note_health","asset_health"])(k[P]||"healthy")==="healthy"?f[P].healthy++:f[P].unhealthy++;let S=_.ocr_status||"";y++,S==="done"?b++:S==="pending"?m++:S==="processing"||S==="queued"||S==="running"?x++:w++}this._cachedStats={version:d.paperforge_version||((l=this._cachedStats)==null?void 0:l.version)||"\u2014",total_papers:g.length,formal_notes:E,exports:0,bases:0,ocr:{total:y,pending:m,processing:x,done:b,failed:w},path_errors:0,lifecycle_level_counts:p,health_aggregate:f},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:d,extraArgs:g=[]}=L(t,(i=r==null?void 0:r.settings)!=null?i:null,void 0,void 0);(0,fe.execFile)(d,[...g,"-m","paperforge","status","--json"],{cwd:t,timeout:3e4},(p,f)=>{if(p){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 y=JSON.parse(f);this._cachedStats=y,this._metricsEl.empty(),this._renderStats(y),this._renderOcr(y)}catch(y){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=Oe.join(e,r,"PaperForge","indexes","formal-library.json");try{let s=pe.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 nt(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]=Ke(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 i=this._metricsEl.createEl("div",{cls:"paperforge-metric-card"});i.style.setProperty("--metric-color",l.color),i.createEl("div",{cls:"paperforge-metric-value",text:((s=l.value)==null?void 0:s.toString())||"\u2014"}),i.createEl("div",{cls:"paperforge-metric-label",text:l.label}),l.barMax>0&&this._buildMetricBar(i,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 i=this._metricsEl.createEl("div",{cls:"paperforge-metric-card"});i.style.setProperty("--metric-color","var(--color-yellow)"),i.createEl("div",{cls:"paperforge-metric-value",text:l.join(", ")}),i.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 i=[{cls:"pending",count:a},{cls:"active",count:s},{cls:"done",count:n},{cls:"failed",count:l}];for(let c of i)if(c.count>0){let d=(c.count/r*100).toFixed(1);this._ocrTrack.createEl("div",{cls:`paperforge-progress-seg ${c.cls}`,attr:{style:`width:${d}%`}})}}if(this._ocrCounts){this._ocrCounts.empty();let i=[{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 i){let d=this._ocrCounts.createEl("div",{cls:"paperforge-ocr-count"});d.createEl("div",{cls:"paperforge-ocr-count-value",text:c.value.toString()}),d.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 i=a.createEl("div",{cls:"step"});i.createEl("div",{cls:"step-indicator"}),i.createEl("div",{cls:"step-label",text:l.label}),l.key===r?(i.addClass("current"),s=!0):s?i.addClass("pending"):i.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"}),i,c,d;s==="healthy"||s==="ok"?(i=a.iconOk,c="ok",d=`${a.label}: OK`):s==="warn"||s==="warning"||s==="degraded"?(i=a.iconWarn,c="warn",d=`${a.label}: Needs Attention`):(i=a.iconFail,c="fail",d=`${a.label}: Failed`),l.addClass(c),l.setAttribute("title",d),l.createEl("div",{cls:"paperforge-health-cell-icon",text:i}),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 i=1;i<=s;i++){let c=a.createEl("div",{cls:"gauge-segment"});i<=l&&(c.addClass("filled"),c.addClass(`level-${i}`))}if(n.createEl("div",{cls:"gauge-level",text:`Level ${l} / ${s}`}),l<s&&r){let i=typeof r=="string"?[r]:r;if(i.length>0){let c=n.createEl("ul",{cls:"gauge-blockers"});for(let d of i)c.createEl("li",{text:d})}}}_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,i=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:${i.toFixed(1)}%`}}),c.createEl("div",{cls:"bar-count",text:l.toString()})}}_invalidateIndex(){this._cachedItems=null}_extractZoteroKeyFromPath(e){return St(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;case"versions":this._renderVersionMode();break}}_renderGlobalMode(){var ee,oe,ve,de,we,Se,ge;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 R of t)R.has_pdf&&n++,R.ocr_status==="done"&&a++,R.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 i=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 R of c){let M=i.createEl("div",{cls:"paperforge-snapshot-pill"});M.createEl("span",{cls:"paperforge-snapshot-value",text:String(R.value)}),M.createEl("span",{cls:"paperforge-snapshot-label",text:" "+R.label})}let d=e.createEl("div",{cls:"paperforge-system-status"});d.createEl("div",{cls:"paperforge-section-label",text:"System Status"});let g=d.createEl("div",{cls:"paperforge-status-grid"}),p=this.app.plugins.plugins.paperforge,f=((ee=p==null?void 0:p.manifest)==null?void 0:ee.version)||"?",y=this._paperforgeVersion;if(!y)try{let R=this.app.vault.adapter.basePath,{path:M,extraArgs:re=[]}=L(R,(oe=p==null?void 0:p.settings)!=null?oe:null,void 0,void 0),J=(0,fe.execFileSync)(M,[...re,"-c","import paperforge; print(paperforge.__version__)"],{cwd:R,timeout:5e3,encoding:"utf-8",windowsHide:!0}).trim();J&&(y=J.startsWith("v")?J:"v"+J,this._paperforgeVersion=y)}catch(R){}y=y||"\u2014";let b=y==="v"+f;this._renderSystemStatusRow(g,"Runtime",b?"healthy":"mismatch",b?"v"+f:"plugin v"+f+" \u2260 CLI "+y);let m=this._loadIndex(),x=m&&m.items&&m.items.length>0;this._renderSystemStatusRow(g,"Index",x?"healthy":"missing",x?m.items.length+" entries":"formal-library.json not found");let w=((ve=p==null?void 0:p.settings)==null?void 0:ve.system_dir)||"System",E=this.app.vault.adapter.basePath,_=!1,v="No exports found";try{let R=Oe.join(E,w,"PaperForge","exports");if(pe.existsSync(R)){let M=pe.readdirSync(R).filter(re=>re.endsWith(".json"));_=M.length>0,v=_?M.length+" export(s)":"No JSON exports"}}catch(R){}this._renderSystemStatusRow(g,"Zotero Export",_?"healthy":"missing",v);let k=!!((de=p==null?void 0:p.settings)!=null&&de.paddleocr_api_key);if(!k)try{let R=((we=p==null?void 0:p.settings)==null?void 0:we.system_dir)||"System",M=Oe.join(E,R,"PaperForge",".env");if(pe.existsSync(M)){let J=pe.readFileSync(M,"utf-8").match(/^PADDLEOCR_API_TOKEN\s*=\s*(.+)$/m);k=!!(J&&J[1]&&J[1].trim())}}catch(R){}k||(k=!!(process.env.PADDLEOCR_API_TOKEN||process.env.PADDLEOCR_API_KEY||process.env.OCR_TOKEN)),this._renderSystemStatusRow(g,"OCR Token",k?"configured":"missing",k?"Configured":"Not set");let S=!1,P="",A=this.app.vault.adapter.basePath,T=Ye(A);S=ht(A),P=T&&((Se=T.summary)==null?void 0:Se.reason)||T&&((ge=T.summary)==null?void 0:ge.status)||"Unknown",this._renderSystemStatusRow(g,"Memory Layer",S?"healthy":"fail",P);let I=!b&&y!=="\u2014";if(I||!x||!_||!k){let R=e.createEl("div",{cls:"paperforge-issue-summary"});R.createEl("div",{cls:"paperforge-section-label",text:"\u9700\u8981\u5904\u7406"});let M=R.createEl("div",{cls:"paperforge-issue-list"});I&&M.createEl("div",{cls:"paperforge-issue-item",text:"Runtime version mismatch"}),x||M.createEl("div",{cls:"paperforge-issue-item",text:"Index missing or corrupted"}),_||M.createEl("div",{cls:"paperforge-issue-item",text:"No Zotero export found"}),k||M.createEl("div",{cls:"paperforge-issue-item",text:"PaddleOCR API key not configured"});let re=R.createEl("div",{cls:"paperforge-issue-actions"}),J=re.createEl("button",{cls:"paperforge-contextual-btn"});J.createEl("span",{text:"Run Doctor"}),J.addEventListener("click",()=>{let Pe=Y.find(Ve=>Ve.id==="paperforge-doctor");Pe&&this._runAction(Pe,J)});let ue=re.createEl("button",{cls:"paperforge-contextual-btn"});ue.createEl("span",{text:"Repair Issues"}),ue.addEventListener("click",()=>{let Pe=Y.find(Ve=>Ve.id==="paperforge-repair");Pe&&this._runAction(Pe,ue)})}let O=e.createEl("div",{cls:"paperforge-global-actions"});O.createEl("div",{cls:"paperforge-section-label",text:"Start Working"});let U=O.createEl("div",{cls:"paperforge-global-actions-row"}),q=U.createEl("button",{cls:"paperforge-contextual-btn primary"});q.createEl("span",{cls:"paperforge-contextual-btn-icon",text:"\u{1F4C1}"}),q.createEl("span",{text:"Open Literature Hub"}),q.addEventListener("click",()=>{var re;let R=((re=p==null?void 0:p.settings)==null?void 0:re.base_dir)||"Bases",M=this.app.vault.getAbstractFileByPath(R);if(M){let J=null;if(M.children&&(J=M.children.find(ue=>ue.extension==="base")),J){let ue=this.app.workspace.getLeaf(!1);ue&&ue.openFile(J)}else new B.Notice("[!!] No .base file found in "+R,6e3)}else new B.Notice("[!!] Base directory not found: "+R,6e3)});let F=U.createEl("button",{cls:"paperforge-contextual-btn"});F.createEl("span",{cls:"paperforge-contextual-btn-icon",text:"\u21BB"}),F.createEl("span",{text:"Sync Library"}),F.addEventListener("click",()=>{let R=Y.find(M=>M.id==="paperforge-sync");R&&this._runAction(R,F)});let D=U.createEl("button",{cls:"paperforge-contextual-btn"});D.createEl("span",{cls:"paperforge-contextual-btn-icon",text:"\u229E"}),D.createEl("span",{text:"Run OCR"}),D.addEventListener("click",()=>{let R=Y.find(M=>M.id==="paperforge-ocr");R&&this._runAction(R,D)});let X=U.createEl("button",{cls:"paperforge-contextual-btn warn"});X.createEl("span",{cls:"paperforge-contextual-btn-icon",text:"\u21BA"}),X.createEl("span",{text:"Redo OCR"}),X.addEventListener("click",()=>{let R=Y.find(M=>M.id==="paperforge-ocr-redo");R&&this._runAction(R,X)})}_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 pf-copy",text:e.title||"Untitled"}).addEventListener("click",()=>{navigator.clipboard.writeText(e.title||""),new B.Notice("Title copied")});let s=n.createEl("div",{cls:"paperforge-paper-meta"});e.authors&&e.authors.length>0&&s.createEl("span",{cls:"paperforge-paper-authors",text:e.authors.join(", ")}),e.year&&s.createEl("span",{cls:"paperforge-paper-year",text:String(e.year)});let l=r.createEl("div",{cls:"paperforge-status-strip"}),i=l.createEl("div",{cls:"paperforge-status-strip-left"}),c=l.createEl("div",{cls:"paperforge-status-strip-right"}),d=[{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 d){let f=i.createEl("span",{cls:"paperforge-status-pill"}),y="pending";p.ok?y="ok":p.fail?y="fail":p.pending&&(y="pending"),f.addClass(y);let b=p.ok?"\u2713":p.fail?"\u2717":"\u25CB";f.createEl("span",{cls:"paperforge-status-pill-icon",text:b}),f.createEl("span",{text:" "+p.label})}if(e.pdf_path){let p=c.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 f=e.pdf_path.match(/\[\[([^\]]+)\]\]/),y=f?f[1]:e.pdf_path;this.app.vault.getAbstractFileByPath(y)?this.app.workspace.openLinkText(y,""):new B.Notice("[!!] PDF not found: "+y,6e3)})}if(e.fulltext_path){let p=c.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))}let g=c.createEl("button",{cls:"paperforge-contextual-btn"});if(g.createEl("span",{text:o("version_panel_title")}),g.addEventListener("click",()=>{this._switchToVersionMode(t)}),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(i=>{let c=this._extractOverviewFromNote(i);if(c){let d=c.length>200?c.slice(0,200)+"...":c;if(s.setText(d),c.length>200){let g=a.createEl("div",{cls:"paperforge-expand-container"}),p=g.createEl("button",{cls:"paperforge-expand-icon",title:"\u5C55\u5F00/\u6536\u8D77"});p.innerHTML='<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="6 9 12 15 18 9"></polyline></svg>';let f=!1;g.addEventListener("click",()=>{s.setText(f?d:c),p.innerHTML=f?'<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="6 9 12 15 18 9"></polyline></svg>':'<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="18 15 12 9 6 15"></polyline></svg>',f=!f})}}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 i=r.indexOf(l);if(i!==-1){let c=r.slice(i+l.length),d=["**5 Cs","**Figure","**\u8BC1\u636E","### Pass 2","## "],g=c.length;for(let y of d){let b=c.indexOf(y);b!==-1&&b<g&&(g=b)}let p=c.indexOf(`
|
|
|
|
`);p!==-1&&p<g&&(g=p);let f=c.slice(0,g).trim();return f.startsWith("**")&&(f=f.slice(2)),f.endsWith("**")&&(f=f.slice(0,-2)),f||null}}let a=r.indexOf(`
|
|
`);if(a===-1)return null;let s=r.slice(a+1).split(`
|
|
|
|
`)[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 i=this._parseDiscussionMD(l);if(!i||i.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 g of i){let p=r.createEl("div",{cls:"paperforge-discussion-item"}),f=p.createEl("div",{cls:"paperforge-discussion-q"});f.createEl("span",{cls:"paperforge-discussion-q-label",text:"\u63D0\u95EE\uFF1A"}),f.createEl("span",{cls:"paperforge-discussion-q-text",text:g.question});let y=p.createEl("div",{cls:"paperforge-discussion-a"}),b=!1;if(g.answer&&g.answer.length>500&&(b=!0,y.classList.add("paperforge-discussion-a-collapsed")),await B.MarkdownRenderer.render(this.app,g.answer||"",y,s,this),b){let m=!1;p.style.cursor="pointer",p.addEventListener("click",()=>{m=!m,y.classList.toggle("paperforge-discussion-a-collapsed",!m),y.classList.toggle("paperforge-discussion-a-expanded",m)})}}r.createEl("a",{cls:"paperforge-discussion-viewall",text:"\u67E5\u770B\u5168\u90E8\u8BA8\u8BBA \u2192"}).addEventListener("click",g=>{g.preventDefault(),this.app.vault.getAbstractFileByPath(s)?this.app.workspace.openLinkText(s,""):new B.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 i=s.substring(0,l.index).trim(),c=s.substring(l.index+3+4).trim();n.push({question:i,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 p=s.style.display!=="none";s.style.display=p?"none":"block",a.setText(p?"\u6280\u672F\u8BE6\u60C5 \u25B8":"\u6280\u672F\u8BE6\u60C5 \u25BE"),this._techDetailsExpanded=!p});let l=s.createEl("div",{cls:"paperforge-workflow-toggles"}),i=[{key:"do_ocr",label:"OCR",hint:"\u52A0\u5165 OCR"},{key:"analyze",label:"\u7CBE\u8BFB",hint:"\u6807\u8BB0\u7CBE\u8BFB"}];for(let p of i){let f=l.createEl("label",{cls:"paperforge-workflow-toggle"}),y=f.createEl("input",{type:"checkbox",cls:"paperforge-workflow-checkbox"});y.checked=t[p.key]===!0,f.createEl("span",{cls:"paperforge-workflow-toggle-label",text:p.label}),f.createEl("span",{cls:"paperforge-workflow-toggle-hint",text:p.hint}),y.addEventListener("change",async()=>{let b=t.note_path?this.app.vault.getAbstractFileByPath(t.note_path):null;if(!b){new B.Notice("[!!] Note file not found",6e3);return}let m=y.checked;await this.app.fileManager.processFrontMatter(b,x=>{x[p.key]=m}),this._patchCachedEntry(r,{[p.key]:m}),this._currentPaperEntry=Ke(this._currentPaperEntry,{[p.key]:m})})}let c=t.health||{},d=[["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"]],g=new Set(["Note Path","Fulltext Path","Key"]);for(let[p,f]of d){let y=s.createEl("div",{cls:"paperforge-technical-row"});y.createEl("span",{cls:"paperforge-technical-label",text:p});let b=y.createEl("span",{cls:"paperforge-technical-value",text:String(f)});g.has(p)&&f&&f!=="\u2014"&&(b.addClass("pf-copy"),b.addEventListener("click",()=>{navigator.clipboard.writeText(f),new B.Notice(p+" copied")}))}}_renderNextStepCard(e,t,r){var i,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 d=l.createEl("button",{cls:"paperforge-next-step-trigger"});d.createEl("span",{text:s.icon+" "+s.label}),d.addEventListener("click",()=>{let g=Y.find(p=>p.cmd===s.cmd);g&&this._runAction(g,d)})}else if(n==="/pf-deep"){let d=l.createEl("button",{cls:"paperforge-next-step-trigger"});d.createEl("span",{text:"\u{1F4CB} "+o("copy_pf_deep_cmd")}),d.addEventListener("click",()=>{let b="/pf-deep "+r;navigator.clipboard.writeText(b).then(()=>{d.setText("\u2713 "+o("copied")),new B.Notice(b+" copied")}).catch(()=>{new B.Notice("[!!] Clipboard write failed",6e3)})});let g=((c=(i=this.app.plugins.plugins.paperforge)==null?void 0:i.settings)==null?void 0:c.agent_platform)||"opencode",f={opencode:"OpenCode",claude:"Claude Code",cursor:"Cursor",github_copilot:"GitHub Copilot",windsurf:"Windsurf",codex:"Codex",gemini:"Gemini CLI",cline:"Cline"}[g]||g;l.createEl("div",{cls:"paperforge-agent-platform-label"}).setText(o("run_in_agent").replace("{0}",f))}else n==="ready"&&l.createEl("button",{cls:"paperforge-next-step-trigger"}).createEl("span",{text:"\u2713 "+s.label})}_openFulltext(e){if(!e){new B.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 B.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,i=0,c=0,d=0,g=0;for(let _ of t){_.has_pdf&&a++,_.ocr_status==="done"&&s++,_.ocr_status==="done"&&_.analyze===!0&&l++,_.deep_reading_status==="done"&&i++;let v=_.ocr_status||"";v==="pending"||v==="queued"?c++:v==="processing"?d++:(v==="failed"||v==="blocked"||v==="done_incomplete"||v==="nopdf")&&g++}r.createEl("div",{cls:"paperforge-collection-header"}).createEl("div",{cls:"paperforge-collection-title",text:e});let f=r.createEl("div",{cls:"paperforge-workflow-overview"});f.createEl("div",{cls:"paperforge-section-label",text:"Workflow Overview"});let y=f.createEl("div",{cls:"paperforge-workflow-funnel"}),b=[{value:n,label:"Total"},{value:a,label:"PDF Ready"},{value:s,label:"OCR Done"},{value:i,label:"Deep Read"}];for(let _=0;_<b.length;_++){let v=y.createEl("div",{cls:"paperforge-workflow-stage"});v.createEl("div",{cls:"paperforge-workflow-stage-value",text:String(b[_].value)}),v.createEl("div",{cls:"paperforge-workflow-stage-label",text:b[_].label}),_<b.length-1&&y.createEl("div",{cls:"paperforge-workflow-arrow",text:"\u2192"})}if(c+d+s+g>0){let _=r.createEl("div",{cls:"paperforge-ocr-section"}),v=_.createEl("div",{cls:"paperforge-collection-ocr-header"});v.createEl("h4",{cls:"paperforge-ocr-title",text:"OCR Pipeline"});let k=v.createEl("span",{cls:"paperforge-ocr-badge idle"});d>0?(k.addClass("active"),k.setText("Processing")):c>0?k.setText("Pending"):(k.addClass("idle"),k.setText("Idle"));let S=_.createEl("div",{cls:"paperforge-progress-track"});d>0&&S.addClass("paperforge-processing");let P=c+d+s+g,A=[{cls:"pending",count:c},{cls:"active",count:d},{cls:"done",count:s},{cls:"failed",count:g}];for(let z of A)if(z.count>0){let O=(z.count/P*100).toFixed(1);S.createEl("div",{cls:`paperforge-progress-seg ${z.cls}`,attr:{style:`width:${O}%`}})}let T=_.createEl("div",{cls:"paperforge-ocr-counts"}),I=[{cls:"pending",value:c,label:"Pending"},{cls:"active",value:d,label:"Processing"},{cls:"done",value:s,label:"Done"},{cls:"failed",value:g,label:"Attention"}];for(let z of I){let O=T.createEl("div",{cls:"paperforge-ocr-count"});O.createEl("div",{cls:"paperforge-ocr-count-value",text:z.value.toString()}),O.createEl("div",{cls:"paperforge-ocr-count-label",text:z.label})}}let m=r.createEl("div",{cls:"paperforge-collection-actions"}),x=m.createEl("button",{cls:"paperforge-contextual-btn primary"});x.createEl("span",{cls:"paperforge-contextual-btn-icon",text:"\u229E"}),x.createEl("span",{text:"Run OCR"}),x.addEventListener("click",()=>{let _=Y.find(v=>v.id==="paperforge-ocr");_&&this._runAction(_,x)});let w=m.createEl("button",{cls:"paperforge-contextual-btn"});w.createEl("span",{cls:"paperforge-contextual-btn-icon",text:"\u21BB"}),w.createEl("span",{text:"Sync Library"}),w.addEventListener("click",()=>{let _=Y.find(v=>v.id==="paperforge-sync");_&&this._runAction(_,w)});let E=m.createEl("button",{cls:"paperforge-contextual-btn warn"});E.createEl("span",{cls:"paperforge-contextual-btn-icon",text:"\u21BA"}),E.createEl("span",{text:"Redo OCR"}),E.addEventListener("click",()=>{let _=Y.find(v=>v.id==="paperforge-ocr-redo");_&&this._runAction(_,E)}),this.renderSearchSection(r)}_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;case"versions":this._renderVersionMode();break}}finally{setTimeout(()=>{this._contentEl&&this._contentEl.removeClass("switching")},50)}}}_switchToVersionMode(e){let r=this.app.vault.adapter.basePath,n=typeof r=="string"?r:"";if(!n){new B.Notice("Cannot determine vault path");return}this._versionPapers=tt(n),this._versionFilter="",this._currentMode="versions",this._currentFilePath=null,this._techDetailsExpanded=!1,this._contentEl&&(this._contentEl.empty(),this._contentEl.removeClass("switching"),this._renderModeHeader("versions"),this._renderVersionMode())}_renderVersionMode(){if(!this._contentEl)return;let e=this._contentEl.createEl("div",{cls:"paperforge-version-panel"}),r=this.app.vault.adapter.basePath,n=typeof r=="string"?r:"";if(!n){e.createEl("div",{cls:"paperforge-status-error",text:"Could not determine vault path"});return}(!this._versionPapers||this._versionPapers.length===0)&&(this._versionPapers=tt(n));let a=e.createEl("div",{cls:"paperforge-version-left"}),s=e.createEl("div",{cls:"paperforge-version-right"}),l=a.createEl("input",{cls:"paperforge-version-filter",attr:{type:"text",placeholder:o("version_filter_placeholder")}});l.value=this._versionFilter;let i=a.createEl("div",{cls:"paperforge-version-paper-list"}),c=()=>{i.empty();let x=this._versionFilter.toLowerCase(),w=this._versionPapers?this._versionPapers.filter(_=>!x||_.key.toLowerCase().includes(x)||_.title.toLowerCase().includes(x)):[];if(w.length===0){i.createEl("div",{cls:"paperforge-meta",text:o("version_no_backups")});return}let E=i.createEl("div",{cls:"paperforge-meta",text:o("version_papers_count").replace("{n}",String(w.length))});for(let _ of w){let v=i.createEl("div",{cls:"paperforge-version-paper-item"}),k=v.createEl("span",{cls:"paperforge-version-paper-title",text:_.title}),S=v.createEl("span",{cls:"paperforge-version-paper-versions",text:_.versions.map(P=>P.label).join(" ")});v.addEventListener("click",()=>{i.querySelectorAll(".paperforge-version-paper-item.selected").forEach(P=>P.removeClass("selected")),v.addClass("selected"),g(_)})}};l.addEventListener("input",()=>{this._versionFilter=l.value,c()});let d=s.createEl("div",{cls:"paperforge-version-timeline-area"}),g=x=>{if(d.empty(),d.createEl("div",{cls:"paperforge-version-timeline-header"}).createEl("span",{cls:"pf-title",text:x.title}),x.versions.length===0){d.createEl("div",{cls:"paperforge-meta",text:o("version_no_backups")});return}let E=d.createEl("div",{cls:"paperforge-version-timeline"});for(let _ of x.versions){let v=_.label===x.currentLabel,k=E.createEl("div",{cls:"paperforge-version-entry"+(v?" paperforge-version-current":"")}),S=k.createEl("div",{cls:"paperforge-version-dot"}),P=k.createEl("div",{cls:"paperforge-version-content"}),A=P.createEl("div",{cls:"paperforge-version-label-row"});A.createEl("span",{cls:"paperforge-version-label",text:_.label}),v&&A.createEl("span",{cls:"paperforge-version-current-tag",text:o("version_current")});let T=_.created_at?_.created_at.slice(0,10):"";P.createEl("div",{cls:"paperforge-meta",text:T+" \u2014 "+_.source});let I=_.fulltext_size?_.fulltext_size>1024?(_.fulltext_size/1024).toFixed(0)+"KB":_.fulltext_size+"B":"";I&&P.createEl("div",{cls:"paperforge-meta",text:I});let z=P.createEl("div",{cls:"paperforge-version-actions"});z.createEl("button",{cls:"pf-btn-primary",text:o("version_restore_btn")}).addEventListener("click",()=>{Ct(n,x.key,_.label)?new B.Notice(o("version_restore_done").replace("{label}",_.label)):new B.Notice("Restore failed",6e3)}),x.versions.length>1&&!v&&z.createEl("button",{cls:"pf-btn-secondary",text:o("version_compare_btn")}).addEventListener("click",()=>{f(x,_.label,x.currentLabel)})}},p=s.createEl("div",{cls:"paperforge-version-compare"});p.style.display="none";let f=(x,w,E)=>{let _=Ft(n,x.key,w,E);p.style.display="block",p.empty();let v=p.createEl("div",{cls:"paperforge-version-compare-header"});if(v.createEl("span",{cls:"pf-title",text:o("version_compare_title").replace("{vA}",w).replace("{vB}",E)}),v.createEl("span",{cls:"paperforge-meta",text:o("version_compare_paragraphs").replace("{n}",String(_.length))}),_.length===0){p.createEl("div",{cls:"paperforge-meta",text:"No changes"});return}let k=p.createEl("div",{cls:"paperforge-version-diff-list"});for(let S of _){let P=k.createEl("div",{cls:"paperforge-version-diff-row"}),A=S.type==="added"?"[+]":S.type==="removed"?"[-]":"[~]",T=S.heading||"paragraph "+(S.paragraphIndex+1);P.createEl("span",{cls:"paperforge-version-diff-label",text:A+" "+T}),S.oldText&&P.createEl("pre",{cls:"paperforge-version-diff-old",text:S.oldText.slice(0,200)}),S.newText&&P.createEl("pre",{cls:"paperforge-version-diff-new",text:S.newText.slice(0,200)})}},y=e.createEl("div",{cls:"paperforge-version-actions-bar"}),b=y.createEl("button",{cls:"pf-btn-primary",text:o("version_restore_selected")}),m=y.createEl("button",{cls:"pf-btn-secondary",text:o("version_clear_old").replace("{size}","")});c()}renderSearchSection(e){this._searchContainer=e.createEl("div",{cls:"paperforge-search-section"}),this._searchContainer.createEl("div",{cls:"paperforge-search-header"}).createEl("span",{cls:"pf-label",text:"Search"});let r=this._searchContainer.createEl("div",{cls:"paperforge-search-input-row"}),n=r.createEl("span",{cls:"paperforge-search-mode",text:"M"});this._searchInput=r.createEl("input",{cls:"paperforge-search-input",attr:{type:"text",placeholder:"Search papers... (@ for deep search)"}}),this._searchResultsEl=this._searchContainer.createEl("div",{cls:"paperforge-search-results"}),this._searchInput.addEventListener("input",()=>{var s;let a=((s=this._searchInput)==null?void 0:s.value)||"";a.startsWith("@")&&!a.startsWith("@ ")?(n.setText("@"),n.addClass("deep")):(n.setText("M"),n.removeClass("deep")),clearTimeout(this._searchTimer),!a.startsWith("@")&&a.trim()&&(this._searchTimer=setTimeout(()=>{this.executeSearch()},200))}),this._searchInput.addEventListener("keydown",a=>{a.key==="Enter"&&(a.preventDefault(),this._searchTimer&&(clearTimeout(this._searchTimer),this._searchTimer=void 0),this.executeSearch())})}async executeSearch(){if(!this._searchInput||!this._searchResultsEl)return;let e=this._searchInput.value.trim();if(!e)return;let t=e.startsWith("@"),r=t?e.slice(1).trim():e;if(!r)return;let n=t?"retrieve":"search",a=this.app.vault.adapter,s="";if(a&&typeof a=="object"&&"basePath"in a){let b=a.basePath;s=typeof b=="string"?b:""}if(this._searchResultsEl.empty(),this._searchResultsEl.createEl("div",{cls:"paperforge-search-loading",text:"Searching..."}),!s){this._renderSearchError("Could not determine vault path");return}let l=null,c=this.app.plugins;if(c&&typeof c=="object"&&"plugins"in c){let b=c.plugins;if(b&&typeof b=="object"&&"paperforge"in b){let m=b.paperforge;m&&typeof m=="object"&&"settings"in m&&(l=m.settings)}}let{path:d,extraArgs:g=[]}=L(s,l,void 0,void 0),p=n==="retrieve"?["--deep"]:[],f=(0,fe.spawn)(d,[...g,"-m","paperforge",n,r,...p,"--json"],{cwd:s,timeout:3e4}),y=[];f.stdout.on("data",b=>{y.push(b.toString("utf-8"))}),f.stderr.on("data",()=>{}),f.on("close",b=>{if(b!==0){this._renderSearchError(`Search failed (exit ${b})`);return}let m=y.join(""),x=m.indexOf("{"),w=m.lastIndexOf("}"),E="";if(x!==-1&&w>x)E=m.slice(x,w+1);else{let _=m.indexOf("["),v=m.lastIndexOf("]");_!==-1&&v>_&&(E=m.slice(_,v+1))}if(!E){this._renderSearchError("No JSON output from CLI");return}try{let _=JSON.parse(E),v=[];if(_&&typeof _=="object"&&"data"in _){let k=_.data;if(k&&typeof k=="object"){let S=k;"matches"in S&&Array.isArray(S.matches)&&(v=S.matches)}}this.renderSearchResults(v,t)}catch(_){let v=_ instanceof Error?_.message:String(_);this._renderSearchError("Failed to parse results: "+v)}}),f.on("error",b=>{this._renderSearchError("Process error: "+b.message)})}renderSearchResults(e,t){if(!this._searchResultsEl)return;if(this._searchResultsEl.empty(),e.length===0){this._searchResultsEl.createEl("div",{cls:"paperforge-search-empty",text:"No results found."});return}let r=this._searchResultsEl.createEl("div",{cls:"paperforge-search-results-header"});r.createEl("span",{text:`${e.length} result${e.length!==1?"s":""}`}),r.createEl("span",{cls:"paperforge-search-mode",text:t?"@":"M"});for(let n of e){if(!n||typeof n!="object")continue;let a=n,s=this._searchResultsEl.createEl("div",{cls:"paperforge-search-result-card",attr:{role:"button"}}),l=typeof a.title=="string"?a.title:typeof a.file_name=="string"?a.file_name:"(untitled)";s.createEl("div",{cls:"paperforge-search-result-title",text:l});let i=typeof a.zotero_key=="string"?a.zotero_key:"",c=typeof a.main_note_path=="string"&&a.main_note_path?a.main_note_path:null,d=typeof a.note_path=="string"&&a.note_path?a.note_path:null,g=c||d;if(!g&&i){let y=this._getCachedIndex().find(b=>b!==null&&typeof b=="object"&&"zotero_key"in b&&b.zotero_key===i);if(y&&typeof y=="object"){let b=y;g=typeof b.main_note_path=="string"&&b.main_note_path?b.main_note_path:typeof b.note_path=="string"&&b.note_path?b.note_path:null}}g?s.addEventListener("click",f=>{let y=f.ctrlKey||f.metaKey;this.app.workspace.openLinkText(g,"",y)}):s.addEventListener("click",()=>{new B.Notice("[!!] Note not found: "+(i||"unknown"),6e3)});let p=s.createEl("div",{cls:"paperforge-search-result-meta"});if(typeof a.first_author=="string"&&a.first_author&&p.createEl("span",{cls:"paperforge-search-result-author",text:a.first_author}),typeof a.journal=="string"&&a.journal&&p.createEl("span",{cls:"paperforge-search-result-journal",text:a.journal}),a.score!==void 0){let f=a.score,y=typeof f=="number"?f.toFixed(3):String(f);p.createEl("span",{cls:"paperforge-search-result-score",text:"Score: "+y})}if(typeof a.domain=="string"&&a.domain&&s.createEl("span",{cls:"paperforge-search-result-tag",text:a.domain}),typeof a.abstract=="string"&&a.abstract){let f=a.abstract;s.createEl("div",{cls:"paperforge-search-result-abstract",text:f.length>200?f.slice(0,200)+"...":f})}if(t&&typeof a.text=="string"&&a.text){let f=a.text;s.createEl("div",{cls:"paperforge-search-result-source",text:f.length>300?f.slice(0,300)+"...":f})}}}_renderSearchError(e){this._searchResultsEl&&(this._searchResultsEl.empty(),this._searchResultsEl.createEl("div",{cls:"paperforge-search-error",text:e}))}_runAction(e,t){var p,f;if(e.disabled){new B.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 y=this.app.workspace.getActiveFile(),b=null;if(y){let m=this.app.metadataCache.getFileCache(y);if(m&&m.frontmatter&&m.frontmatter.zotero_key?b=m.frontmatter.zotero_key:b=this._extractZoteroKeyFromPath(y.path),b)n=[...n,b];else if(m&&m.frontmatter){this._showMessage("[!!] No zotero_key in active note frontmatter","error"),new B.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 B.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 B.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=[]}=L(r,(f=(p=this.app.plugins.plugins.paperforge)==null?void 0:p.settings)!=null?f:null,void 0,void 0),i=(0,fe.spawn)(s,[...l,"-m","paperforge",e.cmd,...n],{cwd:r,timeout:a}),c=[],d=Date.now(),g=setInterval(()=>this._fetchStats(!0),4e3);i.stdout.on("data",y=>{let b=y.toString("utf-8").split(`
|
|
`).filter(Boolean);for(let m of b){let x=m.trim();x&&(c.push(x),this._showMessage(c.slice(-8).join(`
|
|
`),"running"))}}),i.stderr.on("data",y=>{let b=y.toString("utf-8").split(`
|
|
`).filter(Boolean);for(let m of b){if(m.includes("\r")||m.includes("%")||m.includes("\u2588"))continue;let x=m.trim();x&&!x.match(/^\d+%|^\|/)&&(c.push(x),this._showMessage(c.slice(-8).join(`
|
|
`),"running"))}}),i.on("close",y=>{clearInterval(g),t.removeClass("running");let b=((Date.now()-d)/1e3).toFixed(1);if(y!==0){let m=c.slice(-3).join(" | ")||"exit code "+y;(e.cmd==="repair"||e.cmd==="ocr")&&y===1?(this._showMessage("[WARN] "+m,"running"),new B.Notice("[WARN] "+e.cmd+" partial: "+m,8e3),this._fetchStats(!0)):(this._showMessage("[!!] "+m,"error"),new B.Notice("[!!] "+e.cmd+" failed: "+m,8e3))}else if(e.needsKey||e.needsFilter){let m=c.join(`
|
|
`);if(m.trim())try{JSON.parse(m),navigator.clipboard.writeText(m).then(()=>{let x=`${b}s \u2014 ${m.length} chars copied`;this._showMessage("[OK] "+e.title+": "+x,"ok"),new B.Notice("[OK] "+e.okMsg+" \u2014 "+m.length+" chars")}).catch(x=>{this._showMessage("[!!] Clipboard write failed: "+x.message,"error"),new B.Notice("[!!] Clipboard error",6e3)})}catch(x){this._showMessage("[!!] Invalid JSON from "+e.title,"error"),new B.Notice("[!!] "+e.title+" returned invalid JSON: "+x.message.slice(0,100),8e3)}else this._showMessage("[!!] No output from context command","error"),new B.Notice("[!!] Context command returned empty output",8e3);this._fetchStats(!0)}else{let x=c.filter(E=>E.match(/updated \d+/)).pop()||c[c.length-1]||"",w=`${b}s \u2014 ${x}`;this._showMessage("[OK] "+e.title+": "+w,"ok"),new B.Notice("[OK] "+e.okMsg),this._contentEl&&this._contentEl.removeClass("switching"),this._cachedStats=null;try{this._fetchStats(!1)}catch(E){console.log("[PF] fetchStats error:",E)}console.log("[PF] close cmd="+e.cmd+" id="+e.id),e.cmd==="sync"&&Ne(this.app,this.app.plugins.plugins.paperforge,r)}}),i.on("error",y=>{t.removeClass("running"),this._contentEl&&this._contentEl.removeClass("switching"),this._showMessage("[!!] "+y.message,"error"),new B.Notice("[!!] Cannot start: "+y.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;case"versions":t.addClass("versions"),t.setText(o("version_panel_title")),this._headerTitle&&this._headerTitle.setText(o("version_panel_title"));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(_e);if(t.length>0){e.app.workspace.revealLeaf(t[0]);return}let r=e.app.workspace.getRightLeaf(!1);r&&(await r.setViewState({type:_e,active:!0}),e.app.workspace.revealLeaf(r))}};var He=class extends K.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(),at(this.app),this.registerView(_e,t=>new Ee(t));try{(0,K.addIcon)(Ce,st)}catch(t){}this.addRibbonIcon(Ce,"PaperForge Dashboard",()=>Ee.open(this)),Y.find(t=>t.id==="paperforge-ocr-redo")&&this.addRibbonIcon("reset","PaperForge: Redo OCR",()=>{let t=this.app.vault.adapter.basePath;new K.Notice("PaperForge: Redo OCR starting...");let{path:r,extraArgs:n}=L(t,this.settings,void 0,void 0);(0,ie.execFile)(r,[...n,"-m","paperforge","ocr","redo"],{cwd:t,timeout:6e5},(a,s,l)=>{if(a){new K.Notice("PaperForge: Redo OCR failed");return}new K.Notice("PaperForge: Redo OCR done")})}),this.addSettingTab(new je(this.app,this)),this.addCommand({id:"paperforge-status-panel",name:`PaperForge: ${o("guide_open")}`,callback:()=>Ee.open(this)});for(let t of Y)this.addCommand({id:t.id,name:`PaperForge: ${t.title}`,callback:()=>{if(t.disabled){new K.Notice(`[i] ${t.disabledMsg||"This action is not yet available."}`,6e3);return}let r=this.app.vault.adapter.basePath;new K.Notice(`PaperForge: running ${t.cmd}...`);let{path:n,extraArgs:a=[]}=L(r,this.settings,void 0,void 0),s=Array.isArray(t.args)?[...t.args]:[];(0,ie.execFile)(n,[...a,"-m","paperforge",t.cmd,...s],{cwd:r,timeout:3e5},(l,i,c)=>{if(l){new K.Notice(`[!!] ${t.cmd} failed: ${(c||l.message).slice(0,120)}`,8e3);return}new K.Notice(`[OK] ${t.okMsg||i.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=Q(e).memoryStatePath;if(!H.existsSync(r)){let n=L(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,ie.execFile)(n.path,l,{cwd:e,timeout:6e4,windowsHide:!0},()=>{})})}}_autoUpdate(){let e=this.app.vault.adapter.basePath,{path:t,extraArgs:r=[]}=L(e,this.settings,void 0,void 0),n=this.manifest.version,a=`paperforge==${n}`,s=`git+https://github.com/LLLin000/PaperForge.git@${n}`,l=(i,c)=>{(0,ie.spawn)(t,[...r,"-m","pip","install","--upgrade",i],{cwd:e,timeout:12e4,env:me()}).on("close",g=>c(g===0))};(0,ie.execFile)(t,[...r,"-c","import paperforge; print(paperforge.__version__)"],{cwd:e,timeout:1e4},(i,c)=>{let d=p=>{console.log(`[PaperForge] Auto-update: trying PyPI (paperforge==${n})`),l(a,f=>{if(f){console.log("[PaperForge] Auto-update: installed via PyPI"),new K.Notice(`[OK] PaperForge CLI ${p}`,5e3);return}console.warn("[PaperForge] Auto-update: PyPI failed, falling back to git..."),l(s,y=>{y&&(console.log("[PaperForge] Auto-update: installed via git"),new K.Notice(`[OK] PaperForge CLI ${p} (via git)`,5e3))})})};if(i){d("installed");return}let g=c.trim();g!==n&&d(`${g} -> ${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=Q(e).exportsDir;if(!H.existsSync(t))return;let r=0;try{H.readdirSync(t).forEach(n=>{if(!n.endsWith(".json"))return;let a=H.statSync(ke.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=L(e,this.settings,void 0,void 0);if(!t.path){this._autoSyncRunning=!1;return}let r=`"${t.path}" -m paperforge --vault "${e}" sync`;(0,ie.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=Q(e).exportsDir,i=0;H.readdirSync(l).forEach(c=>{c.endsWith(".json")&&(i=Math.max(i,H.statSync(ke.join(l,c)).mtimeMs))}),this._lastExportMtime=i}catch(l){}})}_checkOcr(e){if(this._autoSyncRunning)return;let t=Q(e).ocrDir;if(H.existsSync(t))try{H.readdirSync(t,{withFileTypes:!0}).forEach(r=>{if(!r.isDirectory())return;let n=ke.join(t,r.name,"meta.json");if(!H.existsSync(n))return;let a=H.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=L(e,this.settings,void 0,void 0);if(!l.path){this._autoSyncRunning=!1;return}let i=`"${l.path}" -m paperforge --vault "${e}" sync`;(0,ie.exec)(i,{timeout:3e4,encoding:"utf-8"},()=>{this._autoSyncRunning=!1,this._memoryStatusText=null})})}catch(r){}}readPaperforgeJson(){let e=this.app.vault.adapter.basePath,t=ke.join(e,"paperforge.json"),r={system_dir:"System",resources_dir:"Resources",literature_dir:"Literature",base_dir:"Bases"};try{if(!H.existsSync(t))return r;let n=H.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=ke.join(t,"paperforge.json"),n={};try{H.existsSync(r)&&(n=JSON.parse(H.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(H.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 K.Notice("PaperForge: Failed to save configuration to paperforge.json")}}onunload(){this._pollTimer&&clearInterval(this._pollTimer),this.app.workspace.detachLeavesOfType(_e)}async loadSettings(){this.settings=Object.assign({},Fe,await this.loadData()),this.settings.features&&Fe.features&&(this.settings.features=Object.assign({},Fe.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();H.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(Fe))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=(qe().versions||[]).find(l=>l.version===e);class s extends K.Modal{constructor(i,c){super(i),this._entry=c}onOpen(){let{contentEl:i}=this;if(i.createEl("h2",{text:`PaperForge v${e} \u66F4\u65B0\u8BF4\u660E`}),this._entry){if(i.createEl("p",{text:this._entry.title,cls:"paperforge-modal-subtitle"}),this._entry.breaking_or_migration&&this._entry.breaking_or_migration.length>0){i.createEl("h4",{text:"\u884C\u4E3A\u53D8\u66F4 / \u8FC1\u79FB\u6CE8\u610F"});for(let c of this._entry.breaking_or_migration)i.createEl("p",{text:`\u2022 ${c}`,cls:"paperforge-modal-item"})}if(this._entry.new_features&&this._entry.new_features.length>0){i.createEl("h4",{text:"\u65B0\u529F\u80FD"});for(let c of this._entry.new_features)i.createEl("p",{text:`\u2022 ${c}`,cls:"paperforge-modal-item"})}if(this._entry.fixes&&this._entry.fixes.length>0){i.createEl("h4",{text:"\u4FEE\u590D"});for(let c of this._entry.fixes)i.createEl("p",{text:`\u2022 ${c}`,cls:"paperforge-modal-item"})}if(this._entry.recommended_actions&&this._entry.recommended_actions.length>0){let c=i.createEl("div",{cls:"paperforge-release-recommended"});c.createEl("h4",{text:"\u5EFA\u8BAE\u64CD\u4F5C",cls:""}),c.style.marginBottom="8px";for(let d of this._entry.recommended_actions)c.createEl("p",{text:`\u2022 ${d}`,cls:"paperforge-release-item-bold"})}}else i.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 K.Setting(i).addButton(c=>c.setButtonText("\u77E5\u9053\u4E86").setCta().onClick(()=>{this.close()}))}onClose(){let{contentEl:i}=this;i.empty()}}new s(this.app,a).open(),this.settings.last_seen_version=e,this.saveSettings()}};
|