mirror of
https://github.com/lllin000/PaperForge.git
synced 2026-07-22 17:00:23 +00:00
49 lines
145 KiB
JavaScript
49 lines
145 KiB
JavaScript
"use strict";var mt=Object.create;var Fe=Object.defineProperty;var yt=Object.getOwnPropertyDescriptor;var bt=Object.getOwnPropertyNames;var vt=Object.getPrototypeOf,xt=Object.prototype.hasOwnProperty;var Et=(g,u)=>()=>(u||g((u={exports:{}}).exports,u),u.exports),kt=(g,u)=>{for(var e in u)Fe(g,e,{get:u[e],enumerable:!0})},Ye=(g,u,e,t)=>{if(u&&typeof u=="object"||typeof u=="function")for(let s of bt(u))!xt.call(g,s)&&s!==e&&Fe(g,s,{get:()=>u[s],enumerable:!(t=yt(u,s))||t.enumerable});return g};var z=(g,u,e)=>(e=g!=null?mt(vt(g)):{},Ye(u||!g||!g.__esModule?Fe(e,"default",{value:g,enumerable:!0}):e,g)),wt=g=>Ye(Fe({},"__esModule",{value:!0}),g);var Ne=Et((At,St)=>{St.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 Tt={};kt(Tt,{default:()=>Ae});module.exports=wt(Tt);var M=require("obsidian"),L=z(require("fs")),_e=z(require("path")),se=require("child_process");var ce="paperforge-status",xe="paperforge",Qe='<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>',H=[{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"}],Ee={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 et(g,u){if(!u||!u.note_path)return u;let e=g.vault.getAbstractFileByPath(u.note_path);if(!e)return u;let t=g.metadataCache.getFileCache(e),s=t&&t.frontmatter;if(!s)return u;let n={...u};for(let a of["do_ocr","analyze","ocr_status","ocr_redo","deep_reading_status"])Object.prototype.hasOwnProperty.call(s,a)&&(n[a]=s[a]);return n}function Ie(g,u){return g&&{...g,...u}}var Le={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",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"},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",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"}},Me=null;function Pt(g){try{let u=g.vault;if(typeof u.getConfig=="function"){let e=u.getConfig("language");if(e&&String(e).startsWith("zh"))return"zh"}}catch(u){}try{if(typeof localStorage!="undefined"){let u=localStorage.getItem("language");if(u&&String(u).startsWith("zh"))return"zh"}}catch(u){}return"en"}function tt(g){Me=Pt(g)==="zh"?Le.zh:Le.en}function i(g){return Me&&Me[g]||Le.en[g]||g}var P=require("obsidian"),I=z(require("fs")),$=z(require("path")),gt=z(require("os")),V=require("child_process");var ft=z(Ne());var Q=z(require("fs")),Y=z(require("path")),rt=z(require("os")),re=require("child_process"),ze=null,st=!1;function O(g,u,e,t){let s=e||Q,n=t||re.execFileSync;if(u&&u.python_path&&u.python_path.trim()){let l=u.python_path.trim();if(s.existsSync(l))return{path:l,source:"manual",extraArgs:[]}}let a=[Y.join(g,".paperforge-test-venv","Scripts","python.exe"),Y.join(g,".venv","Scripts","python.exe"),Y.join(g,"venv","Scripts","python.exe")];for(let l of a)try{if(s.existsSync(l))return{path:l,source:"auto-detected",extraArgs:[]}}catch(o){}let r=[{path:"py",extraArgs:["-3"]},{path:"python",extraArgs:[]},{path:"python3",extraArgs:[]}];for(let l of r)try{let o=n(l.path,[...l.extraArgs,"--version"],{encoding:"utf-8",timeout:5e3,windowsHide:!0});if(o&&o.toLowerCase().includes("python"))return{path:l.path,source:"auto-detected",extraArgs:l.extraArgs}}catch(o){}return{path:"python",source:"auto-detected",extraArgs:[]}}function nt(g,u,e,t,s){t===void 0&&(t=1e4);let n=s||re.execFile;return new Promise(a=>{n(g,["-c","import paperforge; print(paperforge.__version__)"],{cwd:e,timeout:t},(r,l)=>{if(r){a({status:"not-installed",pyVersion:null,pluginVersion:u,error:r.message});return}let o=l&&l.trim()||null;a(o===u?{status:"match",pyVersion:o,pluginVersion:u,error:null}:{status:"mismatch",pyVersion:o,pluginVersion:u,error:null})})})}function at(g,u,e){e===void 0&&(e=[]);let t=`paperforge==${u}`,s=`git+https://github.com/LLLin000/PaperForge.git@${u}`,n=[...e,"-m","pip","install","--upgrade",t],a=[...e,"-m","pip","install","--upgrade",s];return{cmd:g,url:s,args:a,pypiArgs:n,gitArgs:a,timeout:12e4}}function it(g,u,e,t,s,n){let a=s||re.spawn;return new Promise(r=>{let l=Date.now(),o={cwd:e,timeout:t,windowsHide:!0};n&&(o.env=n);let c=a(g,u,o),p=[],h=[];c.stdout.on("data",d=>{p.push(d.toString("utf-8"))}),c.stderr.on("data",d=>{h.push(d.toString("utf-8"))}),c.on("close",d=>{r({stdout:p.join(""),stderr:h.join(""),exitCode:d,elapsed:Date.now()-l})}),c.on("error",d=>{r({stdout:p.join(""),stderr:h.join("")+`
|
|
`+d.message,exitCode:-1,elapsed:Date.now()-l})})})}function $e(){if(st)return ze;st=!0;try{let g;if(process.platform==="win32"){let u=process.env.ComSpec||"C:\\Windows\\System32\\cmd.exe";g=(0,re.execFileSync)(u,["/c","where","git"],{timeout:5e3,windowsHide:!0,encoding:"utf-8"})}else g=(0,re.execFileSync)("which",["git"],{timeout:5e3,encoding:"utf-8"});if(g){let u=g.split(`
|
|
`)[0].trim();u&&(ze=Y.dirname(u))}}catch(g){}return ze}function pe(){let g={...process.env},u=process.platform,e=rt.homedir(),t=[],s=$e();s&&t.push(s),u==="darwin"?t.push("/opt/homebrew/bin","/usr/local/bin","/usr/bin",`${e}/.local/bin`):u==="linux"&&t.push("/usr/local/bin","/usr/bin",`${e}/.local/bin`);let n=g.PATH||"";return g.PATH=[...t,n].filter(Boolean).join(Y.delimiter),g}function ot(g){return String(g).toLowerCase().replace(/[^a-z0-9]/g,"").includes("betterbibtex")}function je(g){if(!g)return!1;try{if(!Q.existsSync(g))return!1;for(let u of Q.readdirSync(g))if(ot(u))return!0}catch(u){}return!1}function Te(g){if(!g)return!1;try{if(!Q.existsSync(g))return!1;for(let u of Q.readdirSync(g)){let e=Y.join(g,u,"extensions");try{if(!Q.existsSync(e))continue;for(let t of Q.readdirSync(e))if(ot(t))return!0}catch(t){}}}catch(u){}return!1}var de=z(require("fs")),N=z(require("path")),lt=require("child_process"),ee=null;function Ct(g,u){let e=u||de,t=N.join(g,"paperforge.json"),s={system_dir:"System",resources_dir:"Resources",literature_dir:"Literature",base_dir:"Bases"};try{if(!e.existsSync(t))return{...s,_warning:"paperforge.json not found; using defaults"};let n=e.readFileSync(t,"utf-8"),a=JSON.parse(n),r=a.vault_config||{};return{system_dir:r.system_dir||a.system_dir||s.system_dir,resources_dir:r.resources_dir||a.resources_dir||s.resources_dir,literature_dir:r.literature_dir||a.literature_dir||s.literature_dir,base_dir:r.base_dir||a.base_dir||s.base_dir,_warning:null}}catch(n){return console.warn("PaperForge: Failed to read paperforge.json, using defaults",n),{...s,_warning:"paperforge.json invalid; using defaults"}}}function te(g,u){let e=Ct(g,u),t=N.join(g,e.system_dir,"PaperForge");return{vault:g,systemDir:t,indexesDir:N.join(t,"indexes"),logsDir:N.join(t,"logs"),dbPath:N.join(t,"indexes","paperforge.db"),memoryStatePath:N.join(t,"indexes","memory-runtime-state.json"),vectorStatePath:N.join(t,"indexes","vector-runtime-state.json"),healthStatePath:N.join(t,"indexes","runtime-health.json"),buildStatePath:N.join(t,"indexes","vector-build-state.json"),orphanStatePath:N.join(t,"indexes","sync-orphan-state.json"),exportsDir:N.join(t,"exports"),ocrDir:N.join(t,"ocr"),pluginDataPath:N.join(g,".obsidian","plugins","paperforge","data.json"),pfJsonPath:N.join(g,"paperforge.json"),configWarning:e._warning}}function He(g){try{return de.existsSync(g)?JSON.parse(de.readFileSync(g,"utf-8")):null}catch(u){return null}}function Ft(g){let u=te(g);return He(u.memoryStatePath)}function ke(g){let u=te(g);return He(u.vectorStatePath)}function Ve(g){let u=te(g);return He(u.healthStatePath)}function ct(g){var e;let u=Ve(g);return!!(u&&((e=u.summary)==null?void 0:e.status)==="ok")}function De(g){let u=Ft(g);return!u||u.paper_count_db===0?"DB not found. Run paperforge memory build.":"Papers: "+u.paper_count_db+" | "+(u.fresh?"fresh":"stale")}function ge(g){let u=ke(g);return u?u.healthy===!1?"Vector index unreadable - rebuild required":"Chunks: "+u.chunk_count+" | "+u.model+" | "+u.mode:"Status unavailable"}function ne(g,u){if(ee)return ee;if(u&&u.python_path&&u.python_path.trim()){let s=u.python_path.trim();if(de.existsSync(s))return ee={path:s,source:"manual",extraArgs:[]},ee}let e=[N.join(g,".paperforge-test-venv","Scripts","python.exe"),N.join(g,".venv","Scripts","python.exe"),N.join(g,"venv","Scripts","python.exe")];for(let s=0;s<e.length;s++)if(de.existsSync(e[s]))return ee={path:e[s],source:"auto-detected",extraArgs:[]},ee;let t=[{path:"py",extraArgs:["-3"]},{path:"python",extraArgs:[]},{path:"python3",extraArgs:[]}];for(let s=0;s<t.length;s++)try{let n=t[s],a=(0,lt.execFileSync)(n.path,n.extraArgs.concat(["--version"]),{encoding:"utf-8",timeout:5e3,windowsHide:!0});if(a&&a.toLowerCase().indexOf("python")!==-1)return ee={path:n.path,source:"auto-detected",extraArgs:n.extraArgs},ee}catch(n){}return ee={path:"python",source:"auto-detected",extraArgs:[]},ee}function Ke(g,u,e){return!g||typeof g!="object"||!Object.prototype.hasOwnProperty.call(g,u)?!!e:!!g[u]}function pt(g,u,e){let t=!Ke(g,u,e);return g&&typeof g=="object"&&(g[u]=t),t}var Z=require("obsidian"),G=z(require("fs")),ut=z(require("path")),ht=z(require("https")),Pe=require("child_process");function dt(g,u){return!u||!u.trim()?{blocked:!0,reason:"zotero"}:g?{blocked:!1}:{blocked:!0,reason:"ocr"}}var Ze=class extends Z.Modal{constructor(e,t,s,n){super(e);this._rowEls=[];this.orphans=t.map((a,r)=>({...a,_selected:!0,_idx:r})),this.vaultPath=s,this.py=n}_updateUI(){let e=this.orphans.filter(t=>t._selected);this._countEl.setText(i("orphan_delete_selected").replace("{count}",String(e.length))),this._selectAllBtn.setText(e.length===this.orphans.length?i("orphan_deselect_all"):i("orphan_select_all"));for(let t of this.orphans){let s=this._rowEls[t._idx];s&&s.toggleClass("paperforge-orphan-dimmed",!t._selected)}}onOpen(){let{contentEl:e}=this;e.addClass("paperforge-modal"),e.createEl("h2",{text:i("orphan_title").replace("{count}",String(this.orphans.length))}),e.createEl("p",{cls:"paperforge-modal-desc",text:i("orphan_desc")}),this._rowEls=[];let t=e.createEl("div",{cls:"paperforge-orphan-list"});for(let n of this.orphans){let a=t.createEl("div",{cls:"paperforge-orphan-row"+(n._selected?"":" paperforge-orphan-dimmed")});this._rowEls.push(a);let r=a.createEl("div",{cls:"paperforge-orphan-info"}),l=r.createEl("div",{cls:"paperforge-orphan-header"});l.createEl("span",{cls:"paperforge-orphan-key",text:n.citation_key||n.key});let o=l.createEl("span",{cls:"paperforge-orphan-tags"});o.createEl("span",{cls:"paperforge-tag "+(n.has_pdf?"tag-pdf":"tag-nopdf"),text:n.has_pdf?"PDF":"no PDF"}),n.collection_path&&o.createEl("span",{cls:"paperforge-tag tag-collection",text:n.collection_path}),n.title&&r.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&&r.createEl("div",{cls:"paperforge-orphan-meta",text:c.join(" \xB7 ")}),r.createEl("div",{cls:"paperforge-orphan-explain",text:i("orphan_explain")}),a.addEventListener("click",()=>{n._selected=!n._selected,this._updateUI()})}let s=e.createEl("div",{cls:"paperforge-modal-actions"});this._selectAllBtn=s.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=s.createEl("button",{cls:"paperforge-step-btn mod-cta",text:"Delete "+this.orphans.length+" selected"}),s.createEl("button",{cls:"paperforge-step-btn",text:"Keep all"}).addEventListener("click",()=>this.close()),this._countEl.addEventListener("click",()=>{let n=this.orphans.filter(r=>r._selected);if(n.length===0){new Z.Notice(i("orphan_none_selected"));return}if(this._countEl.setText("Deleting..."),this._countEl.setAttr("disabled",""),this._selectAllBtn.setAttr("disabled",""),!this.py||!this.py.path){new Z.Notice("PaperForge: Python not found"),this.close();return}let a=n.map(r=>r.key);(0,Pe.execFile)(this.py.path,[...this.py.extraArgs,"-m","paperforge","--vault",this.vaultPath,"prune","--force","--json",...a],{cwd:this.vaultPath,timeout:6e4},(r,l)=>{if(r){new Z.Notice("PaperForge: prune failed"),this.close();return}try{let o=JSON.parse(l),c=o.data&&o.data.deleted||[];new Z.Notice("Deleted "+c.length+" orphan workspace(s)")}catch(o){new Z.Notice("PaperForge: prune done")}this.close()})})}onClose(){this.contentEl.empty()}};function Re(g,u,e){console.log("[PF] checkOrphanState called");try{let s=te(e).orphanStatePath;if(!G.existsSync(s)){console.log("[PF] orphan file NOT FOUND");return}console.log("[PF] orphan file FOUND");let n=G.readFileSync(s,"utf-8"),r=JSON.parse(n).orphans||[];if(console.log("[PF] orphans count:",r.length),r.length===0)return;let l=ne(e,u.settings);console.log("[PF] py.path:",l?l.path:"null"),new Ze(g,r,e,l).open(),G.unlinkSync(s),console.log("[PF] orphan file cleaned")}catch(t){console.log("[PF] checkOrphanState exception:",t.message||t)}}var we=class extends Z.Modal{constructor(e,t){super(e);this._pendingSave=null;this._showSkipConfirm=!1;this.plugin=t,this._step=1}onOpen(){this._render()}onClose(){this.contentEl.empty()}_render(){let{contentEl:e}=this;e.empty(),e.addClass("paperforge-modal"),this._renderStepIndicator(),this._renderStepContent(),this._renderNavigation()}_renderStepIndicator(){let e=[i("wizard_step1"),i("wizard_step2"),i("wizard_step3"),i("wizard_step4"),i("wizard_step5")],t=this.contentEl.createEl("div",{cls:"paperforge-step-bar"});e.forEach((s,n)=>{let a=n+1,r=t.createEl("div",{cls:`paperforge-step-dot ${a===this._step?"active":""} ${a<this._step?"done":""}`});r.createEl("span",{cls:"paperforge-step-num",text:`${a}`}),r.createEl("span",{cls:"paperforge-step-label",text:s})})}_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:i("nav_prev")}).addEventListener("click",()=>{this._step--,this._showSkipConfirm=!1,this._render()}),this._step<5?e.createEl("button",{cls:"paperforge-step-btn mod-cta",text:i("nav_next")}).addEventListener("click",()=>{if(this._step===3){let s=this._validateStep3();if(s.blocked){if(s.reason==="zotero")return;if(s.reason==="ocr"){this._showSkipConfirm=!0,this._render();return}}}this._step++,this._showSkipConfirm=!1,this._render()}):e.createEl("button",{cls:"paperforge-step-btn",text:i("nav_close")}).addEventListener("click",()=>this.close())}_validateStep3(){let e=this.plugin.settings,t=dt(this._apiKeyValidated,e.zotero_data_dir);if(t.reason==="ocr")return t;let s=(e.zotero_data_dir||"").trim();if(!s)return new Z.Notice("Zotero \u6570\u636E\u76EE\u5F55\u4E3A\u5FC5\u586B\u9879\uFF0C\u8BF7\u586B\u5199\u8DEF\u5F84"),{blocked:!0,reason:"zotero"};if(!G.existsSync(s))return new Z.Notice("Zotero \u6570\u636E\u76EE\u5F55\u8DEF\u5F84\u4E0D\u5B58\u5728"),{blocked:!0,reason:"zotero"};if(!G.statSync(s).isDirectory())return new Z.Notice("Zotero \u6570\u636E\u76EE\u5F55\u8DEF\u5F84\u4E0D\u662F\u4E00\u4E2A\u76EE\u5F55"),{blocked:!0,reason:"zotero"};let n=ut.join(s,"storage");return!G.existsSync(n)||!G.statSync(n).isDirectory()?(new Z.Notice("Zotero \u6570\u636E\u76EE\u5F55\u4E2D\u672A\u627E\u5230 storage/ \u5B50\u76EE\u5F55"),{blocked:!0,reason:"zotero"}):{blocked:!1}}_stepOverview(e){e.createEl("h2",{text:i("wizard_title")}),e.createEl("p",{text:i("wizard_intro")});let t=this.plugin.settings,s=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 (${s})`;let r=n.createEl("div",{cls:"paperforge-dir-children"}),l=r.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`}),r.createEl("div",{cls:"paperforge-dir-node folder",text:`\u{1F4C1} ${t.base_dir||"Bases"}/ \u2014 \u6570\u636E\u7BA1\u7406\u9762\u677F`}),r.createEl("div",{cls:"paperforge-dir-node folder",text:`\u{1F4C1} ${t.system_dir||"System"}/ \u2014 Zotero \u8F6F\u94FE\u63A5 + PaperForge \u7CFB\u7EDF\u6587\u4EF6\u5939`}),e.createEl("p",{text:i("wizard_preview"),cls:"paperforge-modal-hint"}),e.createEl("p",{text:i("wizard_safety"),cls:"paperforge-modal-hint"});let c=e.createEl("div",{cls:"paperforge-summary"}),p=[{label:i("dir_resources"),val:`${s}/${t.resources_dir||"Resources"}`},{label:i("dir_notes"),val:`${s}/${t.resources_dir||"Resources"}/${t.literature_dir||"Literature"}`},{label:i("dir_base"),val:`${s}/${t.base_dir||"Bases"}`},{label:i("dir_system"),val:`${s}/${t.system_dir||"System"}`}];for(let h of p){let d=c.createEl("div",{cls:"paperforge-summary-row"});d.createEl("span",{cls:"paperforge-summary-label",text:h.label}),d.createEl("span",{cls:"paperforge-summary-value",text:h.val})}}_stepDirectories(e){e.createEl("h2",{text:i("wizard_step2")}),e.createEl("p",{text:i("wizard_intro")});let t=this.plugin.settings,s=this.app.vault.adapter.basePath;this._modalField(e,i("dir_vault"),s,!0),e.createEl("p",{text:i("wizard_dir_hint"),cls:"paperforge-modal-hint"}),this._modalInput(e,"\u8D44\u6E90\u76EE\u5F55\uFF08\u521B\u5EFA\u6587\u732E\u5361\u7247\u76EE\u5F55\u7684\u5730\u65B9\uFF09","resources_dir",t.resources_dir,"Resources"),e.createEl("p",{text:i("wizard_dir_sub_hint"),cls:"paperforge-modal-hint"}),this._modalInput(e,"\u6587\u732E\u5361\u7247\u76EE\u5F55\uFF08\u5B58\u653E\u6587\u732E\u5361\u7247\u7684\u5730\u65B9\uFF0CBase \u6570\u636E\u6765\u6E90\uFF09","literature_dir",t.literature_dir,"Literature"),e.createEl("p",{text:i("wizard_sys_hint"),cls:"paperforge-modal-hint"}),this._modalInput(e,"\u7CFB\u7EDF\u76EE\u5F55\uFF08\u5B58\u653E Zotero \u8F6F\u94FE\u63A5\u548C PaperForge \u7CFB\u7EDF\u6587\u4EF6\uFF09","system_dir",t.system_dir,"System"),this._modalInput(e,"Base \u76EE\u5F55\uFF08\u5B58\u653E\u6570\u636E\u7BA1\u7406\u9762\u677F\u7684\u5730\u65B9\uFF09","base_dir",t.base_dir,"Bases"),e.createEl("p",{text:i("wizard_safety"),cls:"paperforge-modal-hint"});let n=e.createEl("div",{cls:"paperforge-summary"}),a=[{label:i("dir_resources"),val:`${s}/${t.resources_dir||""}`},{label:i("dir_notes"),val:`${s}/${t.resources_dir||""}/${t.literature_dir||""}`},{label:i("dir_system"),val:`${s}/${t.system_dir||""}`},{label:i("dir_base"),val:`${s}/${t.base_dir||""}`}];for(let r of a){let l=n.createEl("div",{cls:"paperforge-summary-row"});l.createEl("span",{cls:"paperforge-summary-label",text:r.label}),l.createEl("span",{cls:"paperforge-summary-value",text:r.val})}}_stepKeys(e){if(e.createEl("h2",{text:i("wizard_step3")}),this._showSkipConfirm){this._renderSkipConfirm(e);return}let t=this.plugin.settings;e.createEl("p",{text:i("wizard_agent_hint"),cls:"paperforge-modal-hint"});let s=[{key:"opencode",name:"OpenCode"},{key:"claude",name:"Claude Code"},{key:"cursor",name:"Cursor"},{key:"github_copilot",name:"GitHub Copilot"},{key:"windsurf",name:"Windsurf"},{key:"codex",name:"Codex"},{key:"gemini",name:"Gemini CLI"},{key:"cline",name:"Cline"}],n=e.createEl("div",{cls:"paperforge-modal-field"});n.createEl("label",{cls:"paperforge-modal-label",text:i("label_agent")});let a=n.createEl("select",{cls:"paperforge-modal-select"});for(let h of s){let d=a.createEl("option",{text:h.name,attr:{value:h.key}});h.key===(t.agent_platform||"opencode")&&(d.selected=!0)}a.addEventListener("change",()=>{t.agent_platform=a.value,this._pendingSave&&clearTimeout(this._pendingSave),this._pendingSave=setTimeout(()=>{this.plugin.saveSettings(),this._pendingSave=null},500)}),e.createEl("p",{text:i("wizard_keys_hint"),cls:"paperforge-modal-hint"});let r=e.createEl("div",{cls:"paperforge-modal-field"});r.createEl("label",{cls:"paperforge-modal-label",text:i("field_paddleocr")});let l=r.createEl("input",{cls:"paperforge-modal-input",attr:{type:"password",placeholder:"API Key"}});l.value=t.paddleocr_api_key||"",this._apiKeyValidated=!1,this._apiKeyStatus=r.createEl("span",{cls:"paperforge-apikey-status",text:""});let o=r.createEl("button",{cls:"paperforge-step-btn",text:"\u9A8C\u8BC1"});o.addEventListener("click",()=>this._validateApiKey(l.value,o)),l.addEventListener("input",()=>{t.paddleocr_api_key=l.value,this._apiKeyValidated=!1,this._apiKeyStatus.textContent="",this._apiKeyStatus.className="paperforge-apikey-status"}),this._pendingSave&&clearTimeout(this._pendingSave),this._pendingSave=setTimeout(()=>{this.plugin.saveSettings(),this._pendingSave=null},500),e.createEl("p",{text:i("wizard_api_hint_skip"),cls:"paperforge-modal-hint"});let c=e.createEl("div",{cls:"paperforge-modal-field"});c.createEl("label",{cls:"paperforge-modal-label",text:i("field_zotero_data")});let p=c.createEl("input",{cls:"paperforge-modal-input",attr:{type:"text",placeholder:i("field_zotero_placeholder")}});p.value=t.zotero_data_dir||"",p.addEventListener("input",()=>{t.zotero_data_dir=p.value,this._pendingSave&&clearTimeout(this._pendingSave),this._pendingSave=setTimeout(()=>{this.plugin.saveSettings(),this._pendingSave=null},500)})}_validateApiKey(e,t){if(!e||e.length<10){this._apiKeyStatus.textContent="\u5BC6\u94A5\u683C\u5F0F\u4E0D\u6B63\u786E\u3002\u53EF\u70B9\u4E0B\u4E00\u6B65\u8DF3\u8FC7\uFF0C\u7B49\u4F1A\u513F\u518D\u914D\u7F6E\u3002",this._apiKeyStatus.className="paperforge-apikey-status error";return}t.disabled=!0,t.textContent="\u9A8C\u8BC1\u4E2D\u2026",this._apiKeyStatus.textContent="\u6B63\u5728\u9A8C\u8BC1\u2026",this._apiKeyStatus.className="paperforge-apikey-status";let s=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(s)},timeout:1e4},a=ht.request(n,r=>{t.disabled=!1,t.textContent="\u9A8C\u8BC1";let l="";r.on("data",o=>l+=o),r.on("end",()=>{try{let o=JSON.parse(l);r.statusCode===400&&o.code===10001?(this._apiKeyStatus.textContent="\u2713 \u5BC6\u94A5\u6709\u6548",this._apiKeyStatus.className="paperforge-apikey-status ok",this._apiKeyValidated=!0):r.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 "+r.statusCode+"\u3002\u53EF\u70B9\u4E0B\u4E00\u6B65\u8DF3\u8FC7\uFF0C\u7B49\u4F1A\u513F\u518D\u914D\u7F6E\u3002",this._apiKeyStatus.className="paperforge-apikey-status error",this._apiKeyValidated=!1)}catch(o){this._apiKeyStatus.textContent="\u9A8C\u8BC1\u5931\u8D25\uFF1A\u65E0\u6CD5\u89E3\u6790\u54CD\u5E94\u3002\u53EF\u70B9\u4E0B\u4E00\u6B65\u8DF3\u8FC7\uFF0C\u7B49\u4F1A\u513F\u518D\u914D\u7F6E\u3002",this._apiKeyStatus.className="paperforge-apikey-status error",this._apiKeyValidated=!1}})});a.on("error",r=>{t.disabled=!1,t.textContent="\u9A8C\u8BC1",this._apiKeyStatus.textContent="\u9A8C\u8BC1\u5931\u8D25\uFF1A\u65E0\u6CD5\u8FDE\u63A5 ("+r.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(s),a.end()}_renderSkipConfirm(e){e.createEl("p",{text:i("wizard_skip_ocr_desc"),cls:"paperforge-modal-desc"});let t=e.createEl("div",{cls:"paperforge-modal-actions"});t.createEl("button",{cls:"paperforge-step-btn mod-cta",text:i("wizard_skip_ocr_continue")}).addEventListener("click",()=>{this._showSkipConfirm=!1,this._step++,this._render()}),t.createEl("button",{cls:"paperforge-step-btn",text:i("wizard_skip_ocr_back")}).addEventListener("click",()=>{this._showSkipConfirm=!1,this._render()})}_modalField(e,t,s,n){let a=e.createEl("div",{cls:"paperforge-modal-field"});a.createEl("label",{cls:"paperforge-modal-label",text:t});let r=a.createEl("input",{cls:"paperforge-modal-input",attr:{type:"text"}});r.value=s,r.disabled=!!n}_modalInput(e,t,s,n,a){let r=e.createEl("div",{cls:"paperforge-modal-field"});r.createEl("label",{cls:"paperforge-modal-label",text:t});let l=r.createEl("input",{cls:"paperforge-modal-input",attr:{type:"text",placeholder:a||""}});l.value=n;let o=this.plugin.settings;l.addEventListener("input",()=>{o[s]=l.value,this._pendingSave&&clearTimeout(this._pendingSave),this._pendingSave=setTimeout(()=>{this.plugin.saveSettings(),this._pendingSave=null},500)})}_modalSecret(e,t,s,n,a){let r=e.createEl("div",{cls:"paperforge-modal-field"});r.createEl("label",{cls:"paperforge-modal-label",text:t});let l=r.createEl("input",{cls:"paperforge-modal-input",attr:{type:"password",placeholder:a||""}});l.value=n;let o=this.plugin.settings;l.addEventListener("input",()=>{o[s]=l.value,this._pendingSave&&clearTimeout(this._pendingSave),this._pendingSave=setTimeout(()=>{this.plugin.saveSettings(),this._pendingSave=null},500)})}_stepInstall(e){e.createEl("h2",{text:i("wizard_step4")}),this._installLog=e.createEl("div",{cls:"paperforge-install-log"});let t=e.createEl("button",{cls:"paperforge-step-btn mod-cta",text:i("install_btn")});t.addEventListener("click",()=>this._runInstall(t))}async _runInstall(e){var r,l,o,c,p,h;e.disabled=!0,e.textContent=i("install_btn_running"),this._installLog.setText(i("install_validating")+`
|
|
`),this._log(i("install_validating"));let t=this.plugin.settings,s=this._validate();if(s.length>0){this._log(i("validate_fail")+":"),s.forEach(d=>this._log(" \u2717 "+d)),e.disabled=!1,e.textContent=i("install_btn_retry");return}let n=(d,y={})=>new Promise((b,v)=>{let{path:f,extraArgs:x=[]}=O(t.vault_path.trim(),this.plugin.settings,void 0,void 0),C=(0,Pe.spawn)(f,[...x,...d],{cwd:t.vault_path.trim(),env:pe(),timeout:12e4,...y}),E="",_="";C.stdout.on("data",m=>{let k=m.toString("utf-8");E+=k,y.logStdout&&this._processSetupOutput(k)}),C.stderr.on("data",m=>{let k=m.toString("utf-8");_+=k,this._log("[stderr] "+k.trim())}),C.on("close",m=>{m===0?b({stdout:E,stderr:_}):v(new Error(_.trim()||E.trim()||`exit code ${m}`))}),C.on("error",m=>v(m))}),a=["-m","paperforge","--vault",t.vault_path.trim(),"setup","--headless","--system-dir",t.system_dir.trim(),"--resources-dir",t.resources_dir.trim(),"--literature-dir",t.literature_dir.trim(),"--base-dir",t.base_dir.trim(),"--agent",t.agent_platform||"opencode"];t.zotero_data_dir&&t.zotero_data_dir.trim()&&a.push("--zotero-data",t.zotero_data_dir.trim()),t.paddleocr_api_key&&t.paddleocr_api_key.trim()&&a.push("--paddleocr-key",t.paddleocr_api_key.trim());try{let d=!0;try{await n(["-c","import paperforge"])}catch(y){d=!1}if(!d){this._log(i("install_bootstrapping"));let y=this.plugin.manifest.version;this._log(`[install] Trying PyPI: pip install paperforge==${y}`);let b=["-m","pip","install","--upgrade"];process.platform!=="win32"&&b.push("--user"),b.push(`paperforge==${y}`);try{await n(b,{logStdout:!0})}catch(v){this._log(`[install] PyPI failed, falling back to git: git+https://...@v${y}`),console.warn("[PaperForge] PyPI install failed, falling back to git:",(r=v.message)==null?void 0:r.slice(0,200));let f=["-m","pip","install","--upgrade"];process.platform!=="win32"&&f.push("--user"),f.push(`git+https://github.com/LLLin000/PaperForge.git@v${y}`),await n(f,{logStdout:!0})}}await n(a,{logStdout:!0,env:pe()}),this._log(i("install_complete")),t.setup_complete=!0,await this.plugin.saveSettings(),setTimeout(()=>{this._step=5,this._render()},800)}catch(d){console.error("PaperForge setup failed:",d.message);let y=this._formatSetupError(d.message);this._log(i("install_failed")+y);let b=(l=this._installLog.parentElement)==null?void 0:l.createEl("button",{cls:"paperforge-copy-diag-btn",text:i("error_copy_diagnostic")||"Copy diagnostic"});if(b){let v=d.message,f=((c=(o=this.plugin)==null?void 0:o.settings)==null?void 0:c.python_path)||"auto",x=((h=(p=this.plugin)==null?void 0:p.manifest)==null?void 0:h.version)||"?",C=process.platform+" "+process.arch,E,_;try{E=$e()||"(not found)"}catch(F){E="(error)"}try{_=O(t.vault_path.trim(),this.plugin.settings,void 0,void 0)}catch(F){_=null}let m=(process.env.PATH||"").length,k=(process.env.PATH||"").toLowerCase().includes("git"),S=["[PaperForge Diagnostic]","Category: "+y,"Plugin version: "+x,"Python: "+f,"Resolved Python: "+((_==null?void 0:_.path)||"?"),"OS: "+C,"Vault path: "+(t.vault_path||"?"),"--- Git ---","Git dir (resolved): "+E,"PATH length: "+m+" chars","PATH contains git: "+k,"--- Raw error ---",v.slice(0,2e3)].join(`
|
|
`);b.addEventListener("click",()=>{navigator.clipboard.writeText(S).then(()=>{b.setText(i("error_copied")||"Copied!"),setTimeout(()=>{b.setText(i("error_copy_diagnostic")||"Copy diagnostic")},3e3)}).catch(()=>{new Z.Notice("[!!] Clipboard write failed",6e3)})})}e.disabled=!1,e.textContent=i("install_btn_retry")}}_log(e){this._installLog&&this._installLog.setText(this._installLog.textContent+e+`
|
|
`)}_validate(){let e=[],t=this.plugin.settings;return(!t.vault_path||!t.vault_path.trim())&&e.push(i("validate_vault")),(!t.resources_dir||!t.resources_dir.trim())&&e.push(i("validate_resources")),(!t.literature_dir||!t.literature_dir.trim())&&e.push(i("validate_notes")),(!t.base_dir||!t.base_dir.trim())&&e.push(i("validate_base")),(!t.paddleocr_api_key||!t.paddleocr_api_key.trim())&&this._log(" ! "+i("validate_key")+" "+i("optional_later")),(!t.zotero_data_dir||!t.zotero_data_dir.trim())&&this._log(" ! "+i("validate_zotero")+" "+i("optional_later")),e}_processSetupOutput(e){let t=e.split(`
|
|
`).filter(Boolean);for(let s of t)if(s.includes("[*]")||s.includes("[OK]")||s.includes("[FAIL]")){let n=s.replace(/^\[\*\].*\d+:?\s*/,"").replace(/^\[OK\]\s*/,"").replace(/^\[FAIL\]\s*/,"");this._log(" "+n)}}_formatSetupError(e){if(process.platform==="darwin"&&/No module named ['"]?paperforge/i.test(e))return"PaperForge not installed \u2014 install Python from Homebrew or python.org (Apple CLT /Library/Developer/CommandLineTools python often fails); then: python3 -m pip install --user git+https://github.com/LLLin000/PaperForge.git";let t=[{match:/pip.*not found|No module named.*pip|command not found.*pip/i,msg:"pip not found"},{match:/command not found|No such file|not recognized/i,msg:"Python not found"},{match:/resolve host|getaddrinfo.*nodename|connect ETIMEDOUT|connect ECONNREFUSED|fetch failed|Network error|ENOTFOUND|ECONNREFUSED|ECONNRESET/i,msg:"Network error"},{match:/certificate verify failed|SSL.*certificate|self.signed.cert|CERTIFICATE_VERIFY_FAILED/i,msg:"SSL certificate error"},{match:/No space left on device|disk full|ENOSPC/i,msg:"Disk full"},{match:/paperforge.*not found|cannot import|ModuleNotFoundError|No module named/i,msg:"PaperForge not installed"},{match:/permission denied|EACCES|EPERM/i,msg:"Permission denied"},{match:/ENOENT/i,msg:"Path not found"},{match:/timeout|timed out/i,msg:"Timeout"}];for(let n of t)if(n.match.test(e))return n.msg;return e.split(`
|
|
`).filter(Boolean).slice(0,3).join(" | ").slice(0,200)||"Unknown error"}_stepComplete(e){e.createEl("h2",{text:i("complete_title")});let t=e.createEl("div",{cls:"paperforge-summary"});t.createEl("div",{cls:"paperforge-summary-title",text:i("complete_summary")});let s=this.plugin.settings,n=this.app.vault.adapter.basePath,a=[{label:i("dir_vault"),val:n},{label:i("dir_resources"),val:`${n}/${s.resources_dir}`},{label:i("dir_notes"),val:`${n}/${s.resources_dir}/${s.literature_dir}`},{label:i("dir_base"),val:`${n}/${s.base_dir}`},{label:i("dir_system"),val:`${n}/${s.system_dir}`},{label:"API Key",val:s.paddleocr_api_key?i("api_key_set"):i("api_key_missing")},{label:i("field_zotero_data"),val:s.zotero_data_dir||i("not_set")}];for(let p of a){let h=t.createEl("div",{cls:"paperforge-summary-row"});h.createEl("span",{cls:"paperforge-summary-label",text:p.label}),h.createEl("span",{cls:"paperforge-summary-value",text:p.val})}let r=t.createEl("div",{cls:"paperforge-summary-row"});r.createEl("span",{cls:"paperforge-summary-label",text:"PaperForge"});let l=r.createEl("span",{cls:"paperforge-summary-value",text:"\u2014"});{let p=n,{path:h,extraArgs:d=[]}=O(p,this.plugin.settings,void 0,void 0);(0,Pe.execFile)(h,[...d,"-c","import paperforge; print(paperforge.__version__)"],{cwd:p,timeout:1e4},(y,b)=>{!y&&b&&(l.textContent="v"+b.trim())})}for(let p of a){let h=t.createEl("div",{cls:"paperforge-summary-row"});h.createEl("span",{cls:"paperforge-summary-label",text:p.label}),h.createEl("span",{cls:"paperforge-summary-value",text:p.val})}e.createEl("h3",{text:i("complete_next")});let o=e.createEl("div",{cls:"paperforge-nextsteps"}),c=[[i("complete_step4"),i("complete_step4_desc")],["",`${i("complete_export_path")} ${n}/${s.system_dir}/PaperForge/exports/`],[i("complete_step1"),i("complete_step1_desc")],[i("complete_step2"),i("complete_step2_desc")],[i("complete_step3"),i("complete_step3_desc")]];for(let[p,h]of c){let d=o.createEl("div",{cls:"paperforge-nextstep-item"});p&&d.createEl("strong",{text:p}),d.createEl("span",{text:h})}}};var Be=class extends P.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"}),s=[{id:"setup",label:i("tab_setup")||"\u5B89\u88C5"},{id:"features",label:i("tab_features")||"\u529F\u80FD"},{id:"release-notes",label:"\u66F4\u65B0\u4E0E\u624B\u518C"}],n={};s.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()})}),s.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._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&&(I.existsSync($.join(t,"paperforge.json"))||(this.plugin.settings.setup_complete=!1,this._debouncedSave())),e.createEl("h2",{text:i("header_title")||"PaperForge"}),e.createEl("p",{text:i("desc"),cls:"paperforge-settings-desc"});let n=e.createEl("div",{cls:"paperforge-setup-bar"}).createEl("span",{cls:"paperforge-setup-label"});this.plugin.settings.setup_complete?(n.setText(i("setup_done")),n.addClass("paperforge-setup-done")):(n.setText(i("setup_pending")),n.addClass("paperforge-setup-pending"));let a=this.app.vault.adapter.basePath,r=O(a,this.plugin.settings,void 0,void 0),l=r.path,o=this.plugin.settings._python_path_stale?"stale":r.source,c=new P.Setting(e).setName(i("field_python_interp")).setDesc(this._getPythonDesc(l,o));this._pythonInterpDescEl=c.descEl;let p=new P.Setting(e).setName(i("field_python_custom")).setDesc("");this._customPathDescEl=p.descEl,p.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=I.existsSync(_.trim());this.plugin.settings._python_path_stale=!S}else this.plugin.settings._python_path_stale=!1;let m=O(this.app.vault.adapter.basePath,this.plugin.settings,void 0,void 0),k=this.plugin.settings._python_path_stale?"stale":m.source;this._pythonInterpDescEl&&(this._pythonInterpDescEl.textContent=this._getPythonDesc(m.path,k))})}),p.addButton(E=>{E.setButtonText(i("btn_validate")).onClick(()=>this._validatePythonOverride())}),e.createEl("h3",{text:i("runtime_health")}),e.createEl("p",{text:i("runtime_health_desc"),cls:"paperforge-settings-desc"});let h=new P.Setting(e).setName("PaperForge").setDesc(i("runtime_health_checking")),d=h.descEl.createEl("span",{cls:"paperforge-runtime-badge"}),y=null;h.addButton(E=>{y=E,E.setButtonText(i("runtime_health_sync")).setDisabled(!0).onClick(()=>this._syncRuntime(E))});{let E=this.app.vault.adapter.basePath,{path:_,extraArgs:m=[]}=O(E,this.plugin.settings,void 0,void 0),k=this.plugin.manifest.version||"?";(0,V.execFile)(_,[...m,"-c","import paperforge; print(paperforge.__version__)"],{cwd:E,timeout:1e4},(S,F)=>{let R=this.plugin.settings.setup_complete,B=!S&&F?F.trim():null,q=B?`${i("runtime_health_plugin_ver").replace("{0}",k)} \u2192 ${i("runtime_health_package_ver").replace("{0}",B)}`:R?`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.`;h.setDesc(q),B===k?(d.setText(i("runtime_health_match")),d.className="paperforge-runtime-badge match",y&&y.setDisabled(!0)):B?(d.setText(i("runtime_health_mismatch")),d.className="paperforge-runtime-badge mismatch",y&&y.setDisabled(!1)):(d.setText(R?"Not installed":"Setup needed"),d.className="paperforge-runtime-badge missing",y&&y.setDisabled(!1))})}e.createEl("h3",{text:i("section_prep")}),e.createEl("p",{text:i("section_prep_desc"),cls:"paperforge-settings-desc"});let b=e.createEl("div",{cls:"paperforge-guide"}),v=[["prep_python","prep_python_desc"],["prep_zotero","prep_zotero_desc"],["prep_bbt","prep_bbt_desc"],["prep_key","prep_key_desc"]];for(let[E,_]of v){let m=b.createEl("div",{cls:"paperforge-guide-item"});m.createEl("strong",{text:i(E)}),m.createEl("span",{text:" \u2014 "+i(_)})}this._checkEl=e.createEl("div",{cls:"paperforge-message"});let f=!this.plugin.settings.setup_complete;new P.Setting(e).setName(i(f?"btn_install":"btn_reconfig")).setDesc(i(f?"btn_install_desc":"btn_reconfig_desc")).addButton(E=>{E.setButtonText(i(f?"btn_install":"btn_reconfig")).setCta().onClick(()=>{f?this._preCheck(()=>{new we(this.app,this.plugin).open()}):new we(this.app,this.plugin).open()})}),e.createEl("h3",{text:i("section_guide")});let x=e.createEl("div",{cls:"paperforge-guide"}),C=[["guide_open","guide_open_desc"],["guide_sync","guide_sync_desc"],["guide_ocr","guide_ocr_desc"]];for(let[E,_]of C){let m=x.createEl("div",{cls:"paperforge-guide-item"});m.createEl("strong",{text:i(E)}),m.createEl("span",{text:" \u2014 "+i(_)})}if(this.plugin.settings.setup_complete){e.createEl("h3",{text:i("section_config")});let E=e.createEl("div",{cls:"paperforge-summary"}),_=this.plugin.settings,m=this._pfConfig,k=[{label:i("dir_vault"),val:t},{label:i("dir_resources"),val:`${t}/${m==null?void 0:m.resources_dir}`},{label:" "+i("dir_notes"),val:`${t}/${m==null?void 0:m.resources_dir}/${m==null?void 0:m.literature_dir}`},{label:i("dir_base"),val:`${t}/${m==null?void 0:m.base_dir}`},{label:i("dir_system"),val:`${t}/${m==null?void 0:m.system_dir}`},{label:"API Key",val:_.paddleocr_api_key?i("api_key_set"):i("api_key_missing")},{label:i("field_zotero_data"),val:_.zotero_data_dir||i("not_set")}];for(let S of k){let F=E.createEl("div",{cls:"paperforge-summary-row"});F.createEl("span",{cls:"paperforge-summary-label",text:S.label}),F.createEl("span",{cls:"paperforge-summary-value",text:S.val})}}}_execMemoryStatus(e,t,s){(0,V.exec)(`"${e}" -m paperforge --vault "${t}" memory status --json`,{encoding:"utf-8",timeout:15e3},(n,a)=>{if(n){s("Status unavailable");return}try{let r=JSON.parse(a);if(r.ok){let l=r.data,o=l.fresh?"fresh":"stale";s(`Papers: ${l.paper_count_db} | ${o}${l.needs_rebuild?" - needs rebuild":""}`)}else s("DB not found. Run paperforge memory build.")}catch(r){s("Could not parse status.")}})}_execEmbedStatus(e,t,s){(0,V.exec)(`"${e}" -m paperforge --vault "${t}" embed status --json`,{encoding:"utf-8",timeout:15e3},(n,a)=>{if(n){s("Status unavailable");return}try{let r=JSON.parse(a);r.ok?s(`Chunks: ${r.data.chunk_count} | ${r.data.model} | ${r.data.mode}`):s("Could not parse status.")}catch(r){s("Could not parse status.")}})}_callPython(e,t){let s=this.app.vault.adapter.basePath,n=ne(s,this.plugin.settings),a=[...n.extraArgs,"-m","paperforge","--vault",s,...e];if(t&&t.stream){let r=(0,V.spawn)(n.path,a,{cwd:s,env:t.env||process.env,windowsHide:!0});return t.onData&&r.stdout.on("data",t.onData),t.onStderr&&r.stderr.on("data",t.onStderr),t.onError&&r.on("error",t.onError),r.on("close",t.onClose),r}return(0,V.execFile)(n.path,a,{cwd:s,timeout:t&&t.timeout||6e4},(r,l,o)=>{t&&t.onClose&&t.onClose(r?1:0,l,o)}),null}_renderMemoryStatusText(e,t,s){if(e.innerHTML="",e.createEl("span",{text:t,cls:"paperforge-memory-text"}).style.cssText="flex:1;",s==="syncing"){let r=e.createEl("span",{text:"Syncing...",cls:"paperforge-sync-status"});r.style.cssText="opacity:0.7; margin-right:8px;"}else if(s){let r=e.createEl("span",{text:s,cls:"paperforge-sync-status"});r.style.cssText="opacity:0.7; margin-right:8px;"}let n=e.createEl("button",{cls:"paperforge-rebuild-btn",text:i("feat_memory_rebuild_btn")});n.style.cssText="margin-left:auto; border:1px solid var(--background-modifier-border); background:var(--background-secondary); cursor:pointer; font-size:11px; padding:2px 6px; border-radius:3px; margin-right:4px;",n.title="Rebuild memory database",n.onclick=()=>{let r=this.app.vault.adapter.basePath,l=ne(r,this.plugin.settings);if(!l.path){new P.Notice(i("feat_no_python"));return}console.log("[PaperForge] Rebuilding memory:",l.path),n.setText(i("feat_memory_rebuilding")),n.setAttr("disabled",""),this._callPython(["memory","build"],{timeout:6e4,onClose:(o,c,p)=>{console.log("[PaperForge] memory build exit:",o?"FAIL:"+o:"OK",(c||"").slice(0,200),(p||"").slice(0,200)),n.setText(i("feat_memory_rebuild_btn")),n.removeAttribute("disabled"),o===0?new P.Notice(i("feat_memory_rebuild_done")):new P.Notice(i("feat_memory_rebuild_failed")+(p?" "+p.slice(0,80):"")),this._memoryStatusText=De(r),this._refreshSnapshots(r)}})};let a=e.createEl("button",{cls:"paperforge-refresh-btn",text:"\u21BB"});a.style.cssText="border:none; background:none; cursor:pointer; font-size:16px; padding:0 4px;",a.title="Sync now",a.onclick=()=>{this._memoryStatusText=null,this._runManualSync()}}_getBuildCommand(e){let t=this.app.vault.adapter.basePath,s=O(t,e,void 0,void 0);return s.path?`"${s.path}" -m paperforge --vault "${t}" sync`:null}_runManualSync(){let e=this.app.vault.adapter.basePath;if(!ne(e,this.plugin.settings).path)return;let s=document.querySelector(".paperforge-memory-status");s&&this._renderMemoryStatusText(s,"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),Re(this.app,this.plugin,e)}})}_refreshSnapshots(e){let t=ne(e,this.plugin.settings),s=[...t.extraArgs,"-m","paperforge","--vault",e,"runtime-health","--json"];this._refreshPending=!0,(0,V.execFile)(t.path,s,{cwd:e,timeout:3e4,windowsHide:!0},(n,a,r)=>{this._refreshPending=!1,this._memoryStatusText=De(e),this._embedStatusText=ge(e),this.display()})}_renderFeaturesTab(e){e.createEl("h3",{text:"Skills"});let t=e.createEl("div",{cls:"paperforge-desc-box"});t.style.cssText="padding:8px 12px; margin:0 0 12px; background:var(--background-secondary); border-radius:4px; font-size:12px; color:var(--text-muted); line-height:1.5;",t.setText(i("feat_skills_desc")),t.createEl("br"),t.createEl("span",{text:i("feat_skills_system"),cls:""}).style.opacity="0.7";let s={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,r=this.plugin.settings.selected_skill_platform||"opencode";new P.Setting(e).setName(i("feat_agent_platform")).setDesc(i("feat_agent_platform_desc")).addDropdown(_=>{Object.entries(s).forEach(([m,k])=>_.addOption(m,k)),_.setValue(r).onChange(m=>{this.plugin.settings.selected_skill_platform=m,this.plugin.saveSettings(),this.display()})}).addExtraButton(_=>{_.setIcon("folder").setTooltip("Open skills folder").onClick(()=>{let m=n[r]||".opencode/skills",k=$.join(a,m);I.existsSync(k)?(0,V.exec)(`start "" "${k}"`):new P.Notice(`Skills folder not found: ${m}`)})});let l=$.join(a,n[r]),o=[],c=[];I.existsSync(l)&&I.readdirSync(l,{withFileTypes:!0}).forEach(_=>{if(!_.isDirectory())return;let m=$.join(l,_.name,"SKILL.md");if(!I.existsSync(m))return;let k=I.readFileSync(m,"utf-8"),S=k.match(/^name:\s*(.+)$/m),F=k.split(`
|
|
`),R=F.findIndex(K=>/^description:/.test(K)),B="";if(R>=0){let K=F[R].match(/^description:\s*(.+)$/);if(K&&K[1]&&K[1]!==">"&&K[1]!=="|-"&&K[1]!=="|")B=K[1].trim();else{for(let J=R+1;J<F.length&&(/^\s{2,}/.test(F[J])||F[J].trim()==="");J++)B+=F[J].trim()+" ";B=B.trim()}}let q=k.match(/^source:\s*(.+)$/m),U=k.match(/^disable-model-invocation:\s*(.+)$/m),A=k.match(/^version:\s*(.+)$/m),W={name:S?S[1].trim():_.name,desc:B,source:q?q[1].trim():"user",disabled:U&&U[1].trim()==="true",version:A?A[1].trim():"",path:m,content:k,dirName:_.name};W.source==="paperforge"?o.push(W):c.push(W)});let p=e.createEl("div");p.style.cssText="background:var(--background-secondary); border-radius:8px; padding:12px 12px 10px; margin:8px 0 16px;";let h=(_,m,k)=>{if(m.length===0)return;let S=p.createEl("div",{cls:"paperforge-skills-group"}),F=S.createEl("div",{cls:"paperforge-skills-collapse-header"}),R=S.createEl("div",{cls:"paperforge-skills-collapse-content"}),B=F.createEl("span",{text:"\u25BC",cls:"paperforge-skills-arrow"});B.style.cssText="display:inline-block; font-size:10px; margin-right:6px; transition:transform 0.2s; transform:rotate(0deg);",F.createEl("h4",{text:`${_} (${m.length})`,cls:"paperforge-skills-subheader"}),m.forEach(A=>{let W=A.name+(A.version?" v"+A.version:""),K=k?" [system]":" [user]",J=A.desc||"",ie=new P.Setting(R).setName(W+K).setDesc(J);ie.settingEl.style.opacity=A.disabled?"0.4":"1",ie.addToggle(he=>{he.setValue(!A.disabled).onChange(me=>{let oe=!me,be=A.content.match(/^disable-model-invocation:\s*(.+)$/m)?A.content.replace(/^disable-model-invocation:\s*.+$/m,`disable-model-invocation: ${oe}`):A.content.replace(/^(---\r?\n)/,`$1disable-model-invocation: ${oe}
|
|
`);I.writeFileSync(A.path,be,"utf-8"),A.disabled=oe,A.content=be,ie.settingEl.style.opacity=A.disabled?"0.4":"1"})})});let q=k?"system":"user";(this._skillsCollapsed[q]||!1)&&(R.style.display="none",B.style.transform="rotate(-90deg)"),F.addEventListener("click",()=>{R.style.display!=="none"?(R.style.display="none",B.style.transform="rotate(-90deg)"):(R.style.display="",B.style.transform="rotate(0deg)"),this._skillsCollapsed[q]=R.style.display==="none"})};h("System Skills",o,!0),h("User Skills",c,!1),o.length===0&&c.length===0&&p.createEl("p",{text:`No skills found in ${n[r]}. Run setup to deploy skills.`,cls:"setting-item-description"}),this._advCollapsed===void 0&&(this._advCollapsed=!0);let d=e.createEl("div",{cls:"paperforge-collapsible-header"});d.style.cssText="cursor:pointer; display:flex; align-items:center; gap:8px; padding:8px 0; user-select:none;";let y=d.createEl("span",{text:"\u25B6",cls:"paperforge-collapsible-arrow"});y.style.cssText="display:inline-block; transition:transform 0.2s; font-size:10px; transform:"+(this._advCollapsed?"rotate(0deg)":"rotate(90deg)")+";";let b=d.createEl("span",{text:"Advanced"});b.style.cssText="font-size:16px; font-weight:700; line-height:1.4;";let v=d.createEl("span",{text:"Memory + Vector DB + Embedding"});v.style.cssText="font-size:12px; color:var(--text-muted); margin-left:10px;";let f=e.createEl("div",{cls:"paperforge-collapsible-content"});f.style.display=this._advCollapsed?"none":"",d.addEventListener("click",()=>{this._advCollapsed=!this._advCollapsed,f.style.display=this._advCollapsed?"none":"",y.style.transform=this._advCollapsed?"rotate(0deg)":"rotate(90deg)"}),f.createEl("h4",{text:"Memory Layer"});let x=f.createEl("div",{cls:"paperforge-desc-box"});x.style.cssText="padding:8px 12px; margin:0 0 12px; background:var(--background-secondary); border-radius:4px; font-size:12px; color:var(--text-muted); line-height:1.5;",x.setText(i("feat_memory_desc"));let C=f.createEl("div",{cls:"paperforge-memory-status"});C.style.cssText="display:flex; align-items:center; padding:8px 12px; margin:8px 0; background:var(--background-secondary); border-radius:4px;";let E=this.app.vault.adapter.basePath;this.plugin._lastSyncTime&&!this._lastSyncTime&&(this._lastSyncTime=this.plugin._lastSyncTime),this._memoryStatusText===null&&(this._memoryStatusText=De(E)),this._renderMemoryStatusText(C,this._memoryStatusText,this._lastSyncTime),this._renderVectorSection(f)}_renderVectorSection(e){var o;e.createEl("h4",{text:"Vector Database"}),this.plugin.settings.features||(this.plugin.settings.features={memory_layer:!0,vector_db:!1});let t=e.createEl("div",{cls:"paperforge-desc-box"});if(t.style.cssText="padding:8px 12px; margin:0 0 8px; background:var(--background-secondary); border-radius:4px; font-size:12px; color:var(--text-muted); line-height:1.5;",t.setText(i("feat_vector_desc")),new P.Setting(e).setName(i("feat_vector_enable")).setDesc(i("feat_vector_enable_desc")).addToggle(c=>{c.setValue(!!this.plugin.settings.features.vector_db).onChange(p=>{this.plugin.settings.features.vector_db=p,this.plugin.saveSettings(),this._vectorDepsOk=null,this._embedStatusText=null,this.display()})}),!this.plugin.settings.features.vector_db)return;let s=this.app.vault.adapter.basePath,n=e.createEl("div",{cls:"paperforge-skills-collapse-header"});n.style.cssText="display:flex; align-items:center; cursor:pointer; padding:6px 0 2px; margin:0;";let a=n.createEl("span",{text:"\u25BC"});a.style.cssText="display:inline-block; font-size:10px; margin-right:6px; transition:transform 0.2s;",n.createEl("span",{text:i("feat_vector_config_label"),cls:""}).style.cssText="font-size:12px; color:var(--text-muted);";let r=e.createEl("div",{cls:"paperforge-vector-config"}),l=c=>{r.style.display=c?"none":"",a.style.transform=c?"rotate(-90deg)":"rotate(0deg)"};if(l(Ke(this._featurePanelsCollapsed,"vectorConfig",!1)),n.addEventListener("click",()=>{let c=pt(this._featurePanelsCollapsed,"vectorConfig",!1);l(c)}),this._vectorDepsOk===!0){this._renderVectorReady(r,s);return}if(this._vectorDepsOk===!1){this._renderVectorNoDeps(r);return}if(this._vectorDepsOk===null){let c=ke(s);this._vectorDepsOk=c&&(o=c.deps_installed)!=null?o:!1,this._vectorDepsOk&&(this._embedStatusText=ge(s)),this.display()}}_renderApiConfig(e){new P.Setting(e).setName(i("feat_openai_key")).setDesc(i("feat_openai_key_desc")).addText(t=>{t.setPlaceholder("sk-...").setValue(this.plugin.settings.vector_db_api_key||"").onChange(s=>{this.plugin.settings.vector_db_api_key=s,this.plugin.saveSettings()})}),new P.Setting(e).setName(i("feat_api_base_url")).setDesc(i("feat_api_base_url_desc")).addText(t=>{t.setPlaceholder("https://api.openai.com/v1").setValue(this.plugin.settings.vector_db_api_base||"").onChange(s=>{this.plugin.settings.vector_db_api_base=s,this.plugin.saveSettings()})}),new P.Setting(e).setName(i("feat_api_model")).setDesc(i("feat_api_model_desc")).addText(t=>{t.setPlaceholder("text-embedding-3-small").setValue(this.plugin.settings.vector_db_api_model||"text-embedding-3-small").onChange(s=>{this.plugin.settings.vector_db_api_model=s,this.plugin.saveSettings()})})}_renderVectorNoDeps(e){let t=e.createEl("div");t.style.cssText="padding:8px 12px; margin:8px 0; background:var(--background-secondary); border-radius:4px;",t.setText(i("feat_deps_missing")),new P.Setting(e).setName(i("feat_install_deps")).setDesc(i("feat_install_deps_desc")).addButton(s=>{s.setButtonText(i("feat_install_btn")).setCta().onClick(async()=>{let n=this.app.vault.adapter.basePath,a=ne(n,this.plugin.settings);if(!a.path){new P.Notice(i("feat_no_python"));return}s.setButtonText(i("feat_installing")),s.setDisabled(!0);let r="chromadb openai",l=new P.Notice(i("feat_installing_pkgs").replace("{pkgs}",r),0);try{let o=Object.assign({},process.env,{PYTHONIOENCODING:"utf-8",PYTHONUTF8:"1"}),c=r.split(" ");await new Promise((p,h)=>{(0,V.execFile)(a.path,[...a.extraArgs,"-m","pip","install",...c],{cwd:n,timeout:3e5,env:o,windowsHide:!0},d=>{d?h(d):p()})}),l.hide(),new P.Notice(i("feat_install_done")),this._vectorDepsOk=!0,this._embedStatusText=ge(n),this.display()}catch(o){l.hide(),new P.Notice(i("feat_install_failed")+(o.stderr||o.message||o)),s.setButtonText(i("feat_retry_btn")),s.setDisabled(!1)}})})}_renderVectorReady(e,t){let s=e.createEl("div");s.style.cssText="padding:8px 12px; margin:8px 0; background:var(--background-secondary); border-radius:4px;",s.setText(ge(t)),this._renderApiConfig(e);let n=e.createEl("div");n.style.cssText="padding:4px 0;";let a=n.createEl("div");a.style.cssText="display:flex; align-items:center; justify-content:space-between; margin-bottom:8px;",a.createEl("span",{text:i("feat_rebuild_vectors"),cls:"setting-item-name"});let r=n.createEl("div");r.style.cssText="display:flex; align-items:center; gap:8px;";let l=n.createEl("div",{cls:"paperforge-embed-status-text"});(()=>{var b;r.empty(),l.empty();let c=(ke(t)||{}).build_state||{};this.plugin._embedProgress=this.plugin._embedProgress||{current:0,total:0,key:""},!this.plugin._embedProcess&&c.status==="running"&&(this.plugin._embedProgress={current:c.current||0,total:c.total||1,key:c.paper_id||""});let{current:p,total:h,key:d}=this.plugin._embedProgress;if(!!this.plugin._embedProcess||c.status==="running"){let v=r.createEl("div",{cls:"paperforge-progress-track"});v.style.cssText="flex:1;";let f=h>0?(p/h*100).toFixed(1):"0",x=v.createEl("div",{cls:"paperforge-progress-seg done"});if(x.style.cssText=`width:${f}%; min-width:${p>0?"2px":"0"};`,p<h){let E=v.createEl("div",{cls:"paperforge-progress-seg pending"});E.style.cssText=`width:${(100-parseFloat(f)).toFixed(1)}%;`}l.createEl("span",{cls:"paperforge-embed-progress-text",text:`${p}/${h} papers`}),d&&l.createEl("span",{cls:"paperforge-embed-progress-key",text:` (${d})`});let C=r.createEl("button");C.setText("Stop"),C.className="mod-warning",C.addEventListener("click",()=>{this._callPython(["embed","stop","--json"],{timeout:8e3}),this.plugin._embedProcess&&(this.plugin._embedProcess.kill(),this.plugin._embedProcess=null),this.display()})}else{let v=ke(t),f=!!(v&&((b=v.chunk_count)!=null?b:0)>0),x=v&&v.corrupted,C=_=>{if(!ne(t,this.plugin.settings).path){new P.Notice(i("feat_no_python"));return}let k=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",_],{stream:!0,env:k,onData:S=>{let F=S.toString("utf-8").split(`
|
|
`);for(let R of F)if(R.startsWith("EMBED_START:"))this.plugin._embedProgress.total=parseInt(R.split(":")[1])||0;else if(R.startsWith("EMBED_PROGRESS:")){let B=R.split(":");this.plugin._embedProgress.current=parseInt(B[1])||0,this.plugin._embedProgress.key=B[3]||""}else R.startsWith("EMBED_DONE")&&(this.plugin._embedProcess=null,this.plugin._embedProgress.current=this.plugin._embedProgress.total);this.display()},onStderr:S=>{this.plugin._embedStderr||(this.plugin._embedStderr=""),this.plugin._embedStderr+=S.toString("utf-8")},onError:S=>{this.plugin._embedProcess=null,new P.Notice(i("feat_build_failed")+": "+(S.message||S)),this.display()},onClose:S=>{if(this.plugin._embedProcess=null,S===0)this.plugin._embedProgress.current=this.plugin._embedProgress.total,this.plugin.saveSettings(),this._embedStatusText=ge(t),new P.Notice(i("feat_build_complete"));else{this._embedStatusText=null;let F=(this.plugin._embedStderr||"").slice(0,200);new P.Notice(i("feat_build_failed")+(F?": "+F:""),8e3)}this.plugin._embedStderr="",this.display(),this._refreshSnapshots(t)}}),this.display()};if(x){let _=n.createEl("div");_.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;",_.createEl("span",{text:i("feat_vector_corrupted")});let m=_.createEl("button",{text:i("feat_vector_rebuild_force_btn")});m.className="mod-cta",m.addEventListener("click",()=>C("--force"))}f&&!x&&r.createEl("span",{text:v.chunk_count+" chunks embedded",cls:"setting-item-description"});let E=r.createEl("button");if(E.setText(f?i("feat_rebuild_btn"):i("feat_build_btn")),E.addClass("mod-cta"),E.addEventListener("click",()=>C("--resume")),!x&&f){let _=r.createEl("button");_.setText(i("feat_vector_rebuild_force_btn")),_.style.marginLeft="6px",_.addEventListener("click",()=>C("--force"))}}})()}_getCurrentModelKey(){return this.plugin.settings.vector_db_api_model||"text-embedding-3-small"}_parseEmbedStatus(e){let t={};return e&&(e.split(`
|
|
`).forEach(s=>{let n=s.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 s=this._pythonInterpDescEl;s&&(t==="stale"?s.textContent=`[!!] ${e} (stale \u2014 path no longer exists, update or clear the override below)`:t==="manual"?s.textContent=`${e} (manual)`:s.textContent=`${e} (auto-detected)`)}_validatePythonOverride(){let e=this.plugin.settings.python_path?this.plugin.settings.python_path.trim():"",t=this._customPathDescEl;if(!e){let s="\u8BF7\u8F93\u5165\u8DEF\u5F84 / Enter a path first";t&&(t.innerHTML=`<span style="color:var(--text-error)">\u2717 ${s}</span>`),new P.Notice(s);return}if(!I.existsSync(e)){let s="\u8DEF\u5F84\u4E0D\u5B58\u5728 / Path does not exist";t&&(t.innerHTML=`<span style="color:var(--text-error)">\u2717 ${s}</span>`),new P.Notice(s,4e3);return}try{I.accessSync(e,I.constants.X_OK)}catch(s){let n="\u4E0D\u53EF\u6267\u884C / Not executable";t&&(t.innerHTML=`<span style="color:var(--text-error)">\u2717 ${n}</span>`),new P.Notice(n,4e3);return}(0,V.execFile)(e,["--version"],{timeout:8e3},(s,n)=>{if(s||!n){let o="\u65E0\u6CD5\u8FD0\u884C / Cannot run";t&&(t.innerHTML=`<span style="color:var(--text-error)">\u2717 ${o}</span>`),new P.Notice(o,4e3);return}let a=n.match(/Python (\d+)\.(\d+)/);if(!a){let o="\u65E0\u6CD5\u89E3\u6790\u7248\u672C / Cannot parse version";t&&(t.innerHTML=`<span style="color:var(--text-error)">\u2717 ${o}</span>`),new P.Notice(o,4e3);return}let r=parseInt(a[1],10),l=parseInt(a[2],10);if(r<3||r===3&&l<10){let o="Python \u7248\u672C\u8FC7\u4F4E\uFF0C\u9700\u8981 3.10+ / Python version too low, need 3.10+";t&&(t.innerHTML=`<span style="color:var(--text-error)">\u2717 ${o}</span>`),new P.Notice(o,4e3);return}(0,V.execFile)(e,["-m","pip","--version"],{timeout:8e3},o=>{if(o){let c=`\u2713 Python ${r}.${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 P.Notice(c,4e3)}else{let c=`\u2713 Python ${r}.${l} \u6709\u6548 / Valid`;t&&(t.innerHTML=`<span style="color:var(--text-accent)">${c}</span>`),new P.Notice(c,4e3)}})})}_syncRuntime(e){let t=this.app.vault.adapter.basePath,{path:s,extraArgs:n=[]}=O(t,this.plugin.settings,void 0,void 0),a=this.plugin.manifest.version,r=at(s,a,n);e.setDisabled(!0),e.setButtonText(i("runtime_health_syncing"));let l=(c,p)=>(console.log(`[PaperForge] Sync Runtime: trying ${p}`),it(r.cmd,c,t,r.timeout,void 0,pe())),o=()=>{let c="opencode";try{let y=I.readFileSync($.join(t,"paperforge.json"),"utf-8"),b=JSON.parse(y);b.agent_key&&(c=b.agent_key)}catch(y){}let p=[...n,"-c",'from paperforge.services.skill_deploy import deploy_skills; from pathlib import Path; r=deploy_skills(vault=Path(r"'+t.replace(/\\/g,"\\\\")+'"), agent_key="'+c+'", overwrite=True); print("skills deployed" if r["skill_deployed"] else "skills skipped", flush=True)'],h=(0,V.spawn)(s,p,{cwd:t,timeout:3e4,windowsHide:!0}),d="";h.stdout.on("data",y=>{d+=y.toString("utf-8")}),h.on("close",y=>{console.log(`[PaperForge] Skill deploy: ${d.trim()} (exit ${y})`)})};l(r.pypiArgs,"PyPI").then(c=>{if(c.exitCode===0){console.log("[PaperForge] Sync Runtime: installed via PyPI"),o(),new P.Notice(i("runtime_health_sync_done").replace("{0}",a),5e3),this.display();return}console.warn("[PaperForge] Sync Runtime: PyPI failed, falling back to git..."),l(r.gitArgs,"git").then(p=>{p.exitCode===0?(console.log("[PaperForge] Sync Runtime: installed via git"),o(),new P.Notice(i("runtime_health_sync_done").replace("{0}",a),5e3),this.display()):(e.setDisabled(!1),e.setButtonText(i("runtime_health_sync")),console.error("[PaperForge] git fallback stderr:",p.stderr),new P.Notice(i("runtime_health_sync_fail").replace("{0}","pip exit code "+p.exitCode),8e3))})})}_debouncedSave(){clearTimeout(this._saveTimeout),this._saveTimeout=setTimeout(()=>this.plugin.saveSettings(),500)}_preCheck(e){var a;let t=this.app.vault.adapter.basePath,{path:s,extraArgs:n=[]}=O(t,(a=this.plugin)==null?void 0:a.settings,void 0,void 0);(0,V.execFile)(s,[...n,"--version"],{timeout:8e3},(r,l)=>{let o=[];o.push({label:"Python",ok:!r,detail:r?i("check_python_fail"):l.trim()});let c=!1,p=process.env.HOME||process.env.USERPROFILE||gt.homedir()||"";if(process.platform==="darwin")c=["/Applications/Zotero.app",$.join(p,"Applications","Zotero.app")].some(x=>{try{return I.existsSync(x)}catch(C){return!1}});else if(process.platform==="win32"){let f=process.env.ProgramFiles||"",x=process.env.LOCALAPPDATA||"";c=[$.join(f,"Zotero"),$.join(f,"(x86)","Zotero"),$.join(x,"Programs","Zotero"),$.join(x,"Zotero"),$.join(p,"AppData","Local","Programs","Zotero")].filter(Boolean).some(E=>{try{return I.existsSync(E)}catch(_){return!1}})}else c=[$.join(p,".local","share","zotero","zotero"),"/usr/bin/zotero","/usr/local/bin/zotero"].some(x=>{try{return I.existsSync(x)}catch(C){return!1}});let h=this.plugin.settings.zotero_data_dir;if(!c&&h)try{c=I.existsSync(h)}catch(f){}o.push({label:"Zotero",ok:c,detail:c?i("check_zotero_ok"):i("check_zotero_fail")});let d=!1,y=process.env.APPDATA||"";process.platform==="win32"&&y&&(d=Te($.join(y,"Zotero","Zotero","Profiles"))),!d&&process.platform==="darwin"&&p&&(d=Te($.join(p,"Library","Application Support","Zotero","Profiles"))),!d&&process.platform!=="win32"&&process.platform!=="darwin"&&p&&(d=Te($.join(p,".zotero","zotero","Profiles"))),!d&&h&&String(h).trim()&&(d=je(h.trim())),!d&&p&&(d=je($.join(p,"Zotero"))),o.push({label:"Better BibTeX",ok:d,detail:d?i("check_bbt_ok"):i("check_bbt_fail")});let b={true:"\u2713",false:"\u2717"};if(this._checkEl){this._checkEl.setText(o.map(x=>`${b[String(x.ok)]} ${x.label}: ${x.detail}`).join(`
|
|
`));let f=o.some(x=>!x.ok);this._checkEl.className=`paperforge-message msg-${f?"error":"ok"}`}let v=o.filter(f=>!f.ok);v.length>0&&new P.Notice(`[!!] \u672A\u901A\u8FC7: ${v.map(f=>f.label).join(", ")}`,6e3),e()})}_renderReleaseNotesTab(e){e.createEl("h2",{text:"\u66F4\u65B0\u4E0E\u624B\u518C"}),e.createEl("h3",{text:"\u7248\u672C\u66F4\u65B0\u8BB0\u5F55"});let t=ft.default.versions||[];for(let a of t){let r=e.createEl("div",{cls:"paperforge-release-card"}),l=r.createEl("div",{cls:"paperforge-release-header"});if(l.createEl("strong",{text:`v${a.version} \u2014 ${a.title}`}),l.createEl("span",{cls:"paperforge-release-date",text:` (${a.date})`}),a.breaking_or_migration&&a.breaking_or_migration.length>0){let o=r.createEl("div",{cls:"paperforge-release-section"});o.createEl("div",{cls:"paperforge-release-label",text:"\u884C\u4E3A\u53D8\u66F4 / \u8FC1\u79FB\u6CE8\u610F"});for(let c of a.breaking_or_migration)o.createEl("div",{cls:"paperforge-release-item",text:`\u2022 ${c}`})}if(a.new_features&&a.new_features.length>0){let o=r.createEl("div",{cls:"paperforge-release-section"});o.createEl("div",{cls:"paperforge-release-label",text:"\u65B0\u529F\u80FD"});for(let c of a.new_features)o.createEl("div",{cls:"paperforge-release-item",text:`\u2022 ${c}`})}if(a.fixes&&a.fixes.length>0){let o=r.createEl("div",{cls:"paperforge-release-section"});o.createEl("div",{cls:"paperforge-release-label",text:"\u4FEE\u590D"});for(let c of a.fixes)o.createEl("div",{cls:"paperforge-release-item",text:`\u2022 ${c}`})}if(a.recommended_actions&&a.recommended_actions.length>0){let o=r.createEl("div",{cls:"paperforge-release-section paperforge-release-recommended"});o.createEl("div",{cls:"paperforge-release-label",text:"\u5EFA\u8BAE\u64CD\u4F5C"});for(let c of a.recommended_actions)o.createEl("div",{cls:"paperforge-release-item paperforge-release-item-bold",text:`\u2022 ${c}`})}}e.createEl("h3",{text:"\u4F7F\u7528\u624B\u518C"}),e.createEl("div",{cls:"paperforge-manual-links"}).createEl("a",{text:"\u2192 \u67E5\u770B\u5B8C\u6574\u4F7F\u7528\u624B\u518C\uFF08GitHub\uFF09",href:"https://github.com/LLLin000/PaperForge/blob/master/docs/user-manual.md"}).setAttr("target","_blank")}};var D=require("obsidian"),ae=z(require("fs")),Ce=z(require("path")),ue=require("child_process");var Se=z(require("path"));function _t(g){if(!g)return null;let u=Se.dirname(g);for(;;){let e=Se.basename(u);if(!e||e===".")break;let t=e.match(/^([A-Z0-9]{8})(?:\s*-\s*.*)?$/i);if(t)return t[1];let s=Se.dirname(u);if(s===u)break;u=s}return null}var fe=class extends D.ItemView{constructor(e){super(e);this._currentMode=null;this._currentDomain=null;this._currentPaperKey=null;this._currentPaperEntry=null;this._currentFilePath=null;this._cachedItems=null;this._modeSubscribers=[];this._leafChangeTimer=null;this._ocrPrivacyShown=!1;this._cachedStats=null;this._techDetailsExpanded=!1;this._paperforgeVersion="";this._dashboardPermissions={};this._headerTitle=null;this._versionBadge=null;this._messageEl=null;this._metricsEl=null;this._ocrSection=null;this._ocrEmpty=null;this._ocrBadge=null;this._ocrTrack=null;this._ocrCounts=null;this._driftBannerEl=null;this._currentMode=null,this._currentDomain=null,this._currentPaperKey=null,this._currentPaperEntry=null,this._currentFilePath=null,this._cachedItems=null,this._modeSubscribers=[],this._leafChangeTimer=null,this._ocrPrivacyShown=!1}getViewType(){return ce}getDisplayText(){return"PaperForge"}getIcon(){return xe}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"}),s=t.createEl("div",{cls:"paperforge-header-left"});s.createEl("div",{cls:"paperforge-header-logo",text:"P"}),this._modeContextEl=s.createEl("div",{cls:"paperforge-mode-context"}),this._headerTitle=s.createEl("h3",{cls:"paperforge-header-title",text:"PaperForge"}),this._versionBadge=s.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 r,l;let e=this.app.vault.adapter.basePath,t=this.app.plugins.plugins.paperforge,s=((r=t==null?void 0:t.manifest)==null?void 0:r.version)||"?",{path:n,extraArgs:a=[]}=O(e,(l=t==null?void 0:t.settings)!=null?l:null,void 0,void 0);nt(n,s,e,1e4,void 0).then(o=>{if(o.status==="not-installed")return;let c=o.pyVersion||"";this._paperforgeVersion=c.startsWith("v")?c:"v"+c,this._versionBadge&&this._versionBadge.setText(this._paperforgeVersion),this._driftBannerEl&&s&&this._paperforgeVersion!=="v"+s.replace(/^v/,"")?(this._driftBannerEl.style.display="block",this._driftBannerEl.setText(i("dashboard_drift_warning").replace("{0}",this._paperforgeVersion).replace("{1}","v"+s.replace(/^v/,"")))):this._driftBannerEl&&(this._driftBannerEl.style.display="none")})}_fetchStats(e){var r;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,s=this.app.plugins.plugins.paperforge,{path:n,extraArgs:a=[]}=O(t,(r=s==null?void 0:s.settings)!=null?r:null,void 0,void 0);(0,ue.execFile)(n,[...a,"-m","paperforge","dashboard","--json"],{cwd:t,timeout:3e4},(l,o)=>{if(!l)try{let c=JSON.parse(o);if(c.ok&&c.data){let p=this._normalizeDashboardData(c.data);this._cachedStats=p,this._metricsEl.empty(),this._renderStats(p),this._renderOcr(p),this._dashboardPermissions=c.data.permissions||{};return}}catch(c){}this._fallbackFetchStats(e,t,s)})}_normalizeDashboardData(e){let t=e.stats||{},s=t.ocr_health||{},n=t.pdf_health||{},a=(s.done||0)+(s.pending||0)+(s.failed||0);return{total_papers:t.papers||0,formal_notes:t.papers||0,exports:0,bases:0,ocr:{total:a,pending:s.pending||0,processing:0,done:s.done||0,failed:s.failed||0},path_errors:(n.broken||0)+(n.missing||0)}}_fallbackFetchStats(e,t,s){var r,l,o;let n=((r=s==null?void 0:s.settings)==null?void 0:r.system_dir)||"System",a=Ce.join(t,n,"PaperForge","indexes","formal-library.json");try{let c=ae.readFileSync(a,"utf-8"),p=JSON.parse(c),h=p.items||[],d={},y={pdf_health:{healthy:0,unhealthy:0},ocr_health:{healthy:0,unhealthy:0},note_health:{healthy:0,unhealthy:0},asset_health:{healthy:0,unhealthy:0}},b=0,v=0,f=0,x=0,C=0,E=0;for(let _ of h){_.note_path&&E++;let m=_.lifecycle||"pdf_ready";d[m]=(d[m]||0)+1;let k=_.health||{};for(let F of["pdf_health","ocr_health","note_health","asset_health"])(k[F]||"healthy")==="healthy"?y[F].healthy++:y[F].unhealthy++;let S=_.ocr_status||"";b++,S==="done"?v++:S==="pending"?f++:S==="processing"||S==="queued"||S==="running"?x++:C++}this._cachedStats={version:p.paperforge_version||((l=this._cachedStats)==null?void 0:l.version)||"\u2014",total_papers:h.length,formal_notes:E,exports:0,bases:0,ocr:{total:b,pending:f,processing:x,done:v,failed:C},path_errors:0,lifecycle_level_counts:d,health_aggregate:y},this._metricsEl.empty(),this._renderStats(this._cachedStats),this._renderOcr(this._cachedStats)}catch(c){!e&&!this._cachedStats&&this._metricsEl.createEl("div",{cls:"paperforge-status-loading",text:"No index \u2014 trying CLI..."});let{path:p,extraArgs:h=[]}=O(t,(o=s==null?void 0:s.settings)!=null?o:null,void 0,void 0);(0,ue.execFile)(p,[...h,"-m","paperforge","status","--json"],{cwd:t,timeout:3e4},(d,y)=>{if(d){if(this._cachedStats)return;this._metricsEl.createEl("div",{cls:"paperforge-status-error",text:`Cannot reach PaperForge CLI.
|
|
Make sure paperforge is installed and in your PATH.`});return}try{let b=JSON.parse(y);this._cachedStats=b,this._metricsEl.empty(),this._renderStats(b),this._renderOcr(b)}catch(b){this._cachedStats||this._metricsEl.createEl("div",{cls:"paperforge-status-error",text:"Invalid response from paperforge status."})}})}}_renderSkeleton(e){e.addClass("paperforge-loading")}_renderEmptyState(e,t){e.createEl("div",{cls:"paperforge-empty-state",text:t||"No data"})}_buildMetricBar(e,t,s){if(s<=0)return;let n=Math.min(100,t/s*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,s=((a=t==null?void 0:t.settings)==null?void 0:a.system_dir)||"System",n=Ce.join(e,s,"PaperForge","indexes","formal-library.json");try{let r=ae.readFileSync(n,"utf-8");return JSON.parse(r)}catch(r){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(s=>s.zotero_key===e)||null;return et(this.app,t)}_patchCachedEntry(e,t){if(!e||!this._cachedItems)return;let s=this._cachedItems.findIndex(n=>n.zotero_key===e);s!==-1&&(this._cachedItems[s]=Ie(this._cachedItems[s],t))}_filterByDomain(e){return e?this._getCachedIndex().filter(t=>t.domain===e):[]}_renderStats(e){var a;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,s=e.formal_notes||0,n=[{value:t,label:"Papers",color:"var(--color-cyan)",barMax:0},{value:s,label:"Formal Notes",color:"var(--color-blue)",barMax:t},{value:e.exports||0,label:"Exports",color:"var(--color-purple)",barMax:0}];for(let r of n){let l=this._metricsEl.createEl("div",{cls:"paperforge-metric-card"});l.style.setProperty("--metric-color",r.color),l.createEl("div",{cls:"paperforge-metric-value",text:((a=r.value)==null?void 0:a.toString())||"\u2014"}),l.createEl("div",{cls:"paperforge-metric-label",text:r.label}),r.barMax>0&&this._buildMetricBar(l,r.value,r.barMax)}}_renderOcr(e){if(!this._ocrSection)return;let t=e.ocr||{},s=t.total||0;if(s===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,r=t.processing||0,l=t.failed||0;if(this._ocrBadge&&(this._ocrBadge.removeClass("active","idle"),r>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(),r>0?this._ocrTrack.addClass("paperforge-processing"):this._ocrTrack.removeClass("paperforge-processing");let o=[{cls:"pending",count:a},{cls:"active",count:r},{cls:"done",count:n},{cls:"failed",count:l}];for(let c of o)if(c.count>0){let p=(c.count/s*100).toFixed(1);this._ocrTrack.createEl("div",{cls:`paperforge-progress-seg ${c.cls}`,attr:{style:`width:${p}%`}})}}if(this._ocrCounts){this._ocrCounts.empty();let o=[{cls:"pending",value:a,label:"Pending"},{cls:"active",value:r,label:"Processing"},{cls:"done",value:n,label:"Done"},{cls:"failed",value:l,label:"Failed"}];for(let c of o){let p=this._ocrCounts.createEl("div",{cls:"paperforge-ocr-count"});p.createEl("div",{cls:"paperforge-ocr-count-value",text:c.value.toString()}),p.createEl("div",{cls:"paperforge-ocr-count-label",text:c.label})}}}_renderLifecycleStepper(e,t,s){if(!t||!s){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"}),r=!1;for(let l of n){let o=a.createEl("div",{cls:"step"});o.createEl("div",{cls:"step-indicator"}),o.createEl("div",{cls:"step-label",text:l.label}),l.key===s?(o.addClass("current"),r=!0):r?o.addClass("pending"):o.addClass("completed")}}_renderHealthMatrix(e,t){if(!t){this._renderSkeleton(e);return}let s=[{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 s){let r=t[a.key]||"healthy",l=n.createEl("div",{cls:"paperforge-health-cell"}),o,c,p;r==="healthy"||r==="ok"?(o=a.iconOk,c="ok",p=`${a.label}: OK`):r==="warn"||r==="warning"||r==="degraded"?(o=a.iconWarn,c="warn",p=`${a.label}: Needs Attention`):(o=a.iconFail,c="fail",p=`${a.label}: Failed`),l.addClass(c),l.setAttribute("title",p),l.createEl("div",{cls:"paperforge-health-cell-icon",text:o}),l.createEl("div",{cls:"paperforge-health-cell-label",text:a.label})}}_renderMaturityGauge(e,t,s){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"}),r=4,l=Math.max(1,Math.min(r,Math.round(t)));for(let o=1;o<=r;o++){let c=a.createEl("div",{cls:"gauge-segment"});o<=l&&(c.addClass("filled"),c.addClass(`level-${o}`))}if(n.createEl("div",{cls:"gauge-level",text:`Level ${l} / ${r}`}),l<r&&s){let o=typeof s=="string"?[s]:s;if(o.length>0){let c=n.createEl("ul",{cls:"gauge-blockers"});for(let p of o)c.createEl("li",{text:p})}}}_renderBarChart(e,t){if(!t||Object.keys(t).length===0){this._renderEmptyState(e,"No lifecycle data");return}let s=[{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,...s.map(r=>t[r.key]||0));for(let r of s){let l=t[r.key]||0,o=l/a*100,c=n.createEl("div",{cls:"bar-row"});c.createEl("div",{cls:"bar-label",text:r.label}),c.createEl("div",{cls:"bar-track"}).createEl("div",{cls:`bar-fill ${r.cls}`,attr:{style:`width:${o.toFixed(1)}%`}}),c.createEl("div",{cls:"bar-count",text:l.toString()})}}_invalidateIndex(){this._cachedItems=null}_extractZoteroKeyFromPath(e){return _t(e)}_resolveModeForFile(e){if(!e)return{mode:"global",filePath:null,key:null,domain:null};let t=e.extension,s=e.path;if(t==="base")return{mode:"collection",filePath:s,key:null,domain:e.basename.trim()};if(t==="md"){let a=this.app.metadataCache.getFileCache(e),r=a&&a.frontmatter&&a.frontmatter.zotero_key;if(r)return{mode:"paper",filePath:s,key:r,domain:null}}if(t==="pdf"){let a=this._getCachedIndex();for(let r of a){let l=(r.pdf_path||"").match(/\[\[([^\]]+)\]\]/);if((l?l[1]:r.pdf_path)===s)return{mode:"paper",filePath:s,key:r.zotero_key,domain:null}}}let n=this._extractZoteroKeyFromPath(s);return n?{mode:"paper",filePath:s,key:n,domain:null}:{mode:"global",filePath:s,key:null,domain:null}}_detectAndSwitch(){let e=this._resolveModeForFile(this.app.workspace.getActiveFile());this._currentDomain=e.domain||null,this._currentPaperKey=e.key||null,this._currentPaperEntry=e.key?this._findEntry(e.key):null,this._switchMode(e.mode,e.filePath)}_switchMode(e,t){if(this._currentMode===e&&this._currentFilePath===t){this._refreshCurrentMode();return}if(this._currentMode=e,this._currentFilePath=t,this._techDetailsExpanded=!1,!!this._contentEl)switch(this._contentEl.empty(),this._contentEl.removeClass("switching"),this._renderModeHeader(e),e){case"global":this._renderGlobalMode();break;case"paper":this._renderPaperMode();break;case"collection":this._renderCollectionMode();break}}_renderGlobalMode(){var be,We,qe,Je,Ue,Ge,Xe;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(),s=t.length,n=0,a=0,r=0;for(let w of t)w.has_pdf&&n++,w.ocr_status==="done"&&a++,w.deep_reading_status==="done"&&r++;let l=e.createEl("div",{cls:"paperforge-library-snapshot"});l.createEl("div",{cls:"paperforge-section-label",text:"Library Snapshot"});let o=l.createEl("div",{cls:"paperforge-snapshot-pills"}),c=[{value:s,label:"papers"},{value:n,label:"PDFs ready"},{value:a,label:"OCR done"},{value:r,label:"deep-read done"}];for(let w of c){let T=o.createEl("div",{cls:"paperforge-snapshot-pill"});T.createEl("span",{cls:"paperforge-snapshot-value",text:String(w.value)}),T.createEl("span",{cls:"paperforge-snapshot-label",text:" "+w.label})}let p=e.createEl("div",{cls:"paperforge-system-status"});p.createEl("div",{cls:"paperforge-section-label",text:"System Status"});let h=p.createEl("div",{cls:"paperforge-status-grid"}),d=this.app.plugins.plugins.paperforge,y=((be=d==null?void 0:d.manifest)==null?void 0:be.version)||"?",b=this._paperforgeVersion;if(!b)try{let w=this.app.vault.adapter.basePath,{path:T,extraArgs:X=[]}=O(w,(We=d==null?void 0:d.settings)!=null?We:null,void 0,void 0),j=(0,ue.execFileSync)(T,[...X,"-c","import paperforge; print(paperforge.__version__)"],{cwd:w,timeout:5e3,encoding:"utf-8",windowsHide:!0}).trim();j&&(b=j.startsWith("v")?j:"v"+j,this._paperforgeVersion=b)}catch(w){}b=b||"\u2014";let v=b==="v"+y;this._renderSystemStatusRow(h,"Runtime",v?"healthy":"mismatch",v?"v"+y:"plugin v"+y+" \u2260 CLI "+b);let f=this._loadIndex(),x=f&&f.items&&f.items.length>0;this._renderSystemStatusRow(h,"Index",x?"healthy":"missing",x?f.items.length+" entries":"formal-library.json not found");let C=((qe=d==null?void 0:d.settings)==null?void 0:qe.system_dir)||"System",E=this.app.vault.adapter.basePath,_=!1,m="No exports found";try{let w=Ce.join(E,C,"PaperForge","exports");if(ae.existsSync(w)){let T=ae.readdirSync(w).filter(X=>X.endsWith(".json"));_=T.length>0,m=_?T.length+" export(s)":"No JSON exports"}}catch(w){}this._renderSystemStatusRow(h,"Zotero Export",_?"healthy":"missing",m);let k=!!((Je=d==null?void 0:d.settings)!=null&&Je.paddleocr_api_key);if(!k)try{let w=((Ue=d==null?void 0:d.settings)==null?void 0:Ue.system_dir)||"System",T=Ce.join(E,w,"PaperForge",".env");if(ae.existsSync(T)){let j=ae.readFileSync(T,"utf-8").match(/^PADDLEOCR_API_TOKEN\s*=\s*(.+)$/m);k=!!(j&&j[1]&&j[1].trim())}}catch(w){}k||(k=!!(process.env.PADDLEOCR_API_TOKEN||process.env.PADDLEOCR_API_KEY||process.env.OCR_TOKEN)),this._renderSystemStatusRow(h,"OCR Token",k?"configured":"missing",k?"Configured":"Not set");let S=!1,F="",R=this.app.vault.adapter.basePath,B=Ve(R);S=ct(R),F=B&&((Ge=B.summary)==null?void 0:Ge.reason)||B&&((Xe=B.summary)==null?void 0:Xe.status)||"Unknown",this._renderSystemStatusRow(h,"Memory Layer",S?"healthy":"fail",F);let q=!v&&b!=="\u2014";if(q||!x||!_||!k){let w=e.createEl("div",{cls:"paperforge-issue-summary"});w.createEl("div",{cls:"paperforge-section-label",text:"\u9700\u8981\u5904\u7406"});let T=w.createEl("div",{cls:"paperforge-issue-list"});q&&T.createEl("div",{cls:"paperforge-issue-item",text:"Runtime version mismatch"}),x||T.createEl("div",{cls:"paperforge-issue-item",text:"Index missing or corrupted"}),_||T.createEl("div",{cls:"paperforge-issue-item",text:"No Zotero export found"}),k||T.createEl("div",{cls:"paperforge-issue-item",text:"PaddleOCR API key not configured"});let X=w.createEl("div",{cls:"paperforge-issue-actions"}),j=X.createEl("button",{cls:"paperforge-contextual-btn"});j.createEl("span",{text:"Run Doctor"}),j.addEventListener("click",()=>{let ve=H.find(Oe=>Oe.id==="paperforge-doctor");ve&&this._runAction(ve,j)});let le=X.createEl("button",{cls:"paperforge-contextual-btn"});le.createEl("span",{text:"Repair Issues"}),le.addEventListener("click",()=>{let ve=H.find(Oe=>Oe.id==="paperforge-repair");ve&&this._runAction(ve,le)})}let A=e.createEl("div",{cls:"paperforge-global-actions"});A.createEl("div",{cls:"paperforge-section-label",text:"Start Working"});let W=A.createEl("div",{cls:"paperforge-global-actions-row"}),K=W.createEl("button",{cls:"paperforge-contextual-btn primary"});K.createEl("span",{cls:"paperforge-contextual-btn-icon",text:"\u{1F4C1}"}),K.createEl("span",{text:"Open Literature Hub"}),K.addEventListener("click",()=>{var X;let w=((X=d==null?void 0:d.settings)==null?void 0:X.base_dir)||"Bases",T=this.app.vault.getAbstractFileByPath(w);if(T){let j=null;if(T.children&&(j=T.children.find(le=>le.extension==="base")),j){let le=this.app.workspace.getLeaf(!1);le&&le.openFile(j)}else new D.Notice("[!!] No .base file found in "+w,6e3)}else new D.Notice("[!!] Base directory not found: "+w,6e3)});let J=W.createEl("button",{cls:"paperforge-contextual-btn"});J.createEl("span",{cls:"paperforge-contextual-btn-icon",text:"\u21BB"}),J.createEl("span",{text:"Sync Library"}),J.addEventListener("click",()=>{let w=H.find(T=>T.id==="paperforge-sync");w&&this._runAction(w,J)});let ie=W.createEl("button",{cls:"paperforge-contextual-btn"});ie.createEl("span",{cls:"paperforge-contextual-btn-icon",text:"\u229E"}),ie.createEl("span",{text:"Run OCR"}),ie.addEventListener("click",()=>{let w=H.find(T=>T.id==="paperforge-ocr");w&&this._runAction(w,ie)});let he=W.createEl("button",{cls:"paperforge-contextual-btn"});he.createEl("span",{cls:"paperforge-contextual-btn-icon",text:"\u2695"}),he.createEl("span",{text:"Run Doctor"}),he.addEventListener("click",()=>{let w=H.find(T=>T.id==="paperforge-doctor");w&&this._runAction(w,he)});let me=W.createEl("button",{cls:"paperforge-contextual-btn"});me.createEl("span",{cls:"paperforge-contextual-btn-icon",text:"\u2139"}),me.createEl("span",{text:"Refresh Status"}),me.addEventListener("click",()=>{this._fetchStats(!1)});let oe=W.createEl("button",{cls:"paperforge-contextual-btn warn"});oe.createEl("span",{cls:"paperforge-contextual-btn-icon",text:"\u21BA"}),oe.createEl("span",{text:"Redo OCR"}),oe.addEventListener("click",()=>{let w=H.find(T=>T.id==="paperforge-ocr-redo");w&&this._runAction(w,oe)});let ye=W.createEl("button",{cls:"paperforge-contextual-btn"});ye.createEl("span",{cls:"paperforge-contextual-btn-icon",text:"\u21BA"}),ye.createEl("span",{text:"Repair Issues"}),ye.addEventListener("click",()=>{let w=H.find(T=>T.id==="paperforge-repair");w&&this._runAction(w,ye)})}_renderSystemStatusRow(e,t,s,n){let a=e.createEl("div",{cls:"paperforge-status-row"});a.createEl("span",{cls:"paperforge-status-dot"}).addClass(s==="healthy"||s==="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 s=this._contentEl.createEl("div",{cls:"paperforge-paper-view"}),n=s.createEl("div",{cls:"paperforge-paper-header"});n.createEl("div",{cls:"paperforge-paper-title",text:e.title||"Untitled"});let a=n.createEl("div",{cls:"paperforge-paper-meta"});e.authors&&e.authors.length>0&&a.createEl("span",{cls:"paperforge-paper-authors",text:e.authors.join(", ")}),e.year&&a.createEl("span",{cls:"paperforge-paper-year",text:String(e.year)});let r=s.createEl("div",{cls:"paperforge-status-strip"}),l=r.createEl("div",{cls:"paperforge-status-strip-left"}),o=r.createEl("div",{cls:"paperforge-status-strip-right"}),c=[{key:"pdf",label:"PDF",ok:e.has_pdf===!0},{key:"ocr",label:"OCR",ok:e.ocr_status==="done",pending:["pending","queued","processing"].includes(e.ocr_status||""),fail:["failed","blocked","done_incomplete","nopdf"].includes(e.ocr_status||"")},{key:"deep",label:"\u7CBE\u8BFB",ok:e.deep_reading_status==="done"}];for(let p of c){let h=l.createEl("span",{cls:"paperforge-status-pill"}),d="pending";p.ok?d="ok":p.fail?d="fail":p.pending&&(d="pending"),h.addClass(d);let y=p.ok?"\u2713":p.fail?"\u2717":"\u25CB";h.createEl("span",{cls:"paperforge-status-pill-icon",text:y}),h.createEl("span",{text:" "+p.label})}if(e.pdf_path){let p=o.createEl("button",{cls:"paperforge-contextual-btn"});p.createEl("span",{cls:"paperforge-contextual-btn-icon",text:"\u{1F4C4}"}),p.createEl("span",{text:"\u6253\u5F00 PDF"}),p.addEventListener("click",()=>{let h=e.pdf_path.match(/\[\[([^\]]+)\]\]/),d=h?h[1]:e.pdf_path;this.app.vault.getAbstractFileByPath(d)?this.app.workspace.openLinkText(d,""):new D.Notice("[!!] PDF not found: "+d,6e3)})}if(e.fulltext_path){let p=o.createEl("button",{cls:"paperforge-contextual-btn"});p.createEl("span",{cls:"paperforge-contextual-btn-icon",text:"\u{1F4DD}"}),p.createEl("span",{text:"\u6253\u5F00\u5168\u6587"}),p.addEventListener("click",()=>this._openFulltext(e.fulltext_path))}if(this._renderPaperOverviewCard(s,e),e.next_step==="ready"&&e.deep_reading_status==="done"){let p=s.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(s,e,t);this._renderRecentDiscussionCard(s,e),this._renderPaperTechnicalDetails(s,e)}_renderPaperOverviewCard(e,t){let s=e.createEl("div",{cls:"paperforge-paper-overview"});s.createEl("div",{cls:"paperforge-paper-overview-header"}).createEl("span",{cls:"paperforge-paper-overview-title",text:"\u6587\u7AE0\u6982\u89C8"});let a=s.createEl("div",{cls:"paperforge-paper-overview-body"}),r=a.createEl("div",{cls:"paperforge-paper-overview-excerpt",text:"\u52A0\u8F7D\u4E2D..."});if(t.note_path){let l=this.app.vault.getAbstractFileByPath(t.note_path);l?this.app.vault.read(l).then(o=>{let c=this._extractOverviewFromNote(o);if(c){let p=c.length>200?c.slice(0,200)+"...":c;if(r.setText(p),c.length>200){let h=a.createEl("div",{cls:"paperforge-expand-container"}),d=h.createEl("button",{cls:"paperforge-expand-icon",title:"\u5C55\u5F00/\u6536\u8D77"});d.innerHTML='<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 y=!1;h.addEventListener("click",()=>{r.setText(y?p:c),d.innerHTML=y?'<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>',y=!y})}}else r.setText("\u5C1A\u672A\u751F\u6210\u6587\u7AE0\u6982\u89C8\u3002\u8FD0\u884C /pf-deep \u5F00\u59CB\u7CBE\u8BFB\u3002")}).catch(()=>{r.setText("\u65E0\u6CD5\u8BFB\u53D6\u7B14\u8BB0\u5185\u5BB9")}):r.setText("\u7B14\u8BB0\u6587\u4EF6\u4E0D\u5B58\u5728")}else r.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 s=e.slice(t),n=["**\u4E00\u53E5\u8BDD\u603B\u89C8:**","**\u4E00\u53E5\u8BDD\u603B\u89C8**","**\u6587\u7AE0\u6458\u8981:**","**\u6587\u7AE0\u6458\u8981**"];for(let l of n){let o=s.indexOf(l);if(o!==-1){let c=s.slice(o+l.length),p=["**5 Cs","**Figure","**\u8BC1\u636E","### Pass 2","## "],h=c.length;for(let b of p){let v=c.indexOf(b);v!==-1&&v<h&&(h=v)}let d=c.indexOf(`
|
|
|
|
`);d!==-1&&d<h&&(h=d);let y=c.slice(0,h).trim();return y.startsWith("**")&&(y=y.slice(2)),y.endsWith("**")&&(y=y.slice(0,-2)),y||null}}let a=s.indexOf(`
|
|
`);if(a===-1)return null;let r=s.slice(a+1).split(`
|
|
|
|
`)[0].trim();return!r||r.startsWith("###")||r.startsWith("##")?null:r.length>300?r.slice(0,300)+"...":r}_renderRecentDiscussionCard(e,t){let s=e.createEl("div",{cls:"paperforge-discussion-card"});if(s.style.display="none",!t.note_path)return;let n=t.note_path.lastIndexOf("/"),r=(n!==-1?t.note_path.substring(0,n):".")+"/ai/discussion.md";this.app.vault.adapter.exists(r).then(l=>{if(l)return this.app.vault.adapter.read(r)}).then(async l=>{if(!l)return;let o=this._parseDiscussionMD(l);if(!o||o.length===0)return;s.style.display="block",s.createEl("div",{cls:"paperforge-discussion-header"}).createEl("span",{cls:"paperforge-discussion-title",text:"\u6700\u8FD1\u8BA8\u8BBA"});for(let h of o){let d=s.createEl("div",{cls:"paperforge-discussion-item"}),y=d.createEl("div",{cls:"paperforge-discussion-q"});y.createEl("span",{cls:"paperforge-discussion-q-label",text:"\u63D0\u95EE\uFF1A"}),y.createEl("span",{cls:"paperforge-discussion-q-text",text:h.question});let b=d.createEl("div",{cls:"paperforge-discussion-a"}),v=!1;if(h.answer&&h.answer.length>500&&(v=!0,b.classList.add("paperforge-discussion-a-collapsed")),await D.MarkdownRenderer.render(this.app,h.answer||"",b,r,this),v){let f=!1;d.style.cursor="pointer",d.addEventListener("click",()=>{f=!f,b.classList.toggle("paperforge-discussion-a-collapsed",!f),b.classList.toggle("paperforge-discussion-a-expanded",f)})}}s.createEl("a",{cls:"paperforge-discussion-viewall",text:"\u67E5\u770B\u5168\u90E8\u8BA8\u8BBA \u2192"}).addEventListener("click",h=>{h.preventDefault(),this.app.vault.getAbstractFileByPath(r)?this.app.workspace.openLinkText(r,""):new D.Notice("\u8BA8\u8BBA\u6587\u4EF6\u5C1A\u672A\u751F\u6210")})}).catch(l=>{console.error("PaperForge: discussion.md read error",r,l.message)})}_parseDiscussionMD(e){let t=e.split(/\n## /).slice(1);if(t.length===0)return null;let s=t[t.length-1],n=[],a=s.split(/\*\*\u95EE\u9898:\*\*/).slice(1);for(let r of a){let l=r.match(/\*\*\u89E3\u7B54:\*\*/);if(!l)continue;let o=r.substring(0,l.index).trim(),c=r.substring(l.index+3+4).trim();n.push({question:o,answer:c})}return n.slice(-3)}_renderPaperTechnicalDetails(e,t){let s=this._currentPaperKey,n=e.createEl("div",{cls:"paperforge-technical-details"}),a=n.createEl("button",{cls:"paperforge-technical-details-toggle"}),r=n.createEl("div",{cls:"paperforge-technical-details-body"});r.style.display="none",this._techDetailsExpanded?(r.style.display="block",a.setText("\u6280\u672F\u8BE6\u60C5 \u25BE")):a.setText("\u6280\u672F\u8BE6\u60C5 \u25B8"),a.addEventListener("click",()=>{let h=r.style.display!=="none";r.style.display=h?"none":"block",a.setText(h?"\u6280\u672F\u8BE6\u60C5 \u25B8":"\u6280\u672F\u8BE6\u60C5 \u25BE"),this._techDetailsExpanded=!h});let l=r.createEl("div",{cls:"paperforge-workflow-toggles"}),o=[{key:"do_ocr",label:"OCR",hint:"\u52A0\u5165 OCR"},{key:"analyze",label:"\u7CBE\u8BFB",hint:"\u6807\u8BB0\u7CBE\u8BFB"}];for(let h of o){let d=l.createEl("label",{cls:"paperforge-workflow-toggle"}),y=d.createEl("input",{type:"checkbox",cls:"paperforge-workflow-checkbox"});y.checked=t[h.key]===!0,d.createEl("span",{cls:"paperforge-workflow-toggle-label",text:h.label}),d.createEl("span",{cls:"paperforge-workflow-toggle-hint",text:h.hint}),y.addEventListener("change",async()=>{let b=t.note_path?this.app.vault.getAbstractFileByPath(t.note_path):null;if(!b){new D.Notice("[!!] Note file not found",6e3);return}let v=y.checked;await this.app.fileManager.processFrontMatter(b,f=>{f[h.key]=v}),this._patchCachedEntry(s,{[h.key]:v}),this._currentPaperEntry=Ie(this._currentPaperEntry,{[h.key]:v})})}let c=t.health||{},p=[["PDF Health",c.pdf_health||"\u2014"],["OCR Status",t.ocr_status||"\u2014"],["Asset Health",c.asset_health||"\u2014"],["Note Path",t.note_path||"\u2014"],["Fulltext Path",t.fulltext_path||"\u2014"]];for(let[h,d]of p){let y=r.createEl("div",{cls:"paperforge-technical-row"});y.createEl("span",{cls:"paperforge-technical-label",text:h}),y.createEl("span",{cls:"paperforge-technical-value",text:String(d)})}}_renderNextStepCard(e,t,s){var o,c;let n=t.next_step||"ready",a={sync:{label:"Sync Needed",text:"This paper needs to be synced from Zotero. Click to run sync.",cmd:"sync",icon:"\u21BB"},ocr:{label:"OCR Needed",text:"Fulltext is missing but PDF is present. Click to run OCR.",cmd:"ocr",icon:"\u229E"},repair:{label:"Repair Needed",text:"State divergence or path errors detected. Click to repair.",cmd:"repair",icon:"\u21BA"},"rebuild index":{label:"Rebuild Needed",text:"Index may be stale. Click to run sync to rebuild.",cmd:"sync",icon:"\u21BB"},"/pf-deep":{label:"Ready for Deep Reading",text:"Fulltext is ready. Copy /pf-deep command and run in your agent.",cmd:null,icon:"\u{1F50D}"},ready:{label:"All Set",text:"This paper is fully processed and ready for use.",cmd:"ready",icon:"\u2713"}},r=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:r.text}),r.cmd&&r.cmd!=="ready"){let p=l.createEl("button",{cls:"paperforge-next-step-trigger"});p.createEl("span",{text:r.icon+" "+r.label}),p.addEventListener("click",()=>{let h=H.find(d=>d.cmd===r.cmd);h&&this._runAction(h,p)})}else if(n==="/pf-deep"){let p=l.createEl("button",{cls:"paperforge-next-step-trigger"});p.createEl("span",{text:"\u{1F4CB} "+i("copy_pf_deep_cmd")}),p.addEventListener("click",()=>{let v="/pf-deep "+s;navigator.clipboard.writeText(v).then(()=>{p.setText("\u2713 "+i("copied")),new D.Notice(v+" copied")}).catch(()=>{new D.Notice("[!!] Clipboard write failed",6e3)})});let h=((c=(o=this.app.plugins.plugins.paperforge)==null?void 0:o.settings)==null?void 0:c.agent_platform)||"opencode",y={opencode:"OpenCode",claude:"Claude Code",cursor:"Cursor",github_copilot:"GitHub Copilot",windsurf:"Windsurf",codex:"Codex",gemini:"Gemini CLI",cline:"Cline"}[h]||h;l.createEl("div",{cls:"paperforge-agent-platform-label"}).setText(i("run_in_agent").replace("{0}",y))}else n==="ready"&&l.createEl("button",{cls:"paperforge-next-step-trigger"}).createEl("span",{text:"\u2713 "+r.label})}_openFulltext(e){if(!e){new D.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 D.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 s=this._contentEl.createEl("div",{cls:"paperforge-collection-view"}),n=t.length,a=0,r=0,l=0,o=0,c=0,p=0,h=0;for(let _ of t){_.has_pdf&&a++,_.ocr_status==="done"&&r++,_.ocr_status==="done"&&_.analyze===!0&&l++,_.deep_reading_status==="done"&&o++;let m=_.ocr_status||"";m==="pending"||m==="queued"?c++:m==="processing"?p++:(m==="failed"||m==="blocked"||m==="done_incomplete"||m==="nopdf")&&h++}s.createEl("div",{cls:"paperforge-collection-header"}).createEl("div",{cls:"paperforge-collection-title",text:e});let y=s.createEl("div",{cls:"paperforge-workflow-overview"});y.createEl("div",{cls:"paperforge-section-label",text:"Workflow Overview"});let b=y.createEl("div",{cls:"paperforge-workflow-funnel"}),v=[{value:n,label:"Total"},{value:a,label:"PDF Ready"},{value:r,label:"OCR Done"},{value:o,label:"Deep Read"}];for(let _=0;_<v.length;_++){let m=b.createEl("div",{cls:"paperforge-workflow-stage"});m.createEl("div",{cls:"paperforge-workflow-stage-value",text:String(v[_].value)}),m.createEl("div",{cls:"paperforge-workflow-stage-label",text:v[_].label}),_<v.length-1&&b.createEl("div",{cls:"paperforge-workflow-arrow",text:"\u2192"})}if(c+p+r+h>0){let _=s.createEl("div",{cls:"paperforge-ocr-section"}),m=_.createEl("div",{cls:"paperforge-collection-ocr-header"});m.createEl("h4",{cls:"paperforge-ocr-title",text:"OCR Pipeline"});let k=m.createEl("span",{cls:"paperforge-ocr-badge idle"});p>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"});p>0&&S.addClass("paperforge-processing");let F=c+p+r+h,R=[{cls:"pending",count:c},{cls:"active",count:p},{cls:"done",count:r},{cls:"failed",count:h}];for(let U of R)if(U.count>0){let A=(U.count/F*100).toFixed(1);S.createEl("div",{cls:`paperforge-progress-seg ${U.cls}`,attr:{style:`width:${A}%`}})}let B=_.createEl("div",{cls:"paperforge-ocr-counts"}),q=[{cls:"pending",value:c,label:"Pending"},{cls:"active",value:p,label:"Processing"},{cls:"done",value:r,label:"Done"},{cls:"failed",value:h,label:"Attention"}];for(let U of q){let A=B.createEl("div",{cls:"paperforge-ocr-count"});A.createEl("div",{cls:"paperforge-ocr-count-value",text:U.value.toString()}),A.createEl("div",{cls:"paperforge-ocr-count-label",text:U.label})}}let f=s.createEl("div",{cls:"paperforge-collection-actions"}),x=f.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 _=H.find(m=>m.id==="paperforge-ocr");_&&this._runAction(_,x)});let C=f.createEl("button",{cls:"paperforge-contextual-btn"});C.createEl("span",{cls:"paperforge-contextual-btn-icon",text:"\u21BB"}),C.createEl("span",{text:"Sync Library"}),C.addEventListener("click",()=>{let _=H.find(m=>m.id==="paperforge-sync");_&&this._runAction(_,C)});let E=f.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 _=H.find(m=>m.id==="paperforge-ocr-redo");_&&this._runAction(_,E)})}_refreshCurrentMode(){if(!(!this._currentMode||!this._contentEl)){this._contentEl.empty(),this._contentEl.addClass("switching"),this._invalidateIndex(),this._currentPaperEntry=this._currentPaperKey?this._findEntry(this._currentPaperKey):null,this._renderModeHeader(this._currentMode);try{switch(this._currentMode){case"global":this._renderGlobalMode();break;case"paper":this._renderPaperMode();break;case"collection":this._renderCollectionMode();break}}finally{setTimeout(()=>{this._contentEl&&this._contentEl.removeClass("switching")},50)}}}_runAction(e,t){var d,y;if(e.disabled){new D.Notice(`[i] ${e.disabledMsg||"This action is not yet available."}`,6e3);return}if(t.classList.contains("running"))return;t.addClass("running");let s=this.app.vault.adapter.basePath;this._showMessage("Processing...","running");let n=Array.isArray(e.args)?[...e.args]:[];if(e.needsKey){let b=this.app.workspace.getActiveFile(),v=null;if(b){let f=this.app.metadataCache.getFileCache(b);if(f&&f.frontmatter&&f.frontmatter.zotero_key?v=f.frontmatter.zotero_key:v=this._extractZoteroKeyFromPath(b.path),v)n=[...n,v];else if(f&&f.frontmatter){this._showMessage("[!!] No zotero_key in active note frontmatter","error"),new D.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 D.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 D.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:r,extraArgs:l=[]}=O(s,(y=(d=this.app.plugins.plugins.paperforge)==null?void 0:d.settings)!=null?y:null,void 0,void 0),o=(0,ue.spawn)(r,[...l,"-m","paperforge",e.cmd,...n],{cwd:s,timeout:a}),c=[],p=Date.now(),h=setInterval(()=>this._fetchStats(!0),4e3);o.stdout.on("data",b=>{let v=b.toString("utf-8").split(`
|
|
`).filter(Boolean);for(let f of v){let x=f.trim();x&&(c.push(x),this._showMessage(c.slice(-8).join(`
|
|
`),"running"))}}),o.stderr.on("data",b=>{let v=b.toString("utf-8").split(`
|
|
`).filter(Boolean);for(let f of v){if(f.includes("\r")||f.includes("%")||f.includes("\u2588"))continue;let x=f.trim();x&&!x.match(/^\d+%|^\|/)&&(c.push(x),this._showMessage(c.slice(-8).join(`
|
|
`),"running"))}}),o.on("close",b=>{clearInterval(h),t.removeClass("running");let v=((Date.now()-p)/1e3).toFixed(1);if(b!==0){let f=c.slice(-3).join(" | ")||"exit code "+b;(e.cmd==="repair"||e.cmd==="ocr")&&b===1?(this._showMessage("[WARN] "+f,"running"),new D.Notice("[WARN] "+e.cmd+" partial: "+f,8e3),this._fetchStats(!0)):(this._showMessage("[!!] "+f,"error"),new D.Notice("[!!] "+e.cmd+" failed: "+f,8e3))}else if(e.needsKey||e.needsFilter){let f=c.join(`
|
|
`);if(f.trim())try{JSON.parse(f),navigator.clipboard.writeText(f).then(()=>{let x=`${v}s \u2014 ${f.length} chars copied`;this._showMessage("[OK] "+e.title+": "+x,"ok"),new D.Notice("[OK] "+e.okMsg+" \u2014 "+f.length+" chars")}).catch(x=>{this._showMessage("[!!] Clipboard write failed: "+x.message,"error"),new D.Notice("[!!] Clipboard error",6e3)})}catch(x){this._showMessage("[!!] Invalid JSON from "+e.title,"error"),new D.Notice("[!!] "+e.title+" returned invalid JSON: "+x.message.slice(0,100),8e3)}else this._showMessage("[!!] No output from context command","error"),new D.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]||"",C=`${v}s \u2014 ${x}`;this._showMessage("[OK] "+e.title+": "+C,"ok"),new D.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"&&Re(this.app,this.app.plugins.plugins.paperforge,s)}}),o.on("error",b=>{t.removeClass("running"),this._contentEl&&this._contentEl.removeClass("switching"),this._showMessage("[!!] "+b.message,"error"),new D.Notice("[!!] Cannot start: "+b.message,8e3)})}_showMessage(e,t){this._messageEl&&(this._messageEl.setText(e),this._messageEl.className=`paperforge-message msg-${t}`)}_renderModeHeader(e){if(!this._modeContextEl)return;this._modeContextEl.empty();let t=this._modeContextEl.createEl("span",{cls:"paperforge-mode-badge"}),s="";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?s=this._currentPaperEntry.title:this._currentPaperKey?(s=this._currentPaperKey,this._modeContextEl.createEl("span",{cls:"paperforge-mode-warning",text:"Not found in index"})):s="Unknown paper";break;case"collection":t.addClass("collection"),t.setText("Collection"),this._headerTitle&&this._headerTitle.setText("Collection"),s=this._currentDomain||"Unknown Domain";break}s&&this._modeContextEl.createEl("span",{cls:"paperforge-mode-name",text:s})}_setupEventSubscriptions(){let e=this.app.workspace.on("active-leaf-change",()=>{this._leafChangeTimer&&clearTimeout(this._leafChangeTimer),this._leafChangeTimer=setTimeout(()=>{let s=this._resolveModeForFile(this.app.workspace.getActiveFile()),n=s.mode,a=s.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",s=>{s&&s.path&&s.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(ce);if(t.length>0){e.app.workspace.revealLeaf(t[0]);return}let s=e.app.workspace.getRightLeaf(!1);s&&(await s.setViewState({type:ce,active:!0}),e.app.workspace.revealLeaf(s))}};var Ae=class extends M.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(),tt(this.app),this.registerView(ce,t=>new fe(t));try{(0,M.addIcon)(xe,Qe)}catch(t){}this.addRibbonIcon(xe,"PaperForge Dashboard",()=>fe.open(this)),H.find(t=>t.id==="paperforge-ocr-redo")&&this.addRibbonIcon("reset","PaperForge: Redo OCR",()=>{let t=this.app.vault.adapter.basePath;new M.Notice("PaperForge: Redo OCR starting...");let{path:s,extraArgs:n}=O(t,this.settings,void 0,void 0);(0,se.execFile)(s,[...n,"-m","paperforge","ocr","redo"],{cwd:t,timeout:6e5},(a,r,l)=>{if(a){new M.Notice("PaperForge: Redo OCR failed");return}new M.Notice("PaperForge: Redo OCR done")})}),this.addSettingTab(new Be(this.app,this)),this.addCommand({id:"paperforge-status-panel",name:`PaperForge: ${i("guide_open")}`,callback:()=>fe.open(this)});for(let t of H)this.addCommand({id:t.id,name:`PaperForge: ${t.title}`,callback:()=>{if(t.disabled){new M.Notice(`[i] ${t.disabledMsg||"This action is not yet available."}`,6e3);return}let s=this.app.vault.adapter.basePath;new M.Notice(`PaperForge: running ${t.cmd}...`);let{path:n,extraArgs:a=[]}=O(s,this.settings,void 0,void 0),r=Array.isArray(t.args)?[...t.args]:[];(0,se.execFile)(n,[...a,"-m","paperforge",t.cmd,...r],{cwd:s,timeout:3e5},(l,o,c)=>{if(l){new M.Notice(`[!!] ${t.cmd} failed: ${(c||l.message).slice(0,120)}`,8e3);return}new M.Notice(`[OK] ${t.okMsg||o.trim().split(`
|
|
`)[0].slice(0,80)}`)})}});this.settings.auto_update_on_startup===!0&&this.settings.setup_complete&&setTimeout(()=>this._autoUpdate(),3e3),this._startFilePolling(),this._firstLaunchSnapshotMigration(),this._checkReleaseNotes()}_firstLaunchSnapshotMigration(){let e=this.app.vault.adapter.basePath;if(!e)return;let s=te(e).memoryStatePath;if(!L.existsSync(s)){let n=O(e,this.settings,void 0,void 0);[["runtime-health","--json"],["memory","status","--json"],["embed","status","--json"]].forEach(r=>{let l=[...n.extraArgs,"-m","paperforge","--vault",e,...r];(0,se.execFile)(n.path,l,{cwd:e,timeout:6e4,windowsHide:!0},()=>{})})}}_autoUpdate(){let e=this.app.vault.adapter.basePath,{path:t,extraArgs:s=[]}=O(e,this.settings,void 0,void 0),n=this.manifest.version,a=`paperforge==${n}`,r=`git+https://github.com/LLLin000/PaperForge.git@${n}`,l=(o,c)=>{(0,se.spawn)(t,[...s,"-m","pip","install","--upgrade",o],{cwd:e,timeout:12e4,env:pe()}).on("close",h=>c(h===0))};(0,se.execFile)(t,[...s,"-c","import paperforge; print(paperforge.__version__)"],{cwd:e,timeout:1e4},(o,c)=>{let p=d=>{console.log(`[PaperForge] Auto-update: trying PyPI (paperforge==${n})`),l(a,y=>{if(y){console.log("[PaperForge] Auto-update: installed via PyPI"),new M.Notice(`[OK] PaperForge CLI ${d}`,5e3);return}console.warn("[PaperForge] Auto-update: PyPI failed, falling back to git..."),l(r,b=>{b&&(console.log("[PaperForge] Auto-update: installed via git"),new M.Notice(`[OK] PaperForge CLI ${d} (via git)`,5e3))})})};if(o){p("installed");return}let h=c.trim();h!==n&&p(`${h} -> ${n}`)})}_startFilePolling(){let e=this.app.vault.adapter.basePath;this._pollTimer=setInterval(()=>{this._checkExports(e),this._checkOcr(e)},12e4)}_checkExports(e){if(this._autoSyncRunning)return;let t=te(e).exportsDir;if(!L.existsSync(t))return;let s=0;try{L.readdirSync(t).forEach(n=>{if(!n.endsWith(".json"))return;let a=L.statSync(_e.join(t,n));a.mtimeMs>s&&(s=a.mtimeMs)})}catch(n){return}s>this._lastExportMtime&&(this._lastExportMtime=s,this._autoSync(e))}_autoSync(e){if(this._autoSyncRunning)return;this._autoSyncRunning=!0;let t=O(e,this.settings,void 0,void 0);if(!t.path){this._autoSyncRunning=!1;return}let s=`"${t.path}" -m paperforge --vault "${e}" sync`;(0,se.exec)(s,{timeout:12e4,encoding:"utf-8"},(n,a,r)=>{this._autoSyncRunning=!1,this._memoryStatusText=null,n||(this._lastSyncTime=new Date().toLocaleTimeString());try{let l=te(e).exportsDir,o=0;L.readdirSync(l).forEach(c=>{c.endsWith(".json")&&(o=Math.max(o,L.statSync(_e.join(l,c)).mtimeMs))}),this._lastExportMtime=o}catch(l){}})}_checkOcr(e){if(this._autoSyncRunning)return;let t=te(e).ocrDir;if(L.existsSync(t))try{L.readdirSync(t,{withFileTypes:!0}).forEach(s=>{if(!s.isDirectory())return;let n=_e.join(t,s.name,"meta.json");if(!L.existsSync(n))return;let a=L.statSync(n),r=this._lastOcrMtimes[s.name]||0;if(a.mtimeMs<=r||(this._lastOcrMtimes[s.name]=a.mtimeMs,this._autoSyncRunning))return;this._autoSyncRunning=!0;let l=O(e,this.settings,void 0,void 0);if(!l.path){this._autoSyncRunning=!1;return}let o=`"${l.path}" -m paperforge --vault "${e}" sync`;(0,se.exec)(o,{timeout:3e4,encoding:"utf-8"},()=>{this._autoSyncRunning=!1,this._memoryStatusText=null})})}catch(s){}}readPaperforgeJson(){let e=this.app.vault.adapter.basePath,t=_e.join(e,"paperforge.json"),s={system_dir:"System",resources_dir:"Resources",literature_dir:"Literature",base_dir:"Bases"};try{if(!L.existsSync(t))return s;let n=L.readFileSync(t,"utf-8"),a=JSON.parse(n),r=a.vault_config||{};return{system_dir:r.system_dir||a.system_dir||s.system_dir,resources_dir:r.resources_dir||a.resources_dir||s.resources_dir,literature_dir:r.literature_dir||a.literature_dir||s.literature_dir,base_dir:r.base_dir||a.base_dir||s.base_dir}}catch(n){return console.warn("PaperForge: Failed to read paperforge.json, using defaults",n),s}}savePaperforgeJson(e){let t=this.app.vault.adapter.basePath,s=_e.join(t,"paperforge.json"),n={};try{L.existsSync(s)&&(n=JSON.parse(L.readFileSync(s,"utf-8")))}catch(r){console.warn("PaperForge: Failed to read paperforge.json for update",r)}(!n.vault_config||typeof n.vault_config!="object")&&(n.vault_config={});let a=["system_dir","resources_dir","literature_dir","base_dir"];for(let r of a)e[r]!==void 0&&(n.vault_config[r]=e[r]);n.schema_version||(n.schema_version="2");for(let r of a)delete n[r];try{if(L.writeFileSync(s,JSON.stringify(n,null,2),"utf-8"),this.settings){let r=this.readPaperforgeJson();this.settings.system_dir=r.system_dir,this.settings.resources_dir=r.resources_dir,this.settings.literature_dir=r.literature_dir,this.settings.base_dir=r.base_dir}}catch(r){console.error("PaperForge: Failed to write paperforge.json",r),new M.Notice("PaperForge: Failed to save configuration to paperforge.json")}}onunload(){this._pollTimer&&clearInterval(this._pollTimer),this.app.workspace.detachLeavesOfType(ce)}async loadSettings(){this.settings=Object.assign({},Ee,await this.loadData()),this.settings.features&&Ee.features&&(this.settings.features=Object.assign({},Ee.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();L.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(Ee))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=(Ne().versions||[]).find(l=>l.version===e);class r extends M.Modal{constructor(o,c){super(o),this._entry=c}onOpen(){let{contentEl:o}=this;if(o.createEl("h2",{text:`PaperForge v${e} \u66F4\u65B0\u8BF4\u660E`}),this._entry){if(o.createEl("p",{text:this._entry.title,cls:"paperforge-modal-subtitle"}),this._entry.breaking_or_migration&&this._entry.breaking_or_migration.length>0){o.createEl("h4",{text:"\u884C\u4E3A\u53D8\u66F4 / \u8FC1\u79FB\u6CE8\u610F"});for(let c of this._entry.breaking_or_migration)o.createEl("p",{text:`\u2022 ${c}`,cls:"paperforge-modal-item"})}if(this._entry.new_features&&this._entry.new_features.length>0){o.createEl("h4",{text:"\u65B0\u529F\u80FD"});for(let c of this._entry.new_features)o.createEl("p",{text:`\u2022 ${c}`,cls:"paperforge-modal-item"})}if(this._entry.fixes&&this._entry.fixes.length>0){o.createEl("h4",{text:"\u4FEE\u590D"});for(let c of this._entry.fixes)o.createEl("p",{text:`\u2022 ${c}`,cls:"paperforge-modal-item"})}if(this._entry.recommended_actions&&this._entry.recommended_actions.length>0){let c=o.createEl("div",{cls:"paperforge-release-recommended"});c.createEl("h4",{text:"\u5EFA\u8BAE\u64CD\u4F5C",cls:""}),c.style.marginBottom="8px";for(let p of this._entry.recommended_actions)c.createEl("p",{text:`\u2022 ${p}`,cls:"paperforge-release-item-bold"})}}else o.createEl("p",{text:"\u7248\u672C\u5DF2\u66F4\u65B0\u81F3 v"+e+"\uFF0C\u8BF7\u524D\u5F80\u8BBE\u7F6E \u2192 \u66F4\u65B0\u4E0E\u624B\u518C \u67E5\u770B\u5B8C\u6574\u66F4\u65B0\u8BB0\u5F55\u3002"});new M.Setting(o).addButton(c=>c.setButtonText("\u77E5\u9053\u4E86").setCta().onClick(()=>{this.close()}))}onClose(){let{contentEl:o}=this;o.empty()}}new r(this.app,a).open(),this.settings.last_seen_version=e,this.saveSettings()}};
|