From 460412d42312dd8b422a7280bb26a05e5587fe6f Mon Sep 17 00:00:00 2001 From: LLLin000 <809867916@qq.com> Date: Sat, 11 Jul 2026 00:39:25 +0800 Subject: [PATCH] fix: isVectorReady checks total_chunks instead of fulltext-only chunk_count --- paperforge/plugin/main.js | 2 +- paperforge/plugin/src/services/memory-state.ts | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/paperforge/plugin/main.js b/paperforge/plugin/main.js index b963af93..442a9f26 100644 --- a/paperforge/plugin/main.js +++ b/paperforge/plugin/main.js @@ -45,7 +45,7 @@ Make sure paperforge is installed and in your PATH.`});return}try{let y=JSON.par `);p!==-1&&p300?s.slice(0,300)+"...":s}_renderRecentDiscussionCard(e,t){let r=e.createEl("div",{cls:"paperforge-discussion-card"});if(r.style.display="none",!t.note_path)return;let n=t.note_path.lastIndexOf("/"),s=(n!==-1?t.note_path.substring(0,n):".")+"/ai/discussion.md";this.app.vault.adapter.exists(s).then(i=>{if(i)return this.app.vault.adapter.read(s)}).then(async i=>{if(!i)return;let l=this._parseDiscussionMD(i);if(!l||l.length===0)return;r.style.display="block",r.createEl("div",{cls:"paperforge-discussion-header"}).createEl("span",{cls:"paperforge-discussion-title",text:"\u6700\u8FD1\u8BA8\u8BBA"});for(let f of l){let p=r.createEl("div",{cls:"paperforge-discussion-item"}),m=p.createEl("div",{cls:"paperforge-discussion-q"});m.createEl("span",{cls:"paperforge-discussion-q-label",text:"\u63D0\u95EE\uFF1A"}),m.createEl("span",{cls:"paperforge-discussion-q-text",text:f.question});let y=p.createEl("div",{cls:"paperforge-discussion-a"}),x=!1;if(f.answer&&f.answer.length>500&&(x=!0,y.classList.add("paperforge-discussion-a-collapsed")),await I.MarkdownRenderer.render(this.app,f.answer||"",y,s,this),x){let _=!1;p.style.cursor="pointer",p.addEventListener("click",()=>{_=!_,y.classList.toggle("paperforge-discussion-a-collapsed",!_),y.classList.toggle("paperforge-discussion-a-expanded",_)})}}r.createEl("a",{cls:"paperforge-discussion-viewall",text:"\u67E5\u770B\u5168\u90E8\u8BA8\u8BBA \u2192"}).addEventListener("click",f=>{f.preventDefault(),this.app.vault.getAbstractFileByPath(s)?this.app.workspace.openLinkText(s,""):new I.Notice("\u8BA8\u8BBA\u6587\u4EF6\u5C1A\u672A\u751F\u6210")})}).catch(i=>{console.error("PaperForge: discussion.md read error",s,i.message)})}_parseDiscussionMD(e){let t=e.split(/\n## /).slice(1);if(t.length===0)return null;let r=t[t.length-1],n=[],a=r.split(/\*\*\u95EE\u9898:\*\*/).slice(1);for(let s of a){let i=s.match(/\*\*\u89E3\u7B54:\*\*/);if(!i)continue;let l=s.substring(0,i.index).trim(),c=s.substring(i.index+3+4).trim();n.push({question:l,answer:c})}return n.slice(-3)}_renderPaperTechnicalDetails(e,t){let r=this._currentPaperKey,n=e.createEl("div",{cls:"paperforge-technical-details"}),a=n.createEl("button",{cls:"paperforge-technical-details-toggle"}),s=n.createEl("div",{cls:"paperforge-technical-details-body"});s.style.display="none",this._techDetailsExpanded?(s.style.display="block",a.setText("\u6280\u672F\u8BE6\u60C5 \u25BE")):a.setText("\u6280\u672F\u8BE6\u60C5 \u25B8"),a.addEventListener("click",()=>{let p=s.style.display!=="none";s.style.display=p?"none":"block",a.setText(p?"\u6280\u672F\u8BE6\u60C5 \u25B8":"\u6280\u672F\u8BE6\u60C5 \u25BE"),this._techDetailsExpanded=!p});let i=s.createEl("div",{cls:"paperforge-workflow-toggles"}),l=[{key:"do_ocr",label:"OCR",hint:"\u52A0\u5165 OCR"},{key:"analyze",label:"\u7CBE\u8BFB",hint:"\u6807\u8BB0\u7CBE\u8BFB"}];for(let p of l){let m=i.createEl("label",{cls:"paperforge-workflow-toggle"}),y=m.createEl("input",{type:"checkbox",cls:"paperforge-workflow-checkbox"});y.checked=t[p.key]===!0,m.createEl("span",{cls:"paperforge-workflow-toggle-label",text:p.label}),m.createEl("span",{cls:"paperforge-workflow-toggle-hint",text:p.hint}),y.addEventListener("change",async()=>{let x=t.note_path?this.app.vault.getAbstractFileByPath(t.note_path):null;if(!x){new I.Notice("[!!] Note file not found",6e3);return}let _=y.checked;await this.app.fileManager.processFrontMatter(x,b=>{b[p.key]=_}),this._patchCachedEntry(r,{[p.key]:_}),this._currentPaperEntry=Ze(this._currentPaperEntry,{[p.key]:_})})}let c=t.health||{},d=[["PDF Health",c.pdf_health||"\u2014"],["OCR Status",t.ocr_status||"\u2014"],["Asset Health",c.asset_health||"\u2014"],["Note Path",t.note_path||"\u2014"],["Fulltext Path",t.fulltext_path||"\u2014"]],f=new Set(["Note Path","Fulltext Path","Key"]);for(let[p,m]of d){let y=s.createEl("div",{cls:"paperforge-technical-row"});y.createEl("span",{cls:"paperforge-technical-label",text:p});let x=y.createEl("span",{cls:"paperforge-technical-value",text:String(m)});f.has(p)&&m&&m!=="\u2014"&&(x.addClass("pf-copy"),x.addEventListener("click",()=>{navigator.clipboard.writeText(m),new I.Notice(p+" copied")}))}}_renderNextStepCard(e,t,r){var l,c;let n=t.next_step||"ready",a={sync:{label:"Sync Needed",text:"This paper needs to be synced from Zotero. Click to run sync.",cmd:"sync",icon:"\u21BB"},ocr:{label:"OCR Needed",text:"Fulltext is missing but PDF is present. Click to run OCR.",cmd:"ocr",icon:"\u229E"},repair:{label:"Repair Needed",text:"State divergence or path errors detected. Click to repair.",cmd:"repair",icon:"\u21BA"},"rebuild index":{label:"Rebuild Needed",text:"Index may be stale. Click to run sync to rebuild.",cmd:"sync",icon:"\u21BB"},"/pf-deep":{label:"Ready for Deep Reading",text:"Fulltext is ready. Copy /pf-deep command and run in your agent.",cmd:null,icon:"\u{1F50D}"},ready:{label:"All Set",text:"This paper is fully processed and ready for use.",cmd:"ready",icon:"\u2713"}},s=a[n]||a.ready,i=e.createEl("div",{cls:"paperforge-next-step-card"});if(n==="ready"&&i.addClass("ready"),i.createEl("div",{cls:"paperforge-next-step-label",text:"Recommended Next Step"}),i.createEl("div",{cls:"paperforge-next-step-text",text:s.text}),s.cmd&&s.cmd!=="ready"){let d=i.createEl("button",{cls:"paperforge-next-step-trigger"});d.createEl("span",{text:s.icon+" "+s.label}),d.addEventListener("click",()=>{let f=se.find(p=>p.cmd===s.cmd);f&&this._runAction(f,d)})}else if(n==="/pf-deep"){let d=i.createEl("button",{cls:"paperforge-next-step-trigger"});d.createEl("span",{text:"\u{1F4CB} "+o("copy_pf_deep_cmd")}),d.addEventListener("click",()=>{let x="/pf-deep "+r;navigator.clipboard.writeText(x).then(()=>{d.setText("\u2713 "+o("copied")),new I.Notice(x+" copied")}).catch(()=>{new I.Notice("[!!] Clipboard write failed",6e3)})});let f=((c=(l=this.app.plugins.plugins.paperforge)==null?void 0:l.settings)==null?void 0:c.agent_platform)||"opencode",m={opencode:"OpenCode",claude:"Claude Code",cursor:"Cursor",github_copilot:"GitHub Copilot",windsurf:"Windsurf",codex:"Codex",gemini:"Gemini CLI",cline:"Cline"}[f]||f;i.createEl("div",{cls:"paperforge-agent-platform-label"}).setText(o("run_in_agent").replace("{0}",m))}else n==="ready"&&i.createEl("button",{cls:"paperforge-next-step-trigger"}).createEl("span",{text:"\u2713 "+s.label})}_openFulltext(e){if(!e){new I.Notice("[!!] No fulltext path available for this paper",6e3);return}let t=this.app.vault.getAbstractFileByPath(e);t?this.app.workspace.openLinkText(t.path,""):new I.Notice("[!!] Fulltext file not found: "+e,6e3)}_renderCollectionMode(){let e=this._currentDomain||"Unknown",t=this._filterByDomain(e);if(t.length===0){this._renderGlobalMode();return}if(!this._contentEl)return;let r=this._contentEl.createEl("div",{cls:"paperforge-collection-view"}),n=t.length,a=0,s=0,i=0,l=0,c=0,d=0,f=0;for(let g of t){g.has_pdf&&a++,g.ocr_status==="done"&&s++,g.ocr_status==="done"&&g.analyze===!0&&i++,g.deep_reading_status==="done"&&l++;let v=g.ocr_status||"";v==="pending"||v==="queued"?c++:v==="processing"?d++:(v==="failed"||v==="blocked"||v==="done_incomplete"||v==="nopdf")&&f++}r.createEl("div",{cls:"paperforge-collection-header"}).createEl("div",{cls:"paperforge-collection-title",text:e});let m=r.createEl("div",{cls:"paperforge-workflow-overview"});m.createEl("div",{cls:"paperforge-section-label",text:"Workflow Overview"});let y=m.createEl("div",{cls:"paperforge-workflow-funnel"}),x=[{value:n,label:"Total"},{value:a,label:"PDF Ready"},{value:s,label:"OCR Done"},{value:l,label:"Deep Read"}];for(let g=0;g0){let g=r.createEl("div",{cls:"paperforge-ocr-section"}),v=g.createEl("div",{cls:"paperforge-collection-ocr-header"});v.createEl("h4",{cls:"paperforge-ocr-title",text:"OCR Pipeline"});let w=v.createEl("span",{cls:"paperforge-ocr-badge idle"});d>0?(w.addClass("active"),w.setText("Processing")):c>0?w.setText("Pending"):(w.addClass("idle"),w.setText("Idle"));let T=g.createEl("div",{cls:"paperforge-progress-track"});d>0&&T.addClass("paperforge-processing");let P=c+d+s+f,L=[{cls:"pending",count:c},{cls:"active",count:d},{cls:"done",count:s},{cls:"failed",count:f}];for(let q of L)if(q.count>0){let D=(q.count/P*100).toFixed(1);T.createEl("div",{cls:`paperforge-progress-seg ${q.cls}`,attr:{style:`width:${D}%`}})}let O=g.createEl("div",{cls:"paperforge-ocr-counts"}),z=[{cls:"pending",value:c,label:"Pending"},{cls:"active",value:d,label:"Processing"},{cls:"done",value:s,label:"Done"},{cls:"failed",value:f,label:"Attention"}];for(let q of z){let D=O.createEl("div",{cls:"paperforge-ocr-count"});D.createEl("div",{cls:"paperforge-ocr-count-value",text:q.value.toString()}),D.createEl("div",{cls:"paperforge-ocr-count-label",text:q.label})}}let _=r.createEl("div",{cls:"paperforge-collection-actions"}),b=_.createEl("button",{cls:"paperforge-contextual-btn primary"});b.createEl("span",{cls:"paperforge-contextual-btn-icon",text:"\u229E"}),b.createEl("span",{text:"Run OCR"}),b.addEventListener("click",()=>{let g=se.find(v=>v.id==="paperforge-ocr");g&&this._runAction(g,b)});let E=_.createEl("button",{cls:"paperforge-contextual-btn"});E.createEl("span",{cls:"paperforge-contextual-btn-icon",text:"\u21BB"}),E.createEl("span",{text:"Sync Library"}),E.addEventListener("click",()=>{let g=se.find(v=>v.id==="paperforge-sync");g&&this._runAction(g,E)});let k=_.createEl("button",{cls:"paperforge-contextual-btn warn"});k.createEl("span",{cls:"paperforge-contextual-btn-icon",text:"\u21BA"}),k.createEl("span",{text:"Redo OCR"}),k.addEventListener("click",()=>{let g=se.find(v=>v.id==="paperforge-ocr-redo");g&&this._runAction(g,k)}),this.renderSearchSection(r)}_refreshCurrentMode(){if(!(!this._currentMode||!this._contentEl)){this._contentEl.empty(),this._contentEl.addClass("switching"),this._invalidateIndex(),this._currentPaperEntry=this._currentPaperKey?this._findEntry(this._currentPaperKey):null,this._renderModeHeader(this._currentMode);try{switch(this._currentMode){case"global":this._renderGlobalMode();break;case"paper":this._renderPaperMode();break;case"collection":this._renderCollectionMode();break;case"versions":this._renderVersionMode();break}}finally{setTimeout(()=>{this._contentEl&&this._contentEl.removeClass("switching")},50)}}}_switchToVersionMode(e){let r=this.app.vault.adapter.basePath,n=typeof r=="string"?r:"";if(!n){new I.Notice("Cannot determine vault path");return}this._versionPapers=nt(n),this._versionFilter="",this._currentMode="versions",this._currentFilePath=null,this._techDetailsExpanded=!1,this._contentEl&&(this._contentEl.empty(),this._contentEl.removeClass("switching"),this._renderModeHeader("versions"),this._renderVersionMode())}_renderVersionMode(){if(!this._contentEl)return;let e=this._contentEl.createEl("div",{cls:"paperforge-version-panel"}),r=this.app.vault.adapter.basePath,n=typeof r=="string"?r:"";if(!n){e.createEl("div",{cls:"paperforge-status-error",text:"Could not determine vault path"});return}(!this._versionPapers||this._versionPapers.length===0)&&(this._versionPapers=nt(n));let a=e.createEl("div",{cls:"paperforge-version-left"}),s=e.createEl("div",{cls:"paperforge-version-right"}),i=a.createEl("input",{cls:"paperforge-version-filter",attr:{type:"text",placeholder:o("version_filter_placeholder")}});i.value=this._versionFilter;let l=a.createEl("div",{cls:"paperforge-version-paper-list"}),c=()=>{l.empty();let b=this._versionFilter.toLowerCase(),E=this._versionPapers?this._versionPapers.filter(g=>!b||g.key.toLowerCase().includes(b)||g.title.toLowerCase().includes(b)):[];if(E.length===0){l.createEl("div",{cls:"paperforge-meta",text:o("version_no_backups")});return}let k=l.createEl("div",{cls:"paperforge-meta",text:o("version_papers_count").replace("{n}",String(E.length))});for(let g of E){let v=l.createEl("div",{cls:"paperforge-version-paper-item"}),w=v.createEl("span",{cls:"paperforge-version-paper-title",text:g.title}),T=v.createEl("span",{cls:"paperforge-version-paper-versions",text:g.versions.map(P=>P.label).join(" ")});v.addEventListener("click",()=>{l.querySelectorAll(".paperforge-version-paper-item.selected").forEach(P=>P.removeClass("selected")),v.addClass("selected"),f(g)})}};i.addEventListener("input",()=>{this._versionFilter=i.value,c()});let d=s.createEl("div",{cls:"paperforge-version-timeline-area"}),f=b=>{if(d.empty(),d.createEl("div",{cls:"paperforge-version-timeline-header"}).createEl("span",{cls:"pf-title",text:b.title}),b.versions.length===0){d.createEl("div",{cls:"paperforge-meta",text:o("version_no_backups")});return}let k=d.createEl("div",{cls:"paperforge-version-timeline"});for(let g of b.versions){let v=g.label===b.currentLabel,w=k.createEl("div",{cls:"paperforge-version-entry"+(v?" paperforge-version-current":"")}),T=w.createEl("div",{cls:"paperforge-version-dot"}),P=w.createEl("div",{cls:"paperforge-version-content"}),L=P.createEl("div",{cls:"paperforge-version-label-row"});L.createEl("span",{cls:"paperforge-version-label",text:g.label}),v&&L.createEl("span",{cls:"paperforge-version-current-tag",text:o("version_current")});let O=g.created_at?g.created_at.slice(0,10):"";P.createEl("div",{cls:"paperforge-meta",text:O+" \u2014 "+g.source});let z=g.fulltext_size?g.fulltext_size>1024?(g.fulltext_size/1024).toFixed(0)+"KB":g.fulltext_size+"B":"";z&&P.createEl("div",{cls:"paperforge-meta",text:z});let q=P.createEl("div",{cls:"paperforge-version-actions"});q.createEl("button",{cls:"pf-btn-primary",text:o("version_restore_btn")}).addEventListener("click",()=>{Rt(n,b.key,g.label)?new I.Notice(o("version_restore_done").replace("{label}",g.label)):new I.Notice("Restore failed",6e3)}),b.versions.length>1&&!v&&q.createEl("button",{cls:"pf-btn-secondary",text:o("version_compare_btn")}).addEventListener("click",()=>{m(b,g.label,b.currentLabel)})}},p=s.createEl("div",{cls:"paperforge-version-compare"});p.style.display="none";let m=(b,E,k)=>{let g=Tt(n,b.key,E,k);p.style.display="block",p.empty();let v=p.createEl("div",{cls:"paperforge-version-compare-header"});if(v.createEl("span",{cls:"pf-title",text:o("version_compare_title").replace("{vA}",E).replace("{vB}",k)}),v.createEl("span",{cls:"paperforge-meta",text:o("version_compare_paragraphs").replace("{n}",String(g.length))}),g.length===0){p.createEl("div",{cls:"paperforge-meta",text:"No changes"});return}let w=p.createEl("div",{cls:"paperforge-version-diff-list"});for(let T of g){let P=w.createEl("div",{cls:"paperforge-version-diff-row"}),L=T.type==="added"?"[+]":T.type==="removed"?"[-]":"[~]",O=T.heading||"paragraph "+(T.paragraphIndex+1);P.createEl("span",{cls:"paperforge-version-diff-label",text:L+" "+O}),T.oldText&&P.createEl("pre",{cls:"paperforge-version-diff-old",text:T.oldText.slice(0,200)}),T.newText&&P.createEl("pre",{cls:"paperforge-version-diff-new",text:T.newText.slice(0,200)})}},y=e.createEl("div",{cls:"paperforge-version-actions-bar"}),x=y.createEl("button",{cls:"pf-btn-primary",text:o("version_restore_selected")}),_=y.createEl("button",{cls:"pf-btn-secondary",text:o("version_clear_old").replace("{size}","")});c()}renderSearchSection(e){this._searchContainer=e.createEl("div",{cls:"paperforge-search-section"}),this._searchContainer.createEl("div",{cls:"paperforge-search-header"}).createEl("span",{cls:"pf-label",text:"Search"});let r=this._searchContainer.createEl("div",{cls:"paperforge-search-input-row"}),n=r.createEl("span",{cls:"paperforge-search-mode",text:"M"});this._searchInput=r.createEl("input",{cls:"paperforge-search-input",attr:{type:"text",placeholder:"Search papers... (@ for deep search)"}}),this._searchResultsEl=this._searchContainer.createEl("div",{cls:"paperforge-search-results"}),this._searchInput.placeholder=o("retrieval_search_placeholder"),this._searchInput.addEventListener("input",()=>{var s;let a=((s=this._searchInput)==null?void 0:s.value)||"";if(a.startsWith("@")&&!a.startsWith("@ ")?(this._searchMode="@",n.setText("@"),n.addClass("deep"),this._searchInput&&(this._searchInput.placeholder=o("retrieval_search_placeholder_deep"))):(this._searchMode="M",n.setText("M"),n.removeClass("deep"),this._searchInput&&(this._searchInput.placeholder=o("retrieval_search_placeholder"))),clearTimeout(this._searchTimer),!a.trim()){this._searchState="idle",this._searchResults=null,this._searchActiveIndex=-1,this._renderSearchState();return}a.startsWith("@")||(this._searchTimer=setTimeout(()=>{this.executeSearch()},200))}),this._searchInput.addEventListener("keydown",a=>{var s,i;if(a.key==="Escape"){a.preventDefault(),this._searchInput&&(this._searchInput.value="",this._searchInput.blur()),this._searchState="idle",this._searchResults=null,this._searchActiveIndex=-1,this._renderSearchState();return}if(a.key==="ArrowDown"||a.key==="ArrowUp"){if(this._searchState!=="results"||!((s=this._searchResults)!=null&&s.length))return;a.preventDefault();let l=this._searchResults.length;a.key==="ArrowDown"?this._searchActiveIndex=Math.min(this._searchActiveIndex+1,l-1):this._searchActiveIndex=Math.max(this._searchActiveIndex-1,-1);let c=(i=this._searchResultsEl)==null?void 0:i.querySelectorAll(".paperforge-search-result-card");c&&c.forEach((d,f)=>{f===this._searchActiveIndex?(d.setAttribute("aria-selected","true"),d.classList.add("active")):(d.setAttribute("aria-selected","false"),d.classList.remove("active"))});return}if(a.key==="Enter"&&a.ctrlKey){a.preventDefault(),this._searchTimer&&(clearTimeout(this._searchTimer),this._searchTimer=void 0);let l=this._searchMode;this._searchMode="@",this.executeSearch(),this._searchMode=l;return}a.key==="Enter"&&(a.preventDefault(),this._searchTimer&&(clearTimeout(this._searchTimer),this._searchTimer=void 0),this.executeSearch())})}_renderSearchState(){if(!this._searchResultsEl)return;switch(this._searchResultsEl.empty(),this._searchResultsEl.removeAttribute("role"),this._searchResultsEl.removeAttribute("aria-live"),this._searchInput&&(this._searchInput.disabled=!1),this._searchState){case"idle":break;case"searching":{let t=this._searchMode==="@";this._searchResultsEl.createEl("div",{cls:"paperforge-search-loading",text:t?o("retrieval_searching_deep"):o("retrieval_searching_metadata")}),this._searchResultsEl.setAttr("aria-live","polite"),t&&this._searchInput&&(this._searchInput.disabled=!0);break}case"results":{this._searchResultsEl.setAttr("role","listbox"),this._searchResultsEl.setAttr("aria-live","polite"),this._searchResults&&this._renderSearchResultsList(this._searchResults,this._searchMode==="@"),setTimeout(()=>{var r;let t=(r=this._searchResultsEl)==null?void 0:r.querySelector(".paperforge-search-result-card");t&&t instanceof HTMLElement&&t.focus()},100);break}case"empty":{let t=this._searchResultsEl.createEl("div",{cls:"paperforge-search-empty"});t.setAttr("role","alert"),t.createEl("div",{text:o("retrieval_empty")}),t.createEl("div",{cls:"paperforge-search-empty-tips",text:o("retrieval_empty_tips")});break}case"vectors-not-built":{let t=this._searchResultsEl.createEl("div",{cls:"paperforge-search-state-card",attr:{role:"alert"}});t.addClass("warning-soft"),t.createEl("div",{cls:"paperforge-search-state-title",text:o("retrieval_vectors_not_built")}),t.createEl("div",{cls:"paperforge-search-state-desc",text:o("retrieval_vectors_not_built_desc")});let r=t.createEl("button",{cls:"pf-btn-link",text:o("retrieval_open_vector_settings")});r.addEventListener("click",()=>{let n=this.app.setting;if(n&&typeof n=="object"){let a=n.openTab;typeof a=="function"&&a.call(n,"paperforge")}}),setTimeout(()=>{r.focus()},100);break}case"backend-unavailable":{let t=this._searchResultsEl.createEl("div",{cls:"paperforge-search-state-card",attr:{role:"alert"}});t.addClass("error-soft"),t.createEl("div",{cls:"paperforge-search-state-title",text:o("retrieval_backend_unavailable")}),t.createEl("div",{cls:"paperforge-search-state-desc",text:o("retrieval_backend_unavailable_desc")});let r=t.createEl("div",{cls:"paperforge-search-state-actions"}),n=r.createEl("button",{cls:"pf-btn-primary",text:o("retrieval_run_doctor")});n.addEventListener("click",()=>{let s=this.app.vault.adapter.basePath;if(typeof s=="string"){let{path:i,extraArgs:l=[]}=N(s,null,void 0,void 0);(0,_e.spawn)(i,[...l,"-m","paperforge","doctor"],{cwd:s,stdio:"inherit"})}}),r.createEl("button",{cls:"pf-btn-secondary",text:o("retrieval_retry")}).addEventListener("click",()=>{this.executeSearch()}),setTimeout(()=>{n.focus()},100);break}case"timeout":{let t=this._searchResultsEl.createEl("div",{cls:"paperforge-search-state-card",attr:{role:"alert"}});t.addClass("warning-soft"),t.createEl("div",{cls:"paperforge-search-state-title",text:o("retrieval_timeout_title")}),t.createEl("div",{cls:"paperforge-search-state-desc",text:o("retrieval_timeout_desc")});let r=t.createEl("button",{cls:"pf-btn-primary",text:o("retrieval_retry")});r.addEventListener("click",()=>{this.executeSearch()}),setTimeout(()=>{r.focus()},100);break}case"model-changed":{let t=this._searchResultsEl.createEl("div",{cls:"paperforge-search-state-card",attr:{role:"alert"}});t.addClass("warning-soft"),t.createEl("div",{cls:"paperforge-search-state-title",text:o("retrieval_model_changed")}),t.createEl("div",{cls:"paperforge-search-state-desc",text:o("retrieval_model_changed_desc")});let r=t.createEl("button",{cls:"pf-btn-primary",text:o("retrieval_rebuild_vectors")});r.addEventListener("click",()=>{let n=this.app.setting;if(n&&typeof n=="object"){let a=n.openTab;typeof a=="function"&&a.call(n,"paperforge")}}),setTimeout(()=>{r.focus()},100);break}default:{this._searchResultsEl.createEl("div",{cls:"paperforge-search-state-card",text:o("retrieval_internal_error"),attr:{role:"alert"}}).addClass("error-soft"),setTimeout(()=>{this._searchInput&&this._searchInput.focus()},100);break}}}async executeSearch(){if(!this._searchInput||!this._searchResultsEl)return;let e=this._searchInput.value.trim();if(!e)return;let t=this._searchMode==="@"||e.startsWith("@"),r=t?e.replace(/^@\s*/,"").trim():e;if(!r)return;let n=t?"retrieve":"search";this._searchState="searching",this._searchResults=null,this._searchActiveIndex=-1,this._renderSearchState();let a=this.app.vault.adapter,s="";if(a&&typeof a=="object"&&"basePath"in a){let x=a.basePath;s=typeof x=="string"?x:""}if(!s){this._searchState="backend-unavailable",this._renderSearchState();return}let i=null,c=this.app.plugins;if(c&&typeof c=="object"&&"plugins"in c){let x=c.plugins;if(x&&typeof x=="object"&&"paperforge"in x){let _=x.paperforge;_&&typeof _=="object"&&"settings"in _&&(i=_.settings)}}let{path:d,extraArgs:f=[]}=N(s,i,void 0,void 0),p=n==="retrieve"?["--deep"]:[],m=(0,_e.spawn)(d,[...f,"-m","paperforge",n,r,...p,"--json"],{cwd:s,timeout:3e4}),y=[];m.stdout.on("data",x=>{y.push(x.toString("utf-8"))}),m.stderr.on("data",()=>{}),m.on("close",x=>{if(x!==0){let g=Xe(String(x));this._searchState=this._mapErrorToSearchState(g.type),this._renderSearchState();return}let _=y.join(""),b=_.indexOf("{"),E=_.lastIndexOf("}"),k="";if(b!==-1&&E>b)k=_.slice(b,E+1);else{let g=_.indexOf("["),v=_.lastIndexOf("]");g!==-1&&v>g&&(k=_.slice(g,v+1))}if(!k){this._searchState="internal-error",this._renderSearchState();return}try{let g=JSON.parse(k),v=[];if(g&&typeof g=="object"&&"data"in g){let w=g.data;if(w&&typeof w=="object"){let T=w;"matches"in T&&Array.isArray(T.matches)&&(v=T.matches)}}this._searchResults=v,this._searchState=v.length>0?"results":"empty",this._renderSearchState()}catch(g){let v=g instanceof Error?g.message:String(g);this._searchState="internal-error",this._renderSearchState()}}),m.on("error",x=>{let _=x.code;if(typeof _=="string"){let b=Xe(_);this._searchState=this._mapErrorToSearchState(b.type)}else this._searchState="backend-unavailable";this._renderSearchState()})}_mapErrorToSearchState(e){switch(e){case"vectors_not_built":return"vectors-not-built";case"vectors_corrupted":return"vectors-not-built";case"backend_unavailable":return"backend-unavailable";case"model_changed":return"model-changed";case"timeout":return"timeout";case"no_python":case"python_missing":case"import_failed":case"version_mismatch":return"backend-unavailable";default:return"backend-unavailable"}}_renderSearchResultsList(e,t){if(!this._searchResultsEl)return;if(this._searchResultsEl.setAttr("aria-live","polite"),e.length===0){this._searchResultsEl.createEl("div",{cls:"paperforge-search-empty",text:"No results found."});return}let r=this._searchResultsEl.createEl("div",{cls:"paperforge-search-results-header"});r.createEl("span",{text:o("retrieval_results_count").replace("{n}",String(e.length)).replace("{s}",e.length!==1?"s":"")}).setAttr("aria-live","polite"),r.createEl("span",{cls:"paperforge-search-mode",text:t?"@":"M"});for(let a=0;aE!==null&&typeof E=="object"&&"zotero_key"in E&&E.zotero_key===f);if(b&&typeof b=="object"){let E=b;y=typeof E.main_note_path=="string"&&E.main_note_path?E.main_note_path:typeof E.note_path=="string"&&E.note_path?E.note_path:null}}y?c.addEventListener("click",_=>{let b=_.ctrlKey||_.metaKey;this.app.workspace.openLinkText(y,"",b)}):c.addEventListener("click",()=>{new I.Notice("[!!] Note not found: "+(f||"unknown"),6e3)}),c.addEventListener("keydown",_=>{if(_.key==="Enter"&&y){_.preventDefault();let b=_.ctrlKey||_.metaKey;this.app.workspace.openLinkText(y,"",b)}});let x=c.createEl("div",{cls:"paperforge-search-result-meta"});if(typeof i.first_author=="string"&&i.first_author&&x.createEl("span",{cls:"paperforge-search-result-author",text:i.first_author}),typeof i.journal=="string"&&i.journal&&x.createEl("span",{cls:"paperforge-search-result-journal",text:i.journal}),i.score!==void 0){let _=i.score,b=typeof _=="number"?_.toFixed(3):String(_);x.createEl("span",{cls:"paperforge-search-result-score",text:"Score: "+b})}if(typeof i.domain=="string"&&i.domain&&c.createEl("span",{cls:"paperforge-search-result-tag",text:i.domain}),typeof i.abstract=="string"&&i.abstract){let _=i.abstract;c.createEl("div",{cls:"paperforge-search-result-abstract",text:_.length>200?_.slice(0,200)+"...":_})}if(t&&typeof i.text=="string"&&i.text){let _=i.text;c.createEl("div",{cls:"paperforge-search-result-source",text:_.length>300?_.slice(0,300)+"...":_})}}}_renderSearchError(e){this._searchResultsEl&&(this._searchResultsEl.empty(),this._searchResultsEl.createEl("div",{cls:"paperforge-search-error",text:e}))}_runAction(e,t){var p,m;if(e.disabled){new I.Notice(`[i] ${e.disabledMsg||"This action is not yet available."}`,6e3);return}if(t.classList.contains("running"))return;t.addClass("running");let r=this.app.vault.adapter.basePath;this._showMessage("Processing...","running");let n=Array.isArray(e.args)?[...e.args]:[];if(e.needsKey){let y=this.app.workspace.getActiveFile(),x=null;if(y){let _=this.app.metadataCache.getFileCache(y);if(_&&_.frontmatter&&_.frontmatter.zotero_key?x=_.frontmatter.zotero_key:x=this._extractZoteroKeyFromPath(y.path),x)n=[...n,x];else if(_&&_.frontmatter){this._showMessage("[!!] No zotero_key in active note frontmatter","error"),new I.Notice("[!!] Open a paper note with a zotero_key in its frontmatter first",6e3),t.removeClass("running");return}else{this._showMessage("[!!] No frontmatter in active note","error"),new I.Notice("[!!] The active note has no frontmatter with a zotero_key",6e3),t.removeClass("running");return}}else{this._showMessage("[!!] No active note open","error"),new I.Notice("[!!] Open a paper note with a zotero_key in its frontmatter first",6e3),t.removeClass("running");return}}e.needsFilter&&(n=[...n,"--all"]);let a=e.needsFilter?6e4:e.needsKey?3e4:6e5,{path:s,extraArgs:i=[]}=N(r,(m=(p=this.app.plugins.plugins.paperforge)==null?void 0:p.settings)!=null?m:null,void 0,void 0),l=(0,_e.spawn)(s,[...i,"-m","paperforge",e.cmd,...n],{cwd:r,timeout:a}),c=[],d=Date.now(),f=setInterval(()=>this._fetchStats(!0),4e3);l.stdout.on("data",y=>{let x=y.toString("utf-8").split(` +`)[0].trim();return!s||s.startsWith("###")||s.startsWith("##")?null:s.length>300?s.slice(0,300)+"...":s}_renderRecentDiscussionCard(e,t){let r=e.createEl("div",{cls:"paperforge-discussion-card"});if(r.style.display="none",!t.note_path)return;let n=t.note_path.lastIndexOf("/"),s=(n!==-1?t.note_path.substring(0,n):".")+"/ai/discussion.md";this.app.vault.adapter.exists(s).then(i=>{if(i)return this.app.vault.adapter.read(s)}).then(async i=>{if(!i)return;let l=this._parseDiscussionMD(i);if(!l||l.length===0)return;r.style.display="block",r.createEl("div",{cls:"paperforge-discussion-header"}).createEl("span",{cls:"paperforge-discussion-title",text:"\u6700\u8FD1\u8BA8\u8BBA"});for(let f of l){let p=r.createEl("div",{cls:"paperforge-discussion-item"}),m=p.createEl("div",{cls:"paperforge-discussion-q"});m.createEl("span",{cls:"paperforge-discussion-q-label",text:"\u63D0\u95EE\uFF1A"}),m.createEl("span",{cls:"paperforge-discussion-q-text",text:f.question});let y=p.createEl("div",{cls:"paperforge-discussion-a"}),x=!1;if(f.answer&&f.answer.length>500&&(x=!0,y.classList.add("paperforge-discussion-a-collapsed")),await I.MarkdownRenderer.render(this.app,f.answer||"",y,s,this),x){let _=!1;p.style.cursor="pointer",p.addEventListener("click",()=>{_=!_,y.classList.toggle("paperforge-discussion-a-collapsed",!_),y.classList.toggle("paperforge-discussion-a-expanded",_)})}}r.createEl("a",{cls:"paperforge-discussion-viewall",text:"\u67E5\u770B\u5168\u90E8\u8BA8\u8BBA \u2192"}).addEventListener("click",f=>{f.preventDefault(),this.app.vault.getAbstractFileByPath(s)?this.app.workspace.openLinkText(s,""):new I.Notice("\u8BA8\u8BBA\u6587\u4EF6\u5C1A\u672A\u751F\u6210")})}).catch(i=>{console.error("PaperForge: discussion.md read error",s,i.message)})}_parseDiscussionMD(e){let t=e.split(/\n## /).slice(1);if(t.length===0)return null;let r=t[t.length-1],n=[],a=r.split(/\*\*\u95EE\u9898:\*\*/).slice(1);for(let s of a){let i=s.match(/\*\*\u89E3\u7B54:\*\*/);if(!i)continue;let l=s.substring(0,i.index).trim(),c=s.substring(i.index+3+4).trim();n.push({question:l,answer:c})}return n.slice(-3)}_renderPaperTechnicalDetails(e,t){let r=this._currentPaperKey,n=e.createEl("div",{cls:"paperforge-technical-details"}),a=n.createEl("button",{cls:"paperforge-technical-details-toggle"}),s=n.createEl("div",{cls:"paperforge-technical-details-body"});s.style.display="none",this._techDetailsExpanded?(s.style.display="block",a.setText("\u6280\u672F\u8BE6\u60C5 \u25BE")):a.setText("\u6280\u672F\u8BE6\u60C5 \u25B8"),a.addEventListener("click",()=>{let p=s.style.display!=="none";s.style.display=p?"none":"block",a.setText(p?"\u6280\u672F\u8BE6\u60C5 \u25B8":"\u6280\u672F\u8BE6\u60C5 \u25BE"),this._techDetailsExpanded=!p});let i=s.createEl("div",{cls:"paperforge-workflow-toggles"}),l=[{key:"do_ocr",label:"OCR",hint:"\u52A0\u5165 OCR"},{key:"analyze",label:"\u7CBE\u8BFB",hint:"\u6807\u8BB0\u7CBE\u8BFB"}];for(let p of l){let m=i.createEl("label",{cls:"paperforge-workflow-toggle"}),y=m.createEl("input",{type:"checkbox",cls:"paperforge-workflow-checkbox"});y.checked=t[p.key]===!0,m.createEl("span",{cls:"paperforge-workflow-toggle-label",text:p.label}),m.createEl("span",{cls:"paperforge-workflow-toggle-hint",text:p.hint}),y.addEventListener("change",async()=>{let x=t.note_path?this.app.vault.getAbstractFileByPath(t.note_path):null;if(!x){new I.Notice("[!!] Note file not found",6e3);return}let _=y.checked;await this.app.fileManager.processFrontMatter(x,b=>{b[p.key]=_}),this._patchCachedEntry(r,{[p.key]:_}),this._currentPaperEntry=Ze(this._currentPaperEntry,{[p.key]:_})})}let c=t.health||{},d=[["PDF Health",c.pdf_health||"\u2014"],["OCR Status",t.ocr_status||"\u2014"],["Asset Health",c.asset_health||"\u2014"],["Note Path",t.note_path||"\u2014"],["Fulltext Path",t.fulltext_path||"\u2014"]],f=new Set(["Note Path","Fulltext Path","Key"]);for(let[p,m]of d){let y=s.createEl("div",{cls:"paperforge-technical-row"});y.createEl("span",{cls:"paperforge-technical-label",text:p});let x=y.createEl("span",{cls:"paperforge-technical-value",text:String(m)});f.has(p)&&m&&m!=="\u2014"&&(x.addClass("pf-copy"),x.addEventListener("click",()=>{navigator.clipboard.writeText(m),new I.Notice(p+" copied")}))}}_renderNextStepCard(e,t,r){var l,c;let n=t.next_step||"ready",a={sync:{label:"Sync Needed",text:"This paper needs to be synced from Zotero. Click to run sync.",cmd:"sync",icon:"\u21BB"},ocr:{label:"OCR Needed",text:"Fulltext is missing but PDF is present. Click to run OCR.",cmd:"ocr",icon:"\u229E"},repair:{label:"Repair Needed",text:"State divergence or path errors detected. Click to repair.",cmd:"repair",icon:"\u21BA"},"rebuild index":{label:"Rebuild Needed",text:"Index may be stale. Click to run sync to rebuild.",cmd:"sync",icon:"\u21BB"},"/pf-deep":{label:"Ready for Deep Reading",text:"Fulltext is ready. Copy /pf-deep command and run in your agent.",cmd:null,icon:"\u{1F50D}"},ready:{label:"All Set",text:"This paper is fully processed and ready for use.",cmd:"ready",icon:"\u2713"}},s=a[n]||a.ready,i=e.createEl("div",{cls:"paperforge-next-step-card"});if(n==="ready"&&i.addClass("ready"),i.createEl("div",{cls:"paperforge-next-step-label",text:"Recommended Next Step"}),i.createEl("div",{cls:"paperforge-next-step-text",text:s.text}),s.cmd&&s.cmd!=="ready"){let d=i.createEl("button",{cls:"paperforge-next-step-trigger"});d.createEl("span",{text:s.icon+" "+s.label}),d.addEventListener("click",()=>{let f=se.find(p=>p.cmd===s.cmd);f&&this._runAction(f,d)})}else if(n==="/pf-deep"){let d=i.createEl("button",{cls:"paperforge-next-step-trigger"});d.createEl("span",{text:"\u{1F4CB} "+o("copy_pf_deep_cmd")}),d.addEventListener("click",()=>{let x="/pf-deep "+r;navigator.clipboard.writeText(x).then(()=>{d.setText("\u2713 "+o("copied")),new I.Notice(x+" copied")}).catch(()=>{new I.Notice("[!!] Clipboard write failed",6e3)})});let f=((c=(l=this.app.plugins.plugins.paperforge)==null?void 0:l.settings)==null?void 0:c.agent_platform)||"opencode",m={opencode:"OpenCode",claude:"Claude Code",cursor:"Cursor",github_copilot:"GitHub Copilot",windsurf:"Windsurf",codex:"Codex",gemini:"Gemini CLI",cline:"Cline"}[f]||f;i.createEl("div",{cls:"paperforge-agent-platform-label"}).setText(o("run_in_agent").replace("{0}",m))}else n==="ready"&&i.createEl("button",{cls:"paperforge-next-step-trigger"}).createEl("span",{text:"\u2713 "+s.label})}_openFulltext(e){if(!e){new I.Notice("[!!] No fulltext path available for this paper",6e3);return}let t=this.app.vault.getAbstractFileByPath(e);t?this.app.workspace.openLinkText(t.path,""):new I.Notice("[!!] Fulltext file not found: "+e,6e3)}_renderCollectionMode(){let e=this._currentDomain||"Unknown",t=this._filterByDomain(e);if(t.length===0){this._renderGlobalMode();return}if(!this._contentEl)return;let r=this._contentEl.createEl("div",{cls:"paperforge-collection-view"}),n=t.length,a=0,s=0,i=0,l=0,c=0,d=0,f=0;for(let g of t){g.has_pdf&&a++,g.ocr_status==="done"&&s++,g.ocr_status==="done"&&g.analyze===!0&&i++,g.deep_reading_status==="done"&&l++;let v=g.ocr_status||"";v==="pending"||v==="queued"?c++:v==="processing"?d++:(v==="failed"||v==="blocked"||v==="done_incomplete"||v==="nopdf")&&f++}r.createEl("div",{cls:"paperforge-collection-header"}).createEl("div",{cls:"paperforge-collection-title",text:e});let m=r.createEl("div",{cls:"paperforge-workflow-overview"});m.createEl("div",{cls:"paperforge-section-label",text:"Workflow Overview"});let y=m.createEl("div",{cls:"paperforge-workflow-funnel"}),x=[{value:n,label:"Total"},{value:a,label:"PDF Ready"},{value:s,label:"OCR Done"},{value:l,label:"Deep Read"}];for(let g=0;g0){let g=r.createEl("div",{cls:"paperforge-ocr-section"}),v=g.createEl("div",{cls:"paperforge-collection-ocr-header"});v.createEl("h4",{cls:"paperforge-ocr-title",text:"OCR Pipeline"});let w=v.createEl("span",{cls:"paperforge-ocr-badge idle"});d>0?(w.addClass("active"),w.setText("Processing")):c>0?w.setText("Pending"):(w.addClass("idle"),w.setText("Idle"));let T=g.createEl("div",{cls:"paperforge-progress-track"});d>0&&T.addClass("paperforge-processing");let P=c+d+s+f,L=[{cls:"pending",count:c},{cls:"active",count:d},{cls:"done",count:s},{cls:"failed",count:f}];for(let q of L)if(q.count>0){let D=(q.count/P*100).toFixed(1);T.createEl("div",{cls:`paperforge-progress-seg ${q.cls}`,attr:{style:`width:${D}%`}})}let O=g.createEl("div",{cls:"paperforge-ocr-counts"}),z=[{cls:"pending",value:c,label:"Pending"},{cls:"active",value:d,label:"Processing"},{cls:"done",value:s,label:"Done"},{cls:"failed",value:f,label:"Attention"}];for(let q of z){let D=O.createEl("div",{cls:"paperforge-ocr-count"});D.createEl("div",{cls:"paperforge-ocr-count-value",text:q.value.toString()}),D.createEl("div",{cls:"paperforge-ocr-count-label",text:q.label})}}let _=r.createEl("div",{cls:"paperforge-collection-actions"}),b=_.createEl("button",{cls:"paperforge-contextual-btn primary"});b.createEl("span",{cls:"paperforge-contextual-btn-icon",text:"\u229E"}),b.createEl("span",{text:"Run OCR"}),b.addEventListener("click",()=>{let g=se.find(v=>v.id==="paperforge-ocr");g&&this._runAction(g,b)});let E=_.createEl("button",{cls:"paperforge-contextual-btn"});E.createEl("span",{cls:"paperforge-contextual-btn-icon",text:"\u21BB"}),E.createEl("span",{text:"Sync Library"}),E.addEventListener("click",()=>{let g=se.find(v=>v.id==="paperforge-sync");g&&this._runAction(g,E)});let k=_.createEl("button",{cls:"paperforge-contextual-btn warn"});k.createEl("span",{cls:"paperforge-contextual-btn-icon",text:"\u21BA"}),k.createEl("span",{text:"Redo OCR"}),k.addEventListener("click",()=>{let g=se.find(v=>v.id==="paperforge-ocr-redo");g&&this._runAction(g,k)}),this.renderSearchSection(r)}_refreshCurrentMode(){if(!(!this._currentMode||!this._contentEl)){this._contentEl.empty(),this._contentEl.addClass("switching"),this._invalidateIndex(),this._currentPaperEntry=this._currentPaperKey?this._findEntry(this._currentPaperKey):null,this._renderModeHeader(this._currentMode);try{switch(this._currentMode){case"global":this._renderGlobalMode();break;case"paper":this._renderPaperMode();break;case"collection":this._renderCollectionMode();break;case"versions":this._renderVersionMode();break}}finally{setTimeout(()=>{this._contentEl&&this._contentEl.removeClass("switching")},50)}}}_switchToVersionMode(e){let r=this.app.vault.adapter.basePath,n=typeof r=="string"?r:"";if(!n){new I.Notice("Cannot determine vault path");return}this._versionPapers=nt(n),this._versionFilter="",this._currentMode="versions",this._currentFilePath=null,this._techDetailsExpanded=!1,this._contentEl&&(this._contentEl.empty(),this._contentEl.removeClass("switching"),this._renderModeHeader("versions"),this._renderVersionMode())}_renderVersionMode(){if(!this._contentEl)return;let e=this._contentEl.createEl("div",{cls:"paperforge-version-panel"}),r=this.app.vault.adapter.basePath,n=typeof r=="string"?r:"";if(!n){e.createEl("div",{cls:"paperforge-status-error",text:"Could not determine vault path"});return}(!this._versionPapers||this._versionPapers.length===0)&&(this._versionPapers=nt(n));let a=e.createEl("div",{cls:"paperforge-version-left"}),s=e.createEl("div",{cls:"paperforge-version-right"}),i=a.createEl("input",{cls:"paperforge-version-filter",attr:{type:"text",placeholder:o("version_filter_placeholder")}});i.value=this._versionFilter;let l=a.createEl("div",{cls:"paperforge-version-paper-list"}),c=()=>{l.empty();let b=this._versionFilter.toLowerCase(),E=this._versionPapers?this._versionPapers.filter(g=>!b||g.key.toLowerCase().includes(b)||g.title.toLowerCase().includes(b)):[];if(E.length===0){l.createEl("div",{cls:"paperforge-meta",text:o("version_no_backups")});return}let k=l.createEl("div",{cls:"paperforge-meta",text:o("version_papers_count").replace("{n}",String(E.length))});for(let g of E){let v=l.createEl("div",{cls:"paperforge-version-paper-item"}),w=v.createEl("span",{cls:"paperforge-version-paper-title",text:g.title}),T=v.createEl("span",{cls:"paperforge-version-paper-versions",text:g.versions.map(P=>P.label).join(" ")});v.addEventListener("click",()=>{l.querySelectorAll(".paperforge-version-paper-item.selected").forEach(P=>P.removeClass("selected")),v.addClass("selected"),f(g)})}};i.addEventListener("input",()=>{this._versionFilter=i.value,c()});let d=s.createEl("div",{cls:"paperforge-version-timeline-area"}),f=b=>{if(d.empty(),d.createEl("div",{cls:"paperforge-version-timeline-header"}).createEl("span",{cls:"pf-title",text:b.title}),b.versions.length===0){d.createEl("div",{cls:"paperforge-meta",text:o("version_no_backups")});return}let k=d.createEl("div",{cls:"paperforge-version-timeline"});for(let g of b.versions){let v=g.label===b.currentLabel,w=k.createEl("div",{cls:"paperforge-version-entry"+(v?" paperforge-version-current":"")}),T=w.createEl("div",{cls:"paperforge-version-dot"}),P=w.createEl("div",{cls:"paperforge-version-content"}),L=P.createEl("div",{cls:"paperforge-version-label-row"});L.createEl("span",{cls:"paperforge-version-label",text:g.label}),v&&L.createEl("span",{cls:"paperforge-version-current-tag",text:o("version_current")});let O=g.created_at?g.created_at.slice(0,10):"";P.createEl("div",{cls:"paperforge-meta",text:O+" \u2014 "+g.source});let z=g.fulltext_size?g.fulltext_size>1024?(g.fulltext_size/1024).toFixed(0)+"KB":g.fulltext_size+"B":"";z&&P.createEl("div",{cls:"paperforge-meta",text:z});let q=P.createEl("div",{cls:"paperforge-version-actions"});q.createEl("button",{cls:"pf-btn-primary",text:o("version_restore_btn")}).addEventListener("click",()=>{Rt(n,b.key,g.label)?new I.Notice(o("version_restore_done").replace("{label}",g.label)):new I.Notice("Restore failed",6e3)}),b.versions.length>1&&!v&&q.createEl("button",{cls:"pf-btn-secondary",text:o("version_compare_btn")}).addEventListener("click",()=>{m(b,g.label,b.currentLabel)})}},p=s.createEl("div",{cls:"paperforge-version-compare"});p.style.display="none";let m=(b,E,k)=>{let g=Tt(n,b.key,E,k);p.style.display="block",p.empty();let v=p.createEl("div",{cls:"paperforge-version-compare-header"});if(v.createEl("span",{cls:"pf-title",text:o("version_compare_title").replace("{vA}",E).replace("{vB}",k)}),v.createEl("span",{cls:"paperforge-meta",text:o("version_compare_paragraphs").replace("{n}",String(g.length))}),g.length===0){p.createEl("div",{cls:"paperforge-meta",text:"No changes"});return}let w=p.createEl("div",{cls:"paperforge-version-diff-list"});for(let T of g){let P=w.createEl("div",{cls:"paperforge-version-diff-row"}),L=T.type==="added"?"[+]":T.type==="removed"?"[-]":"[~]",O=T.heading||"paragraph "+(T.paragraphIndex+1);P.createEl("span",{cls:"paperforge-version-diff-label",text:L+" "+O}),T.oldText&&P.createEl("pre",{cls:"paperforge-version-diff-old",text:T.oldText.slice(0,200)}),T.newText&&P.createEl("pre",{cls:"paperforge-version-diff-new",text:T.newText.slice(0,200)})}},y=e.createEl("div",{cls:"paperforge-version-actions-bar"}),x=y.createEl("button",{cls:"pf-btn-primary",text:o("version_restore_selected")}),_=y.createEl("button",{cls:"pf-btn-secondary",text:o("version_clear_old").replace("{size}","")});c()}renderSearchSection(e){this._searchContainer=e.createEl("div",{cls:"paperforge-search-section"}),this._searchContainer.createEl("div",{cls:"paperforge-search-header"}).createEl("span",{cls:"pf-label",text:"Search"});let r=this._searchContainer.createEl("div",{cls:"paperforge-search-input-row"}),n=r.createEl("span",{cls:"paperforge-search-mode",text:"M"});this._searchInput=r.createEl("input",{cls:"paperforge-search-input",attr:{type:"text",placeholder:"Search papers... (@ for deep search)"}}),this._searchResultsEl=this._searchContainer.createEl("div",{cls:"paperforge-search-results"}),this._searchInput.placeholder=o("retrieval_search_placeholder"),this._searchInput.addEventListener("input",()=>{var s;let a=((s=this._searchInput)==null?void 0:s.value)||"";if(a.startsWith("@")&&!a.startsWith("@ ")?(this._searchMode="@",n.setText("@"),n.addClass("deep"),this._searchInput&&(this._searchInput.placeholder=o("retrieval_search_placeholder_deep"))):(this._searchMode="M",n.setText("M"),n.removeClass("deep"),this._searchInput&&(this._searchInput.placeholder=o("retrieval_search_placeholder"))),clearTimeout(this._searchTimer),!a.trim()){this._searchState="idle",this._searchResults=null,this._searchActiveIndex=-1,this._renderSearchState();return}a.startsWith("@")||(this._searchTimer=setTimeout(()=>{this.executeSearch()},200))}),this._searchInput.addEventListener("keydown",a=>{var s,i;if(a.key==="Escape"){a.preventDefault(),this._searchInput&&(this._searchInput.value="",this._searchInput.blur()),this._searchState="idle",this._searchResults=null,this._searchActiveIndex=-1,this._renderSearchState();return}if(a.key==="ArrowDown"||a.key==="ArrowUp"){if(this._searchState!=="results"||!((s=this._searchResults)!=null&&s.length))return;a.preventDefault();let l=this._searchResults.length;a.key==="ArrowDown"?this._searchActiveIndex=Math.min(this._searchActiveIndex+1,l-1):this._searchActiveIndex=Math.max(this._searchActiveIndex-1,-1);let c=(i=this._searchResultsEl)==null?void 0:i.querySelectorAll(".paperforge-search-result-card");c&&c.forEach((d,f)=>{f===this._searchActiveIndex?(d.setAttribute("aria-selected","true"),d.classList.add("active")):(d.setAttribute("aria-selected","false"),d.classList.remove("active"))});return}if(a.key==="Enter"&&a.ctrlKey){a.preventDefault(),this._searchTimer&&(clearTimeout(this._searchTimer),this._searchTimer=void 0);let l=this._searchMode;this._searchMode="@",this.executeSearch(),this._searchMode=l;return}a.key==="Enter"&&(a.preventDefault(),this._searchTimer&&(clearTimeout(this._searchTimer),this._searchTimer=void 0),this.executeSearch())})}_renderSearchState(){if(!this._searchResultsEl)return;switch(this._searchResultsEl.empty(),this._searchResultsEl.removeAttribute("role"),this._searchResultsEl.removeAttribute("aria-live"),this._searchInput&&(this._searchInput.disabled=!1),this._searchState){case"idle":break;case"searching":{let t=this._searchMode==="@";this._searchResultsEl.createEl("div",{cls:"paperforge-search-loading",text:t?o("retrieval_searching_deep"):o("retrieval_searching_metadata")}),this._searchResultsEl.setAttr("aria-live","polite"),t&&this._searchInput&&(this._searchInput.disabled=!0);break}case"results":{this._searchResultsEl.setAttr("role","listbox"),this._searchResultsEl.setAttr("aria-live","polite"),this._searchResults&&this._renderSearchResultsList(this._searchResults,this._searchMode==="@"),setTimeout(()=>{var r;let t=(r=this._searchResultsEl)==null?void 0:r.querySelector(".paperforge-search-result-card");t&&t instanceof HTMLElement&&t.focus()},100);break}case"empty":{let t=this._searchResultsEl.createEl("div",{cls:"paperforge-search-empty"});t.setAttr("role","alert"),t.createEl("div",{text:o("retrieval_empty")}),t.createEl("div",{cls:"paperforge-search-empty-tips",text:o("retrieval_empty_tips")});break}case"vectors-not-built":{let t=this._searchResultsEl.createEl("div",{cls:"paperforge-search-state-card",attr:{role:"alert"}});t.addClass("warning-soft"),t.createEl("div",{cls:"paperforge-search-state-title",text:o("retrieval_vectors_not_built")}),t.createEl("div",{cls:"paperforge-search-state-desc",text:o("retrieval_vectors_not_built_desc")});let r=t.createEl("button",{cls:"pf-btn-link",text:o("retrieval_open_vector_settings")});r.addEventListener("click",()=>{let n=this.app.setting;if(n&&typeof n=="object"){let a=n.openTab;typeof a=="function"&&a.call(n,"paperforge")}}),setTimeout(()=>{r.focus()},100);break}case"backend-unavailable":{let t=this._searchResultsEl.createEl("div",{cls:"paperforge-search-state-card",attr:{role:"alert"}});t.addClass("error-soft"),t.createEl("div",{cls:"paperforge-search-state-title",text:o("retrieval_backend_unavailable")}),t.createEl("div",{cls:"paperforge-search-state-desc",text:o("retrieval_backend_unavailable_desc")});let r=t.createEl("div",{cls:"paperforge-search-state-actions"}),n=r.createEl("button",{cls:"pf-btn-primary",text:o("retrieval_run_doctor")});n.addEventListener("click",()=>{let s=this.app.vault.adapter.basePath;if(typeof s=="string"){let{path:i,extraArgs:l=[]}=N(s,null,void 0,void 0);(0,_e.spawn)(i,[...l,"-m","paperforge","doctor"],{cwd:s,stdio:"inherit"})}}),r.createEl("button",{cls:"pf-btn-secondary",text:o("retrieval_retry")}).addEventListener("click",()=>{this.executeSearch()}),setTimeout(()=>{n.focus()},100);break}case"timeout":{let t=this._searchResultsEl.createEl("div",{cls:"paperforge-search-state-card",attr:{role:"alert"}});t.addClass("warning-soft"),t.createEl("div",{cls:"paperforge-search-state-title",text:o("retrieval_timeout_title")}),t.createEl("div",{cls:"paperforge-search-state-desc",text:o("retrieval_timeout_desc")});let r=t.createEl("button",{cls:"pf-btn-primary",text:o("retrieval_retry")});r.addEventListener("click",()=>{this.executeSearch()}),setTimeout(()=>{r.focus()},100);break}case"model-changed":{let t=this._searchResultsEl.createEl("div",{cls:"paperforge-search-state-card",attr:{role:"alert"}});t.addClass("warning-soft"),t.createEl("div",{cls:"paperforge-search-state-title",text:o("retrieval_model_changed")}),t.createEl("div",{cls:"paperforge-search-state-desc",text:o("retrieval_model_changed_desc")});let r=t.createEl("button",{cls:"pf-btn-primary",text:o("retrieval_rebuild_vectors")});r.addEventListener("click",()=>{let n=this.app.setting;if(n&&typeof n=="object"){let a=n.openTab;typeof a=="function"&&a.call(n,"paperforge")}}),setTimeout(()=>{r.focus()},100);break}default:{this._searchResultsEl.createEl("div",{cls:"paperforge-search-state-card",text:o("retrieval_internal_error"),attr:{role:"alert"}}).addClass("error-soft"),setTimeout(()=>{this._searchInput&&this._searchInput.focus()},100);break}}}async executeSearch(){if(!this._searchInput||!this._searchResultsEl)return;let e=this._searchInput.value.trim();if(!e)return;let t=this._searchMode==="@"||e.startsWith("@"),r=t?e.replace(/^@\s*/,"").trim():e;if(!r)return;let n=t?"retrieve":"search";this._searchState="searching",this._searchResults=null,this._searchActiveIndex=-1,this._renderSearchState();let a=this.app.vault.adapter,s="";if(a&&typeof a=="object"&&"basePath"in a){let x=a.basePath;s=typeof x=="string"?x:""}if(!s){this._searchState="backend-unavailable",this._renderSearchState();return}let i=null,c=this.app.plugins;if(c&&typeof c=="object"&&"plugins"in c){let x=c.plugins;if(x&&typeof x=="object"&&"paperforge"in x){let _=x.paperforge;_&&typeof _=="object"&&"settings"in _&&(i=_.settings)}}let{path:d,extraArgs:f=[]}=N(s,i,void 0,void 0),p=n==="retrieve"?["--deep"]:[],m=(0,_e.spawn)(d,[...f,"-m","paperforge","--vault",s,n,r,...p,"--json"],{cwd:s,timeout:3e4}),y=[];m.stdout.on("data",x=>{y.push(x.toString("utf-8"))}),m.stderr.on("data",()=>{}),m.on("close",x=>{if(x!==0){let g=Xe(String(x));this._searchState=this._mapErrorToSearchState(g.type),this._renderSearchState();return}let _=y.join(""),b=_.indexOf("{"),E=_.lastIndexOf("}"),k="";if(b!==-1&&E>b)k=_.slice(b,E+1);else{let g=_.indexOf("["),v=_.lastIndexOf("]");g!==-1&&v>g&&(k=_.slice(g,v+1))}if(!k){this._searchState="internal-error",this._renderSearchState();return}try{let g=JSON.parse(k),v=[];if(g&&typeof g=="object"&&"data"in g){let w=g.data;if(w&&typeof w=="object"){let T=w;"matches"in T&&Array.isArray(T.matches)&&(v=T.matches)}}this._searchResults=v,this._searchState=v.length>0?"results":"empty",this._renderSearchState()}catch(g){let v=g instanceof Error?g.message:String(g);this._searchState="internal-error",this._renderSearchState()}}),m.on("error",x=>{let _=x.code;if(typeof _=="string"){let b=Xe(_);this._searchState=this._mapErrorToSearchState(b.type)}else this._searchState="backend-unavailable";this._renderSearchState()})}_mapErrorToSearchState(e){switch(e){case"vectors_not_built":return"vectors-not-built";case"vectors_corrupted":return"vectors-not-built";case"backend_unavailable":return"backend-unavailable";case"model_changed":return"model-changed";case"timeout":return"timeout";case"no_python":case"python_missing":case"import_failed":case"version_mismatch":return"backend-unavailable";default:return"backend-unavailable"}}_renderSearchResultsList(e,t){if(!this._searchResultsEl)return;if(this._searchResultsEl.setAttr("aria-live","polite"),e.length===0){this._searchResultsEl.createEl("div",{cls:"paperforge-search-empty",text:"No results found."});return}let r=this._searchResultsEl.createEl("div",{cls:"paperforge-search-results-header"});r.createEl("span",{text:o("retrieval_results_count").replace("{n}",String(e.length)).replace("{s}",e.length!==1?"s":"")}).setAttr("aria-live","polite"),r.createEl("span",{cls:"paperforge-search-mode",text:t?"@":"M"});for(let a=0;aE!==null&&typeof E=="object"&&"zotero_key"in E&&E.zotero_key===f);if(b&&typeof b=="object"){let E=b;y=typeof E.main_note_path=="string"&&E.main_note_path?E.main_note_path:typeof E.note_path=="string"&&E.note_path?E.note_path:null}}y?c.addEventListener("click",_=>{let b=_.ctrlKey||_.metaKey;this.app.workspace.openLinkText(y,"",b)}):c.addEventListener("click",()=>{new I.Notice("[!!] Note not found: "+(f||"unknown"),6e3)}),c.addEventListener("keydown",_=>{if(_.key==="Enter"&&y){_.preventDefault();let b=_.ctrlKey||_.metaKey;this.app.workspace.openLinkText(y,"",b)}});let x=c.createEl("div",{cls:"paperforge-search-result-meta"});if(typeof i.first_author=="string"&&i.first_author&&x.createEl("span",{cls:"paperforge-search-result-author",text:i.first_author}),typeof i.journal=="string"&&i.journal&&x.createEl("span",{cls:"paperforge-search-result-journal",text:i.journal}),i.score!==void 0){let _=i.score,b=typeof _=="number"?_.toFixed(3):String(_);x.createEl("span",{cls:"paperforge-search-result-score",text:"Score: "+b})}if(typeof i.domain=="string"&&i.domain&&c.createEl("span",{cls:"paperforge-search-result-tag",text:i.domain}),typeof i.abstract=="string"&&i.abstract){let _=i.abstract;c.createEl("div",{cls:"paperforge-search-result-abstract",text:_.length>200?_.slice(0,200)+"...":_})}if(t&&typeof i.text=="string"&&i.text){let _=i.text;c.createEl("div",{cls:"paperforge-search-result-source",text:_.length>300?_.slice(0,300)+"...":_})}}}_renderSearchError(e){this._searchResultsEl&&(this._searchResultsEl.empty(),this._searchResultsEl.createEl("div",{cls:"paperforge-search-error",text:e}))}_runAction(e,t){var p,m;if(e.disabled){new I.Notice(`[i] ${e.disabledMsg||"This action is not yet available."}`,6e3);return}if(t.classList.contains("running"))return;t.addClass("running");let r=this.app.vault.adapter.basePath;this._showMessage("Processing...","running");let n=Array.isArray(e.args)?[...e.args]:[];if(e.needsKey){let y=this.app.workspace.getActiveFile(),x=null;if(y){let _=this.app.metadataCache.getFileCache(y);if(_&&_.frontmatter&&_.frontmatter.zotero_key?x=_.frontmatter.zotero_key:x=this._extractZoteroKeyFromPath(y.path),x)n=[...n,x];else if(_&&_.frontmatter){this._showMessage("[!!] No zotero_key in active note frontmatter","error"),new I.Notice("[!!] Open a paper note with a zotero_key in its frontmatter first",6e3),t.removeClass("running");return}else{this._showMessage("[!!] No frontmatter in active note","error"),new I.Notice("[!!] The active note has no frontmatter with a zotero_key",6e3),t.removeClass("running");return}}else{this._showMessage("[!!] No active note open","error"),new I.Notice("[!!] Open a paper note with a zotero_key in its frontmatter first",6e3),t.removeClass("running");return}}e.needsFilter&&(n=[...n,"--all"]);let a=e.needsFilter?6e4:e.needsKey?3e4:6e5,{path:s,extraArgs:i=[]}=N(r,(m=(p=this.app.plugins.plugins.paperforge)==null?void 0:p.settings)!=null?m:null,void 0,void 0),l=(0,_e.spawn)(s,[...i,"-m","paperforge",e.cmd,...n],{cwd:r,timeout:a}),c=[],d=Date.now(),f=setInterval(()=>this._fetchStats(!0),4e3);l.stdout.on("data",y=>{let x=y.toString("utf-8").split(` `).filter(Boolean);for(let _ of x){let b=_.trim();b&&(c.push(b),this._showMessage(c.slice(-8).join(` `),"running"))}}),l.stderr.on("data",y=>{let x=y.toString("utf-8").split(` `).filter(Boolean);for(let _ of x){if(_.includes("\r")||_.includes("%")||_.includes("\u2588"))continue;let b=_.trim();b&&!b.match(/^\d+%|^\|/)&&(c.push(b),this._showMessage(c.slice(-8).join(` diff --git a/paperforge/plugin/src/services/memory-state.ts b/paperforge/plugin/src/services/memory-state.ts index 61aaa2a8..3240ec88 100644 --- a/paperforge/plugin/src/services/memory-state.ts +++ b/paperforge/plugin/src/services/memory-state.ts @@ -227,7 +227,9 @@ export function isVectorReady(vaultPath: string): boolean { if (!s.deps_installed) return false; if (!s.db_exists) return false; if (s.healthy === false) return false; - if (s.chunk_count === 0) return false; + // Use total_chunks (body + object + fulltext) — chunk_count alone is vec_fulltext_meta which may be empty + const total = (s.chunk_count ?? 0) + ((s.body_chunk_count as number) ?? 0) + ((s.object_chunk_count as number) ?? 0); + if (total === 0) return false; return true; }