fancive_obsidian-parallel-r.../main.js
wujunchen ff1116d7f4 fix: pass --max-tokens to Claude Code CLI to prevent output truncation
The CLI path was not forwarding settings.apiMaxTokens, causing the
model to use its own default which is too small for long documents
with many CJK cards. This was the root cause of repeated "LLM 返回
非 JSON" errors — the JSON was being cut off mid-card.

Change-Id: Ia738418e2e6cf7f919752cb3128a82768d95cedf
2026-04-27 11:58:04 +08:00

111 lines
94 KiB
JavaScript

'use strict';
"use strict";var _t=Object.create;var se=Object.defineProperty;var Vt=Object.getOwnPropertyDescriptor;var Gt=Object.getOwnPropertyNames;var Ut=Object.getPrototypeOf,jt=Object.prototype.hasOwnProperty;var Ht=(r,t)=>{for(var e in t)se(r,e,{get:t[e],enumerable:!0})},dt=(r,t,e,n)=>{if(t&&typeof t=="object"||typeof t=="function")for(let i of Gt(t))!jt.call(r,i)&&i!==e&&se(r,i,{get:()=>t[i],enumerable:!(n=Vt(t,i))||n.enumerable});return r};var oe=(r,t,e)=>(e=r!=null?_t(Ut(r)):{},dt(t||!r||!r.__esModule?se(e,"default",{value:r,enumerable:!0}):e,r)),Jt=r=>dt(se({},"__esModule",{value:!0}),r);var br={};Ht(br,{__test:()=>yr,default:()=>fr});module.exports=Jt(br);var h=require("obsidian");function $(r,t){if(!t)return-1;let e=u=>u.replace(/\s+/g," ").trim(),n=u=>{let y=[],p=[],m=!1;for(let b=0;b<u.length;b++){let ae=u[b];if(/\s/.test(ae)){m=y.length>0;continue}m&&(y.push(" "),p.push(b),m=!1),y.push(ae),p.push(b)}return{text:y.join(""),map:p}},i=u=>{if(!u)return-1;let y=r.indexOf(u);if(y===-1)return-1;let p=0;for(let m=0;m<y;m++)r[m]===`
`&&p++;return p},a=i(t);if(a>=0||(a=i(t.trim()),a>=0))return a;for(let u of[60,40,25,15]){let y=t.trim().slice(0,u);if(a=i(y),a>=0)return a}let s=n(r),c=e(t).slice(0,30);if(!c)return-1;let o=s.text.indexOf(c);if(o===-1)return-1;let d=s.map[o];if(d==null)return-1;let l=0;for(let u=0;u<d;u++)r[u]===`
`&&l++;return l}var mt=oe(require("crypto"));var ce={zh:{appTitle:"\u5BF9\u7167\u9605\u8BFB\u7B14\u8BB0",settingsTitle:"Parallel Reader \u8BBE\u7F6E",emptyOpenNote:"\u6253\u5F00\u4E00\u7BC7\u7B14\u8BB0\uFF0C\u7136\u540E\u8FD0\u884C\u547D\u4EE4\uFF1A",emptyNoCache:"\u8BE5\u7B14\u8BB0\u5C1A\u65E0\u5BF9\u7167\u7B14\u8BB0\u7F13\u5B58\u3002\u8FD0\u884C\u547D\u4EE4\uFF1A",commandGenerate:"Parallel Reader: \u4E3A\u5F53\u524D\u7B14\u8BB0\u751F\u6210\u5BF9\u7167\u7B14\u8BB0",displayName:"\u5BF9\u7167\u9605\u8BFB\u7B14\u8BB0",ribbonOpen:"\u6253\u5F00\u5BF9\u7167\u7B14\u8BB0\u9762\u677F",cmdRun:"\u4E3A\u5F53\u524D\u7B14\u8BB0\u751F\u6210\u5BF9\u7167\u7B14\u8BB0\uFF08\u7F13\u5B58\u4F18\u5148\uFF09",cmdRegen:"\u5F3A\u5236\u91CD\u65B0\u751F\u6210\uFF08\u7ED5\u8FC7\u7F13\u5B58\uFF09",cmdOpenView:"\u6253\u5F00\u5BF9\u7167\u7B14\u8BB0\u9762\u677F",cmdExport:"\u5BFC\u51FA\u5F53\u524D\u5BF9\u7167\u7B14\u8BB0\u5230 Vault",cmdCopyMarkdown:"\u590D\u5236\u5F53\u524D\u5BF9\u7167\u7B14\u8BB0 Markdown",cmdCancel:"\u53D6\u6D88\u5F53\u524D\u5BF9\u7167\u7B14\u8BB0\u751F\u6210",cmdClearCurrent:"\u6E05\u9664\u5F53\u524D\u7B14\u8BB0\u7684\u7F13\u5B58",cmdClearAll:"\u6E05\u9664\u6240\u6709\u7F13\u5B58",cmdCardPrev:"\u805A\u7126\u4E0A\u4E00\u5F20\u6458\u8981\u5361\u7247",cmdCardNext:"\u805A\u7126\u4E0B\u4E00\u5F20\u6458\u8981\u5361\u7247",cmdCardJump:"\u8DF3\u8F6C\u5230\u5F53\u524D\u6458\u8981\u5361\u7247\u539F\u6587",actionCancel:"\u53D6\u6D88\u751F\u6210",actionRegenerate:"\u91CD\u65B0\u751F\u6210",actionCopyAll:"\u590D\u5236\u5168\u90E8 Markdown",actionExport:"\u5BFC\u51FA\u5230 Vault",staleBanner:"\u6E90\u7B14\u8BB0\u6216\u751F\u6210\u914D\u7F6E\u5DF2\u4FEE\u6539\uFF0C\u5F53\u524D\u662F\u65E7\u7F13\u5B58\u3002",loadingDefault:"\u6B63\u5728\u751F\u6210\u5BF9\u7167\u7B14\u8BB0...",loadingGenerating:"\u5BF9\u7167\u9605\u8BFB\uFF1A\u8BA9 LLM \u8BFB\u5168\u6587\u5E76\u81EA\u9002\u5E94\u5207\u6BB5...",loadingSubtitle:"\u53EF\u4EE5\u7EE7\u7EED\u9605\u8BFB\u539F\u6587\uFF0C\u751F\u6210\u5B8C\u6210\u540E\u4F1A\u81EA\u52A8\u5237\u65B0\u53F3\u4FA7\u5361\u7247\u3002",errorTitle:"\u751F\u6210\u5931\u8D25",actionCopyError:"\u590D\u5236\u9519\u8BEF\u4FE1\u606F",emptyCard:"\uFF08\u672A\u751F\u6210\uFF09",anchorMismatch:"anchor \u5339\u914D\u5931\u8D25\uFF0C\u65E0\u6CD5\u6EDA\u52A8\u8054\u52A8",menuCopyMarkdown:"\u590D\u5236 Markdown",menuCopyPlain:"\u590D\u5236\u7EAF\u6587\u672C",menuCopyAnchor:"\u590D\u5236 anchor \u5F15\u7528",menuJumpSource:"\u8DF3\u8F6C\u5230\u539F\u6587",menuEditCard:"\u7F16\u8F91\u6B64\u5361\u7247",menuDeleteCard:"\u5220\u9664\u6B64\u5361\u7247",copiedMarkdown:"\u5DF2\u590D\u5236 Markdown",copiedPlain:"\u5DF2\u590D\u5236\u7EAF\u6587\u672C",copiedAnchor:"\u5DF2\u590D\u5236\u5F15\u7528\u539F\u6587",copiedAllMarkdown:"\u5DF2\u590D\u5236\u5168\u90E8 Markdown",copyFailed:"\u590D\u5236\u5931\u8D25\uFF1A{error}",actionFailed:"{label}\u5931\u8D25\uFF1A{error}",exported:"\u5DF2\u5BFC\u51FA \u2192 {path}",noCurrentNote:"\u6CA1\u6709\u5F53\u524D\u7B14\u8BB0",cacheClearedFile:"\u5DF2\u6E05\u9664\u7F13\u5B58\uFF1A{name}",cacheClearedAll:"\u5DF2\u6E05\u9664 {count} \u6761\u7F13\u5B58",noCancelableJob:"\u5F53\u524D\u6CA1\u6709\u53EF\u53D6\u6D88\u7684\u751F\u6210\u4EFB\u52A1",cancelRequested:"\u5DF2\u8BF7\u6C42\u53D6\u6D88\u751F\u6210",cancelRequestedApiInFlight:"\u5DF2\u8BF7\u6C42\u53D6\u6D88\u751F\u6210\uFF1B\u5F53\u524D API \u8BF7\u6C42\u65E0\u6CD5\u7ACB\u5373\u4E2D\u65AD\uFF0C\u8FD4\u56DE\u540E\u4F1A\u4E22\u5F03\u7ED3\u679C\u3002",actionGenerate:"\u751F\u6210\u5BF9\u7167\u7B14\u8BB0",fileMenuGenerate:"\u751F\u6210\u5BF9\u7167\u7B14\u8BB0",fileMenuRegen:"\u5F3A\u5236\u91CD\u65B0\u751F\u6210\u5BF9\u7167\u7B14\u8BB0",fileMenuClear:"\u6E05\u9664\u5BF9\u7167\u7B14\u8BB0\u7F13\u5B58",noExportContent:"\u5F53\u524D\u6CA1\u6709\u53EF\u5BFC\u51FA\u7684\u5BF9\u7167\u7B14\u8BB0",noCopyContent:"\u5F53\u524D\u6CA1\u6709\u53EF\u590D\u5236\u7684\u5BF9\u7167\u7B14\u8BB0",noActiveCard:"\u5F53\u524D\u6CA1\u6709\u53EF\u8DF3\u8F6C\u7684\u6458\u8981\u5361\u7247",viewOpenFailed:"\u65E0\u6CD5\u6253\u5F00\u5BF9\u7167\u7B14\u8BB0\u9762\u677F",confirmRegenerateEditedCards:"\u8FD9\u7BC7\u7B14\u8BB0\u7684\u5BF9\u7167\u5361\u7247\u5DF2\u88AB\u624B\u52A8\u7F16\u8F91\u3002\u91CD\u65B0\u751F\u6210\u4F1A\u8986\u76D6\u8FD9\u4E9B\u4FEE\u6539\uFF0C\u662F\u5426\u7EE7\u7EED\uFF1F",regenerateCancelled:"\u5DF2\u53D6\u6D88\u91CD\u65B0\u751F\u6210",cardDeleted:"\u5DF2\u5220\u9664\u6B64\u5361\u7247",cardSaved:"\u5DF2\u4FDD\u5B58\u6B64\u5361\u7247",editCardTitle:"\u7F16\u8F91\u6458\u8981\u5361\u7247",editCardTitleField:"\u6807\u9898",editCardGistField:"\u9886\u8BFB",editCardBulletsField:"\u8981\u70B9\uFF08\u6BCF\u884C\u4E00\u6761\uFF09",editCardCancel:"\u53D6\u6D88",editCardSave:"\u4FDD\u5B58",openNoteFirst:"\u5148\u6253\u5F00\u4E00\u7BC7\u7B14\u8BB0",alreadyGenerating:"\u8BE5\u7B14\u8BB0\u6B63\u5728\u751F\u6210\u5BF9\u7167\u7B14\u8BB0",emptyNote:"\u7B14\u8BB0\u4E3A\u7A7A",longNoteTruncated:"\u7B14\u8BB0\u8F83\u957F\uFF1A\u4EC5\u53D1\u9001\u524D {count} \u4E2A\u5B57\u7B26\u7ED9\u6A21\u578B",generatingNotice:"\u5BF9\u7167\u9605\u8BFB\uFF1A\u8BA9 LLM \u8BFB\u5168\u6587\u5E76\u81EA\u9002\u5E94\u5207\u6BB5\u2026",noCardsReturned:"LLM \u672A\u8FD4\u56DE\u4EFB\u4F55 card",generationDone:"\u5BF9\u7167\u7B14\u8BB0\u751F\u6210\u5B8C\u6210\uFF1A{count} \u6BB5{suffix}",unanchoredSuffix:"\uFF08\u26A0 {count} \u6BB5 anchor \u672A\u5339\u914D\uFF09",cancelled:"\u5DF2\u53D6\u6D88\u751F\u6210",cancelledError:"\u751F\u6210\u5DF2\u53D6\u6D88",generationFailed:"\u751F\u6210\u5931\u8D25{kind}\uFF1A{error}",errorCustomProviderBaseUrlRequired:"\u81EA\u5B9A\u4E49 provider \u9700\u8981\u586B\u5199 API Base URL\u3002",errorApiBaseUrlMissing:"API Base URL \u672A\u8BBE\u7F6E\u3002\u8BF7\u5728\u8BBE\u7F6E\u91CC\u9009\u62E9 provider \u6216\u586B\u5199\u81EA\u5B9A\u4E49 base URL\u3002",errorModelMissing:"Model \u672A\u8BBE\u7F6E\u3002\u8BF7\u5728\u8BBE\u7F6E\u91CC\u586B\u5199\u6A21\u578B ID\u3002",errorApiKeyMissing:"API key \u672A\u8BBE\u7F6E\u3002\u8BF7\u5728\u8BBE\u7F6E\u91CC\u586B\u5199 API Key{hint}\u3002",errorApiKeyEnvHint:" \u6216\u73AF\u5883\u53D8\u91CF {envVar}",errorLlmNonJson:`LLM \u8FD4\u56DE\u975E JSON\uFF1A
{excerpt}`,errorCustomHeadersJsonParse:"\u81EA\u5B9A\u4E49 headers JSON \u89E3\u6790\u5931\u8D25\uFF1A{error}",errorCustomHeadersJsonObject:"\u81EA\u5B9A\u4E49 headers JSON \u5FC5\u987B\u662F\u5BF9\u8C61",errorCustomHeadersLineFormat:"\u81EA\u5B9A\u4E49 headers \u6BCF\u884C\u683C\u5F0F\u5E94\u4E3A `Header-Name: value`",errorProviderNonJson:`{label} \u8FD4\u56DE\u975E JSON\uFF1A
{excerpt}`,errorProviderRequestFailed:"{label} \u8BF7\u6C42\u5931\u8D25\uFF1A{error}",errorProviderApiStatus:"{label} API \u8FD4\u56DE HTTP {status}\uFF1A{excerpt}",noEditor:"\u627E\u4E0D\u5230\u6E90\u7B14\u8BB0\u5BF9\u5E94\u7684\u7F16\u8F91\u5668\u7A97\u53E3",settingUiLanguageName:"\u754C\u9762\u8BED\u8A00",settingUiLanguageDesc:"\u63A7\u5236\u63D2\u4EF6\u754C\u9762\u3001\u547D\u4EE4\u548C\u63D0\u793A\u6587\u6848\uFF1BAuto \u8DDF\u968F Obsidian/\u7CFB\u7EDF\u8BED\u8A00",settingBackendName:"Backend",settingBackendDesc:"\u751F\u6210 bullet \u7684\u540E\u7AEF\uFF1ACLI \u590D\u7528\u672C\u673A\u767B\u5F55\uFF1BAPI \u652F\u6301 OpenAI/Anthropic/Gemini \u53CA\u517C\u5BB9\u4EE3\u7406",settingCliPathName:"CLI \u8DEF\u5F84\uFF08\u53EF\u9009\uFF09",settingCliPathDesc:"\u7559\u7A7A\u5219\u81EA\u52A8\u63A2\u6D4B\u5E38\u89C1\u4F4D\u7F6E\uFF1BObsidian GUI \u542F\u52A8\u65F6\u4E0D\u7EE7\u627F shell PATH\uFF0C\u5FC5\u8981\u65F6\u586B\u7EDD\u5BF9\u8DEF\u5F84",settingCliPathPlaceholder:"\u4F8B\uFF1A/Users/you/bin/codex",settingCliTimeoutName:"CLI \u8D85\u65F6 (ms)",apiProviderHeader:"API Provider",settingProviderPresetName:"Provider preset",settingProviderPresetDesc:"\u53C2\u8003 OpenClaw \u7684 provider/model \u601D\u8DEF\uFF1Apreset \u53EA\u8D1F\u8D23\u534F\u8BAE\u3001base URL \u548C\u8BA4\u8BC1\u9ED8\u8BA4\u503C",settingApiFormatName:"API format",settingApiFormatDesc:"\u4E0D\u540C provider \u7684 wire protocol\uFF1BOpenAI-compatible \u4EE3\u7406\u901A\u5E38\u9009 Chat Completions",settingBaseUrlName:"Base URL",settingBaseUrlDesc:"\u586B provider \u6839\u5730\u5740\uFF0C\u4E0D\u8981\u9644\u52A0 /chat/completions\uFF1B\u7559\u7A7A\u65F6\u4F7F\u7528 preset \u9ED8\u8BA4\u503C",settingApiKeyName:"API Key",settingApiKeyDesc:"\u672C\u5730 Ollama/LM Studio \u53EF\u7559\u7A7A\uFF1B\u5176\u4ED6 provider \u901A\u5E38\u9700\u8981 key",settingApiKeyEnvName:"API Key \u73AF\u5883\u53D8\u91CF",settingApiKeyEnvDesc:"\u53EF\u9009\uFF1BObsidian GUI \u4E0D\u4E00\u5B9A\u7EE7\u627F shell \u73AF\u5883\uFF0C\u76F4\u63A5\u586B API Key \u66F4\u7A33\u5B9A",settingAuthTypeName:"\u8BA4\u8BC1\u65B9\u5F0F",settingAuthTypeDesc:"Auto \u4F7F\u7528 provider preset\uFF1B\u81EA\u5B9A\u4E49\u4EE3\u7406\u53EF\u6309\u9700\u8981\u6539\u6210 Bearer\u3001x-api-key \u6216 none",settingHeadersName:"\u989D\u5916 headers",settingHeadersDesc:"\u53EF\u9009\u3002\u652F\u6301 JSON \u5BF9\u8C61\u6216\u6BCF\u884C `Header: value`\uFF0C\u7528\u4E8E Cloudflare AI Gateway \u7B49\u4EE3\u7406",settingMaxTokensName:"\u6700\u5927\u8F93\u51FA tokens",settingModelName:"Model",settingModelDescApi:"API \u8C03\u7528\u7684\u6A21\u578B ID\uFF1B\u652F\u6301 OpenClaw \u98CE\u683C provider/model\uFF0C\u82E5 provider \u524D\u7F00\u5339\u914D\u5F53\u524D preset \u4F1A\u81EA\u52A8\u5265\u79BB",settingModelDescCli:"Claude Code \u4E0B\u4F1A\u4F20 --model\uFF1BCodex \u4E0B\u901A\u5E38\u5FFD\u7565\uFF08\u7528 Codex \u9ED8\u8BA4\u914D\u7F6E\uFF09",settingMaxInputName:"\u6700\u5927\u8F93\u5165\u5B57\u7B26\u6570",settingMaxInputDesc:"\u8D85\u8FC7\u8BE5\u957F\u5EA6\u4F1A\u622A\u65AD\u540E\u518D\u53D1\u9001\u7ED9\u6A21\u578B\uFF1B\u957F\u4E0A\u4E0B\u6587\u6A21\u578B\u53EF\u9002\u5F53\u8C03\u5927",promptHeader:"Prompt",settingPromptLanguageName:"\u8F93\u51FA\u8BED\u8A00",settingPromptLanguageDesc:"\u63A7\u5236 title/gist/bullets \u7684\u8BED\u8A00\uFF1Banchor \u59CB\u7EC8\u9010\u5B57\u590D\u5236\u539F\u6587",settingCardRangeName:"\u5361\u7247\u6570\u91CF\u8303\u56F4",settingCardRangeDesc:"\u6A21\u578B\u4F1A\u5728\u8FD9\u4E2A\u8303\u56F4\u5185\u81EA\u9002\u5E94\u5207\u6BB5",settingCustomPromptName:"\u81EA\u5B9A\u4E49 system prompt",settingCustomPromptDesc:"\u53EF\u9009\u3002\u652F\u6301\u53D8\u91CF\uFF1A{minCards}\u3001{maxCards}\u3001{languageInstruction}\u3001{schema}\u3001{example}",settingCustomPromptPlaceholder:"\u7559\u7A7A\u4F7F\u7528\u5185\u7F6E prompt",settingTestBackendName:"\u6D4B\u8BD5\u5F53\u524D\u540E\u7AEF",settingTestBackendDescApi:"\u4F1A\u53D1\u8D77\u4E00\u6B21\u6700\u5C0F LLM \u8BF7\u6C42\u9A8C\u8BC1 API \u8BBE\u7F6E",settingTestBackendDescCli:"\u8C03\u7528 `<cli> --version` \u9A8C\u8BC1 spawn \u80FD\u627E\u5230\u4E8C\u8FDB\u5236",backendTestFailed:"\u2717 \u540E\u7AEF\u6D4B\u8BD5\u5931\u8D25\uFF1A{error}",settingExportFolderName:"\u5BFC\u51FA\u6587\u4EF6\u5939",settingExportFolderDesc:"\u5BF9\u7167\u7B14\u8BB0\u751F\u6210\u4F4D\u7F6E\uFF08\u76F8\u5BF9 Vault \u6839\uFF09",cacheHeader:"\u7F13\u5B58",settingMaxCacheName:"\u6700\u5927\u7F13\u5B58\u7BC7\u6570",settingMaxCacheDesc:"\u8D85\u8FC7\u4E0A\u9650\u540E\u6309\u6700\u8FD1\u8BBF\u95EE\u65F6\u95F4\u6DD8\u6C70\u6700\u65E7\u7684\u7B14\u8BB0\u7F13\u5B58\uFF1B\u7F13\u5B58\u4FDD\u5B58\u5728\u63D2\u4EF6\u76EE\u5F55\u7684 cache.json",cachePruned:"\u5DF2\u6DD8\u6C70 {count} \u6761\u65E7\u7F13\u5B58",cachedNotesName:"\u5DF2\u7F13\u5B58\u7B14\u8BB0\uFF1A{count} \u7BC7",cachedNotesDesc:"\u7F13\u5B58\u4EE5\u6E90\u7B14\u8BB0 SHA1 + \u751F\u6210\u914D\u7F6E\u6307\u7EB9\u4F5C\u4E3A\u5931\u6548\u952E\uFF0C\u6E90\u7B14\u8BB0\u6216\u6A21\u578B\u914D\u7F6E\u4FEE\u6539\u540E\u4F1A\u663E\u793A stale \u63D0\u793A",clearAllCacheButton:"\u6E05\u9664\u6240\u6709\u7F13\u5B58",settingStreamingName:"\u6D41\u5F0F\u8F93\u51FA",settingStreamingDesc:"\u542F\u7528\u540E\u751F\u6210\u65F6\u5B9E\u65F6\u663E\u793A LLM \u8F93\u51FA\u8FDB\u5EA6\uFF08\u4EC5 OpenAI Chat \u548C Anthropic \u683C\u5F0F\u652F\u6301\uFF09",settingStreamingTimeoutName:"\u6D41\u5F0F\u8D85\u65F6 (ms)",settingStreamingTimeoutDesc:"\u5355\u6B21\u6D41\u5F0F\u8BF7\u6C42\u7684\u8D85\u65F6\u65F6\u95F4\uFF1B\u4F4E\u4E8E 1000ms \u6216\u975E\u6CD5\u503C\u4F1A\u6062\u590D\u9ED8\u8BA4\u503C",cmdBatchGenerate:"\u6279\u91CF\u751F\u6210\u5BF9\u7167\u7B14\u8BB0\uFF08\u5F53\u524D\u6587\u4EF6\u5939\uFF09",batchSelectFolder:"\u8BF7\u8F93\u5165\u8981\u6279\u91CF\u5904\u7406\u7684\u6587\u4EF6\u5939\u8DEF\u5F84\uFF08\u7559\u7A7A\u4E3A Vault \u6839\u76EE\u5F55\uFF09",batchFolderPrompt:"\u6587\u4EF6\u5939\u8DEF\u5F84",batchAlreadyRunning:"\u6279\u91CF\u751F\u6210\u6B63\u5728\u8FD0\u884C",batchCancelRequested:"\u5DF2\u8BF7\u6C42\u53D6\u6D88\u6279\u91CF\u751F\u6210\uFF1B\u5F53\u524D\u6587\u4EF6\u7ED3\u675F\u540E\u505C\u6B62",batchInvalidFolderInput:"\u6587\u4EF6\u5939\u8DEF\u5F84\u65E0\u6548\uFF1A{path}",batchFolderNotFound:"\u6587\u4EF6\u5939\u4E0D\u5B58\u5728\uFF1A{path}",batchNoMarkdown:"\u8BE5\u6587\u4EF6\u5939\u4E0B\u6CA1\u6709 Markdown \u6587\u4EF6",batchProgress:"\u6279\u91CF\u751F\u6210\uFF1A{current}/{total}",batchDone:"\u6279\u91CF\u751F\u6210\u5B8C\u6210\uFF1A\u5171\u5904\u7406 {processed}/{total} \u7BC7\uFF0C\u8DF3\u8FC7\u7F13\u5B58 {skipped} \u7BC7\uFF0C\u5931\u8D25 {errors} \u7BC7",batchCancelled:"\u6279\u91CF\u751F\u6210\u5DF2\u53D6\u6D88\uFF1A\u5DF2\u5904\u7406 {processed}/{total} \u7BC7\uFF0C\u8DF3\u8FC7\u7F13\u5B58 {skipped} \u7BC7\uFF0C\u5931\u8D25 {errors} \u7BC7"},en:{appTitle:"Parallel Reader",settingsTitle:"Parallel Reader Settings",emptyOpenNote:"Open a note, then run:",emptyNoCache:"This note has no cached parallel notes. Run:",commandGenerate:"Parallel Reader: Generate notes for current note",displayName:"Parallel Reader",ribbonOpen:"Open Parallel Reader pane",cmdRun:"Generate parallel notes for current note (cache first)",cmdRegen:"Regenerate parallel notes (bypass cache)",cmdOpenView:"Open Parallel Reader pane",cmdExport:"Export current parallel notes to Vault",cmdCopyMarkdown:"Copy current parallel notes as Markdown",cmdCancel:"Cancel current parallel-note generation",cmdClearCurrent:"Clear cache for current note",cmdClearAll:"Clear all caches",cmdCardPrev:"Focus previous summary card",cmdCardNext:"Focus next summary card",cmdCardJump:"Jump current summary card to source",actionCancel:"Cancel generation",actionRegenerate:"Regenerate",actionCopyAll:"Copy all Markdown",actionExport:"Export to Vault",staleBanner:"The source note or generation settings changed. This is stale cache.",loadingDefault:"Generating parallel notes...",loadingGenerating:"Parallel Reader: asking the LLM to read and segment the full note...",loadingSubtitle:"You can keep reading. Cards will refresh when generation finishes.",errorTitle:"Generation failed",actionCopyError:"Copy error",emptyCard:"(not generated)",anchorMismatch:"Anchor did not match; scroll sync is unavailable",menuCopyMarkdown:"Copy Markdown",menuCopyPlain:"Copy plain text",menuCopyAnchor:"Copy anchor quote",menuJumpSource:"Jump to source",menuEditCard:"Edit this card",menuDeleteCard:"Delete this card",copiedMarkdown:"Copied Markdown",copiedPlain:"Copied plain text",copiedAnchor:"Copied anchor quote",copiedAllMarkdown:"Copied all Markdown",copyFailed:"Copy failed: {error}",actionFailed:"{label} failed: {error}",exported:"Exported \u2192 {path}",noCurrentNote:"No current note",cacheClearedFile:"Cleared cache: {name}",cacheClearedAll:"Cleared {count} cache entries",noCancelableJob:"No cancellable generation job",cancelRequested:"Cancel requested",cancelRequestedApiInFlight:"Cancel requested. The in-flight API request cannot be aborted immediately; its result will be ignored.",actionGenerate:"Generate parallel notes",fileMenuGenerate:"Generate parallel notes",fileMenuRegen:"Regenerate parallel notes",fileMenuClear:"Clear parallel-note cache",noExportContent:"No parallel notes to export",noCopyContent:"No parallel notes to copy",noActiveCard:"No active summary card to jump",viewOpenFailed:"Could not open the Parallel Reader pane",confirmRegenerateEditedCards:"These parallel-reader cards were edited manually. Regenerating will overwrite those edits. Continue?",regenerateCancelled:"Regeneration cancelled",cardDeleted:"Deleted this card",cardSaved:"Saved this card",editCardTitle:"Edit summary card",editCardTitleField:"Title",editCardGistField:"Gist",editCardBulletsField:"Bullets (one per line)",editCardCancel:"Cancel",editCardSave:"Save",openNoteFirst:"Open a note first",alreadyGenerating:"This note is already being generated",emptyNote:"The note is empty",longNoteTruncated:"Long note: only the first {count} characters will be sent to the model",generatingNotice:"Parallel Reader: asking the LLM to read and segment the full note...",noCardsReturned:"LLM returned no cards",generationDone:"Generated {count} sections{suffix}",unanchoredSuffix:" (\u26A0 {count} anchors unmatched)",cancelled:"Generation cancelled",cancelledError:"Generation cancelled",generationFailed:"Generation failed{kind}: {error}",errorCustomProviderBaseUrlRequired:"Custom provider requires an API Base URL.",errorApiBaseUrlMissing:"API Base URL is not set. Choose a provider or enter a custom base URL in settings.",errorModelMissing:"Model is not set. Enter a model ID in settings.",errorApiKeyMissing:"API key is not set. Enter an API Key in settings{hint}.",errorApiKeyEnvHint:" or set environment variable {envVar}",errorLlmNonJson:`LLM returned non-JSON:
{excerpt}`,errorCustomHeadersJsonParse:"Custom headers JSON parse failed: {error}",errorCustomHeadersJsonObject:"Custom headers JSON must be an object",errorCustomHeadersLineFormat:"Custom headers lines must use `Header-Name: value`",errorProviderNonJson:`{label} returned non-JSON:
{excerpt}`,errorProviderRequestFailed:"{label} request failed: {error}",errorProviderApiStatus:"{label} API returned HTTP {status}: {excerpt}",noEditor:"Could not find the source note editor",settingUiLanguageName:"UI language",settingUiLanguageDesc:"Controls plugin UI, commands, and notices. Auto follows Obsidian/system language.",settingBackendName:"Backend",settingBackendDesc:"Backend for generating bullets: CLI reuses local login; API supports OpenAI, Anthropic, Gemini, and compatible proxies.",settingCliPathName:"CLI path (optional)",settingCliPathDesc:"Leave blank to auto-detect common paths. Obsidian launched from the GUI may not inherit shell PATH.",settingCliPathPlaceholder:"Example: /Users/you/bin/codex",settingCliTimeoutName:"CLI timeout (ms)",apiProviderHeader:"API Provider",settingProviderPresetName:"Provider preset",settingProviderPresetDesc:"OpenClaw-style provider/model setup: presets define protocol, base URL, and auth defaults.",settingApiFormatName:"API format",settingApiFormatDesc:"Wire protocol for the provider. OpenAI-compatible proxies usually use Chat Completions.",settingBaseUrlName:"Base URL",settingBaseUrlDesc:"Provider root URL, without /chat/completions. Blank uses the preset default.",settingApiKeyName:"API Key",settingApiKeyDesc:"Can be blank for local Ollama/LM Studio; most hosted providers require a key.",settingApiKeyEnvName:"API key env var",settingApiKeyEnvDesc:"Optional. Obsidian GUI may not inherit shell env; direct API Key is usually more reliable.",settingAuthTypeName:"Auth type",settingAuthTypeDesc:"Auto uses provider preset. Custom proxies can use Bearer, x-api-key, or none.",settingHeadersName:"Extra headers",settingHeadersDesc:"Optional. JSON object or one `Header: value` per line, useful for Cloudflare AI Gateway.",settingMaxTokensName:"Max output tokens",settingModelName:"Model",settingModelDescApi:"Model ID for API calls. Supports OpenClaw-style provider/model; matching provider prefixes are stripped.",settingModelDescCli:"Passed as --model for Claude Code. Usually ignored by Codex, which uses its default config.",settingMaxInputName:"Max input characters",settingMaxInputDesc:"Longer notes are truncated before sending to the model. Raise this for long-context models.",promptHeader:"Prompt",settingPromptLanguageName:"Output language",settingPromptLanguageDesc:"Controls title/gist/bullets language. Anchor is always copied verbatim from source.",settingCardRangeName:"Card count range",settingCardRangeDesc:"The model adapts segmentation within this range.",settingCustomPromptName:"Custom system prompt",settingCustomPromptDesc:"Optional. Variables: {minCards}, {maxCards}, {languageInstruction}, {schema}, {example}",settingCustomPromptPlaceholder:"Leave blank to use built-in prompt",settingTestBackendName:"Test current backend",settingTestBackendDescApi:"Sends a minimal LLM request to validate API settings.",settingTestBackendDescCli:"Runs `<cli> --version` to verify the binary can be spawned.",backendTestFailed:"\u2717 Backend test failed: {error}",settingExportFolderName:"Export folder",settingExportFolderDesc:"Parallel-note output location, relative to the Vault root.",cacheHeader:"Cache",settingMaxCacheName:"Max cached notes",settingMaxCacheDesc:"Prunes least-recently accessed note caches above this limit. Cache is stored in plugin cache.json.",cachePruned:"Pruned {count} old cache entries",cachedNotesName:"Cached notes: {count}",cachedNotesDesc:"Cache is invalidated by source SHA1 and generation settings fingerprint.",clearAllCacheButton:"Clear all caches",settingStreamingName:"Streaming output",settingStreamingDesc:"Show real-time LLM output progress during generation (OpenAI Chat and Anthropic formats only)",settingStreamingTimeoutName:"Streaming timeout (ms)",settingStreamingTimeoutDesc:"Timeout for one streaming request; invalid values or values below 1000ms use the default",cmdBatchGenerate:"Batch generate parallel notes (current folder)",batchSelectFolder:"Enter the folder path to batch-process (leave blank for Vault root)",batchFolderPrompt:"Folder path",batchAlreadyRunning:"Batch generation is already running",batchCancelRequested:"Batch cancellation requested; it will stop after the current note",batchInvalidFolderInput:"Invalid folder path: {path}",batchFolderNotFound:"Folder not found: {path}",batchNoMarkdown:"No Markdown files found in that folder",batchProgress:"Batch generating: {current}/{total}",batchDone:"Batch complete: processed {processed}/{total}, skipped {skipped} (cached), errors {errors}",batchCancelled:"Batch cancelled: processed {processed}/{total}, skipped {skipped} (cached), errors {errors}"}};function $t(r){let t=r?.uiLanguage;return t==="zh"||t==="en"?t:String((typeof navigator<"u"?navigator:null)?.language||"").toLowerCase().startsWith("zh")?"zh":"en"}function C(r,t,e){let n=$t(r),i=ce[n]||ce.en,a=ce.en[t]||ce.zh[t]||t,s=i[t]||a;return String(s).replace(/\{([a-zA-Z0-9_]+)\}/g,(c,o)=>e&&Object.hasOwn(e,o)?String(e[o]):c)}var Me=1e5,Kt=2,V=2,G=100,qt=1e3,K={zh:"\u4E2D\u6587",en:"English",auto:"Auto-detect"},Ne={auto:"Auto",zh:"\u4E2D\u6587",en:"English"},f={uiLanguage:"auto",backend:"api",cliPath:"",apiProvider:"anthropic",apiFormat:"anthropic-messages",apiBaseUrl:"",apiKey:"",apiKeyEnvVar:"",apiAuthType:"auto",apiHeaders:"",apiMaxTokens:4096,maxDocChars:Me,maxCacheEntries:G,promptLanguage:"zh",minCards:5,maxCards:15,customSystemPrompt:"",model:"claude-sonnet-4-6",exportFolder:"Reading/Articles",cliTimeoutMs:12e4,streaming:!0,streamingTimeoutMs:12e4},T={"anthropic-messages":{label:"Anthropic Messages",defaultBaseUrl:"https://api.anthropic.com/v1",defaultAuthType:"x-api-key"},"openai-chat":{label:"OpenAI Chat Completions",defaultBaseUrl:"https://api.openai.com/v1",defaultAuthType:"bearer",tokenLimitField:"max_tokens"},"openai-responses":{label:"OpenAI Responses",defaultBaseUrl:"https://api.openai.com/v1",defaultAuthType:"bearer"},"google-generative-ai":{label:"Google Gemini generateContent",defaultBaseUrl:"https://generativelanguage.googleapis.com/v1beta",defaultAuthType:"x-goog-api-key"}},Ie={auto:"Auto",bearer:"Authorization: Bearer","x-api-key":"x-api-key","x-goog-api-key":"x-goog-api-key","api-key":"api-key",none:"None"},M={anthropic:{label:"Anthropic",format:"anthropic-messages",baseUrl:"https://api.anthropic.com/v1",authType:"x-api-key",envVar:"ANTHROPIC_API_KEY",model:"claude-sonnet-4-6"},openai:{label:"OpenAI",format:"openai-chat",baseUrl:"https://api.openai.com/v1",authType:"bearer",envVar:"OPENAI_API_KEY",tokenLimitField:"max_completion_tokens",model:"gpt-5.1"},"openai-responses":{label:"OpenAI Responses",format:"openai-responses",baseUrl:"https://api.openai.com/v1",authType:"bearer",envVar:"OPENAI_API_KEY",modelPrefix:"openai",model:"gpt-5.1"},google:{label:"Google Gemini",format:"google-generative-ai",baseUrl:"https://generativelanguage.googleapis.com/v1beta",authType:"x-goog-api-key",envVar:"GEMINI_API_KEY",model:"gemini-3-pro-preview"},openrouter:{label:"OpenRouter",format:"openai-chat",baseUrl:"https://openrouter.ai/api/v1",authType:"bearer",envVar:"OPENROUTER_API_KEY",model:""},groq:{label:"Groq",format:"openai-chat",baseUrl:"https://api.groq.com/openai/v1",authType:"bearer",envVar:"GROQ_API_KEY",model:""},deepseek:{label:"DeepSeek",format:"openai-chat",baseUrl:"https://api.deepseek.com",authType:"bearer",envVar:"DEEPSEEK_API_KEY",model:"deepseek-chat"},moonshot:{label:"Moonshot / Kimi",format:"openai-chat",baseUrl:"https://api.moonshot.ai/v1",authType:"bearer",envVar:"MOONSHOT_API_KEY",model:"kimi-k2.5"},qianfan:{label:"Baidu Qianfan",format:"openai-chat",baseUrl:"https://qianfan.baidubce.com/v2",authType:"bearer",envVar:"QIANFAN_API_KEY",model:"deepseek-v3.2"},minimax:{label:"MiniMax (Anthropic-compatible)",format:"anthropic-messages",baseUrl:"https://api.minimax.io/anthropic",authType:"bearer",envVar:"MINIMAX_API_KEY",model:"MiniMax-M2.1"},xai:{label:"xAI",format:"openai-chat",baseUrl:"https://api.x.ai/v1",authType:"bearer",envVar:"XAI_API_KEY",model:""},mistral:{label:"Mistral",format:"openai-chat",baseUrl:"https://api.mistral.ai/v1",authType:"bearer",envVar:"MISTRAL_API_KEY",model:""},cerebras:{label:"Cerebras",format:"openai-chat",baseUrl:"https://api.cerebras.ai/v1",authType:"bearer",envVar:"CEREBRAS_API_KEY",model:""},zai:{label:"Z.AI / GLM",format:"openai-chat",baseUrl:"https://api.z.ai/api/paas/v4",authType:"bearer",envVar:"ZAI_API_KEY",model:""},ollama:{label:"Ollama (local)",format:"openai-chat",baseUrl:"http://127.0.0.1:11434/v1",authType:"none",envVar:"",model:""},lmstudio:{label:"LM Studio (local)",format:"openai-chat",baseUrl:"http://127.0.0.1:1234/v1",authType:"none",envVar:"",model:""},"custom-openai":{label:"Custom OpenAI-compatible",format:"openai-chat",baseUrl:"",authType:"bearer",envVar:"",model:""},"custom-anthropic":{label:"Custom Anthropic-compatible",format:"anthropic-messages",baseUrl:"",authType:"x-api-key",envVar:"",model:""}};function _(r){return mt.default.createHash("sha1").update(r,"utf8").digest("hex")}function Re(r){return Array.isArray(r)?"["+r.map(Re).join(",")+"]":r&&typeof r=="object"?"{"+Object.keys(r).sort().map(t=>JSON.stringify(t)+":"+Re(r[t])).join(",")+"}":JSON.stringify(r)}function De(r){return r==="api"||r==="anthropic-api"}function x(r){return M[r.apiProvider]||M.anthropic}function P(r){let t=x(r),e=(r.apiFormat||t.format||"").trim();return T[e]?e:t.format}function R(r){let t=P(r),e=x(r),n=(r.apiBaseUrl||"").trim();if(n)return n.replace(/\/+$/,"");if((r.apiProvider||"").startsWith("custom-"))throw new Error(C(r,"errorCustomProviderBaseUrlRequired"));let i=(e.baseUrl||T[t].defaultBaseUrl||"").trim();if(!i)throw new Error(C(r,"errorApiBaseUrlMissing"));return i.replace(/\/+$/,"")}function Le(r){let t=(r.apiAuthType||"auto").trim();if(t&&t!=="auto")return t;let e=x(r),n=P(r);return e.authType||T[n].defaultAuthType||"bearer"}function gt(r){let t=(r.apiKey||"").trim();if(t)return t;let e=(r.apiKeyEnvVar||x(r).envVar||"").trim();return e&&process.env?.[e]?String(process.env[e]).trim():""}function D(r){let t=(r.model||"").trim();if(!t)throw new Error(C(r,"errorModelMissing"));let e=x(r),n=[r.apiProvider,e.modelPrefix].map(a=>(a||"").trim()).filter(Boolean),i=t.toLowerCase();for(let a of n){let s=a.toLowerCase();if(i.startsWith(s+"/"))return t.slice(a.length+1).trim()}return t}function Oe(r,t){let e=x(r),n=M[t]||M.anthropic,i=(r.model||"").trim(),a=!i||i===f.model||!!e.model&&i===e.model;return{...r,apiProvider:t,apiFormat:n.format,apiBaseUrl:n.baseUrl,apiAuthType:n.authType||"auto",apiKeyEnvVar:n.envVar||"",...a?{model:n.model||""}:{}}}function le(r){Ne[r.uiLanguage]||(r.uiLanguage=f.uiLanguage),(!r.apiProvider||!M[r.apiProvider])&&(r.apiProvider="anthropic");let t=x(r);(!r.apiFormat||!T[r.apiFormat])&&(r.apiFormat=t.format),(!r.apiAuthType||!Ie[r.apiAuthType])&&(r.apiAuthType="auto"),r.backend==="anthropic-api"&&(r.apiProvider=r.apiProvider||"anthropic",r.apiFormat=r.apiFormat||"anthropic-messages",r.apiBaseUrl=r.apiBaseUrl||M.anthropic.baseUrl,r.apiAuthType=r.apiAuthType||"x-api-key",r.apiKeyEnvVar=r.apiKeyEnvVar||"ANTHROPIC_API_KEY");let e=Number(r.apiMaxTokens);(!Number.isFinite(e)||e<=0)&&(r.apiMaxTokens=f.apiMaxTokens);let n=Number(r.maxDocChars);return(!Number.isFinite(n)||n<1e3)&&(r.maxDocChars=f.maxDocChars),r.maxCacheEntries=ft(r.maxCacheEntries),K[r.promptLanguage]||(r.promptLanguage=f.promptLanguage),r.minCards=pt(r.minCards,f.minCards),r.maxCards=pt(r.maxCards,f.maxCards),r.maxCards<r.minCards&&(r.maxCards=r.minCards),r.streamingTimeoutMs=q(r.streamingTimeoutMs),typeof r.customSystemPrompt!="string"&&(r.customSystemPrompt=""),r}function pt(r,t){let e=Math.floor(Number(r));return Number.isFinite(e)?Math.min(30,Math.max(1,e)):t}function ft(r){let t=Math.floor(Number(r));return!Number.isFinite(t)||t<=0?G:t}function q(r){let t=Math.floor(Number(r));return!Number.isFinite(t)||t<qt?f.streamingTimeoutMs:t}function ht(r){let t=r&&(r.lastAccessedAt||r.generatedAt||r.updatedAt),e=Date.parse(t||"");return Number.isFinite(e)?e:0}function ue(r,t){if(!r||typeof r!="object")return[];let e=ft(t),n=Object.entries(r);if(n.length<=e)return[];let i=n.sort(([a,s],[c,o])=>ht(s)-ht(o)||a.localeCompare(c)).slice(0,n.length-e).map(([a])=>a);for(let a of i)delete r[a];return i}function z(r){let t=le(Object.assign({},f,r||{})),e=De(t.backend),n=x(t),i=P(t),a=e?(t.apiBaseUrl||n.baseUrl||T[i]?.defaultBaseUrl||"").trim().replace(/\/+$/,""):"";return _(Re({cacheSchemaVersion:V,promptVersion:Kt,maxDocChars:Number(t.maxDocChars)||f.maxDocChars,promptLanguage:t.promptLanguage,minCards:t.minCards,maxCards:t.maxCards,customSystemPromptHash:_(t.customSystemPrompt||""),backend:t.backend,model:t.model,apiProvider:e?t.apiProvider:"",apiFormat:e?i:"",apiBaseUrl:a,apiAuthType:e?Le(t):"",apiHeadersHash:e?_(t.apiHeaders||""):"",apiMaxTokens:e?Number(t.apiMaxTokens)||f.apiMaxTokens:0,structuredOutputVersion:1}))}function U(r,t,e){return!!r&&r.schemaVersion===V&&r.contentHash===_(t)&&r.settingsHash===z(e)}function de(r){return(r||"").trim().split("/").map(t=>t.trim()).filter(t=>t&&t!=="."&&t!=="..").join("/")}function Be(r){return(r||"").split("/").map(t=>t.trim()).some(t=>t==="."||t==="..")}function _e(r,t){let e=de(r);return Be(r)?{valid:!1,reason:"unsafe",folderPath:e}:e&&!t(e)?{valid:!1,reason:"missing",folderPath:e}:{valid:!0,reason:"ok",folderPath:e}}function zt(r,t){return t?r.parent?.path===t:!r.path.includes("/")}function Ve(r,t){let e=de(t);return r.filter(n=>zt(n,e))}function Ge(r,t){return{current:r+1,total:t}}function Ue(r){return{total:r,processed:0,skipped:0,errors:0}}function je(r){return{...r,processed:r.processed+1}}function He(r){return{...r,processed:r.processed+1,skipped:r.skipped+1}}function Je(r){return{...r,processed:r.processed+1,errors:r.errors+1}}function $e(r,t,e){return!!r&&U(r,t,e)}function Ke(){return{cancelled:!1,currentPath:""}}function qe(r,t){return r.currentPath=t,r}function pe(r){return!r||r.cancelled?!1:(r.cancelled=!0,!0)}function he(r,t){return r?{...r,lastAccessedAt:t||new Date().toISOString()}:null}function me(r){return JSON.stringify({version:1,entries:r||{}})}function ze(r,t){return!!t&&!!r&&typeof r.updatedAt=="string"&&r.updatedAt.trim().length>0}var W=class{constructor(t,e,n,i){this.adapter=t;this.configDir=e;this.pluginId=n;this.getSettings=i;this.cache={};this._timer=null;this._dirty=!1}filePath(){return`${this.configDir}/plugins/${this.pluginId}/cache.json`}async ensureDir(){let t=`${this.configDir}/plugins/${this.pluginId}`;try{if(typeof this.adapter.exists=="function"&&await this.adapter.exists(t))return;await this.adapter.mkdir(t)}catch{}}async readFile(){try{let t=await this.adapter.read(this.filePath()),e=JSON.parse(t);if(e&&typeof e=="object"&&e.entries&&typeof e.entries=="object")return e.entries}catch(t){let e=t instanceof Error?t.message:String(t);/not found|does not exist|ENOENT/i.test(e)||console.warn("[parallel-reader] failed to read cache.json",t)}return{}}async writeFile(){await this.ensureDir(),await this.adapter.write(this.filePath(),me(this.cache))}async load(){this.cache=await this.readFile(),this.prune().length>0&&await this.writeFile()}prune(){let t=this.getSettings();return ue(this.cache,t?.maxCacheEntries||G)}async pruneIfNeeded(){let t=this.prune();return t.length>0&&await this.save(),t}async save(){this._timer&&(clearTimeout(this._timer),this._timer=null),this.prune(),await this.writeFile(),this._dirty=!1}scheduleSave(t=5e3){this._dirty=!0,!this._timer&&(this._timer=setTimeout(()=>{this._timer=null,this._dirty&&this.save().catch(e=>console.error("[parallel-reader] failed to save cache",e))},t))}async flush(){this._timer&&(clearTimeout(this._timer),this._timer=null),this._dirty&&await this.save()}get(t){return this.cache[t]||null}touch(t){let e=he(this.cache[t]||null);return e?(this.cache[t]=e,this.scheduleSave(),e):null}async move(t,e){if(typeof t!="string"||typeof e!="string"||!t.trim()||!e.trim())return!1;if(t===e)return Object.hasOwn(this.cache,t);let n=this.cache[t];if(!n||Object.hasOwn(this.cache,e))return!1;let i={...this.cache,[e]:n};return delete i[t],this.cache=i,await this.save(),!0}async put(t,e,n,i){let a=new Date().toISOString();this.cache[t]={schemaVersion:V,contentHash:_(e),settingsHash:z(i||this.getSettings()),cards:n,generatedAt:a,lastAccessedAt:a},await this.save()}async replaceCards(t,e){let n=this.cache[t];if(!n)return!1;let i=new Date().toISOString();return this.cache[t]={...n,cards:(e||[]).map(a=>({title:a.title,anchor:a.anchor,gist:a.gist,bullets:a.bullets||[]})),updatedAt:i,lastAccessedAt:i},await this.save(),!0}async delete(t){this.cache[t]&&(delete this.cache[t],await this.save())}async clear(){this.cache={},await this.save()}};function ge(r,t){let e=Array.isArray(r)?r.slice():[];return!Number.isInteger(t)||t<0||t>=e.length||e.splice(t,1),e}function fe(r,t,e){if(!Number.isInteger(r)||!Number.isInteger(t)||t<=0||!Number.isInteger(e)||e<0||r<0||r>=t)return e;let n=t-1;return n<=0?-1:r<e?Math.max(0,e-1):r===e?Math.min(e,n-1):e}function ye(r,t,e){let n=Array.isArray(r)?r.slice():[];return!Number.isInteger(t)||t<0||t>=n.length||(n[t]=Object.assign({},n[t],e||{})),n}var vt=require("child_process"),xt=oe(require("fs")),be=oe(require("os")),v=oe(require("path"));var j=class extends Error{constructor(t){super("\u8BE5\u7B14\u8BB0\u6B63\u5728\u751F\u6210\u5BF9\u7167\u7B14\u8BB0"),this.name="GenerationJobAlreadyRunningError",this.code="already-running",this.key=t}},k=class extends Error{constructor(t){super("\u751F\u6210\u5DF2\u53D6\u6D88"),this.name="GenerationJobCancelledError",this.code="cancelled",this.key=t}},We=class{constructor(t){this.key=t,this.phase="queued",this.cancelled=!1,this.startedAt=new Date().toISOString(),this.updatedAt=this.startedAt,this._cancelHandlers=[]}setPhase(t){this.phase=t,this.updatedAt=new Date().toISOString()}onCancel(t){if(typeof t=="function"){if(this.cancelled){t();return}this._cancelHandlers.push(t)}}cancel(){if(this.cancelled)return!1;this.cancelled=!0,this.setPhase("cancelled");for(let t of this._cancelHandlers.splice(0))try{t()}catch{}return!0}throwIfCancelled(){if(this.cancelled)throw new k(this.key)}},Y=class{constructor(){this.jobs=new Map}get(t){return this.jobs.get(t)||null}isRunning(t){return this.jobs.has(t)}async start(t,e){if(this.jobs.has(t))throw new j(t);let n=new We(t);this.jobs.set(t,n);try{n.setPhase("running");let i=await e(n);return n.throwIfCancelled(),i}catch(i){throw n.cancelled&&!(i instanceof k)?new k(t):i}finally{this.jobs.delete(t)}}cancel(t){let e=this.jobs.get(t);return e?e.cancel():!1}};function Ye(r){if(r instanceof k)return"cancelled";let t=r;if(t?.code==="cancelled")return"cancelled";let e=String(t?.message||r);return/api key|unauthorized|401|403|认证|权限/i.test(e)?"auth":/timeout|超时|timed out/i.test(e)?"timeout":/429|rate limit|too many requests/i.test(e)?"rate-limit":/非 JSON|json_schema|schema|structured/i.test(e)?"schema":/model 未设置|base url|配置|config/i.test(e)?"config":"unknown"}var X="record_parallel_reader_cards";function yt(r){let t=[],e=-1,n=0,i=!1,a=!1;for(let s=0;s<r.length;s++){let c=r[s];if(i){a?a=!1:c==="\\"?a=!0:c==='"'&&(i=!1);continue}c==='"'?i=!0:c==="{"?(n===0&&(e=s),n++):c==="}"&&(n>0&&n--,n===0&&e>=0&&(t.push(r.slice(e,s+1)),e=-1))}return t}function Xe(r){let t=(r||"").trim();if(!t)return t;try{return JSON.parse(t),t}catch{}let e=t.match(/```(?:json)?\s*([\s\S]*?)```/);if(e){let i=e[1].trim();try{return JSON.parse(i),i}catch{}}let n=yt(t);n.sort((i,a)=>a.length-i.length);for(let i of n)try{return JSON.parse(i),i}catch{}return t}function Ze(r){let t=r.match(/\{\s*"cards"\s*:\s*\[/);if(!t||t.index===void 0)return null;let e=t.index+t[0].length,n=yt(r.slice(e)),i=[];for(let a of n)try{JSON.parse(a),i.push(a)}catch{}return i.length===0?null:'{"cards":['+i.join(",")+"]}"}function S(r,t){let e=Xe(r),n;try{n=JSON.parse(e)}catch{let a=Ze(r);if(a)try{return n=JSON.parse(a),console.warn("[parallel-reader] LLM output was truncated; salvaged",n.cards?.length??0,"complete cards. Consider increasing max tokens."),H(n)}catch{}throw console.warn("[parallel-reader] LLM returned non-JSON. Raw response:",r),new Error(C(t||null,"errorLlmNonJson",{excerpt:(r||"").slice(0,500)}))}return H(n)}function H(r){return(r&&Array.isArray(r.cards)?r.cards:[]).filter(e=>!!e&&typeof e=="object").map(e=>({title:typeof e.title=="string"?e.title:"(\u65E0\u6807\u9898)",anchor:typeof e.anchor=="string"?e.anchor:"",gist:typeof e.gist=="string"?e.gist:"",bullets:Array.isArray(e.bullets)?e.bullets.filter(n=>typeof n=="string"):[]}))}function Z(r){let t={type:"object",properties:{title:{type:"string"},anchor:{type:"string"},gist:{type:"string"},bullets:{type:"array",items:{type:"string"}}},required:["title","anchor","gist","bullets"]},e={type:"object",properties:{cards:{type:"array",items:t}},required:["cards"]};return r&&(t.additionalProperties=!1,e.additionalProperties=!1),e}function bt(){return{type:"json_schema",json_schema:{name:"parallel_reader_cards",strict:!0,schema:Z(!0)}}}function Ct(){return{format:{type:"json_schema",name:"parallel_reader_cards",strict:!0,schema:Z(!0)}}}function wt(){return{name:X,description:"Return the generated Parallel Reader summary cards.",input_schema:Z(!0)}}function L(r,t){if(t?.trim())return t.trim();let e=be.default.homedir(),n=process.platform==="win32",i=n?[".cmd",".exe",""]:[""],a=n?[v.default.join(e,"AppData","Roaming","npm"),v.default.join(e,"AppData","Local","Programs","claude-code"),v.default.join(e,"AppData","Local","Programs","codex"),v.default.join(e,".claude","local"),v.default.join(e,".codex","bin"),v.default.join(e,".bun","bin"),v.default.join(e,"scoop","shims"),"C:\\Program Files\\nodejs"]:[v.default.join(e,"bin"),v.default.join(e,".local","bin"),v.default.join(e,".claude","local"),v.default.join(e,".codex","bin"),v.default.join(e,".bun","bin"),v.default.join(e,".npm-global","bin"),v.default.join(e,".cargo","bin"),"/opt/homebrew/bin","/usr/local/bin"];for(let s of a)for(let c of i){let o=v.default.join(s,r+c);try{if(xt.default.existsSync(o))return o}catch{}}return r}function O(r,t,e,n,i,a=vt.spawn){return new Promise((s,c)=>{let o,d=!1,l=null,u=w=>{d||(d=!0,l&&clearTimeout(l),c(w))},y=w=>{d||(d=!0,l&&clearTimeout(l),s(w))};try{o=a(r,t,{stdio:["pipe","pipe","pipe"],env:{...process.env,PATH:[process.env.PATH||"","/usr/local/bin","/opt/homebrew/bin",v.default.join(be.default.homedir(),".local/bin"),v.default.join(be.default.homedir(),".claude/local")].filter(Boolean).join(":")}})}catch(w){return c(new Error(`Failed to start ${r}: ${w.message}`))}let p="",m="";if(l=setTimeout(()=>{try{o.kill("SIGKILL")}catch{}u(new Error(`CLI timed out (${n}ms)`))},n),i&&i.onCancel(()=>{try{o.kill("SIGKILL")}catch{}u(new k(i.key))}),!o.stdout||!o.stderr||!o.stdin){u(new Error("CLI process streams are unavailable"));return}let b=o.stdout,ae=o.stderr,Ee=o.stdin;if(b.on("data",w=>{p+=w.toString("utf8")}),ae.on("data",w=>{m+=w.toString("utf8")}),o.on("error",w=>{u(new Error(`CLI startup error: ${w.message}. Try setting an absolute CLI path.`))}),o.on("close",w=>{if(!d){if(w!==0)return u(new Error(`CLI exited with code ${w}
stderr:
${m.slice(0,1e3)}`));y({stdout:p,stderr:m})}}),e)try{Ee.write(e),Ee.end()}catch{}else try{Ee.end()}catch{}})}async function At(r,t,e,n){let i=L("claude",e.cliPath),a=Number(e.apiMaxTokens)||4096,s=["-p","--output-format","json","--max-tokens",String(a),"--append-system-prompt",r,"--disallowed-tools","Bash,Read,Write,Edit,Glob,Grep,WebFetch,WebSearch,TodoWrite,Task"],{stdout:c}=await O(i,s,t,e.cliTimeoutMs,n),o="";try{let d=JSON.parse(c);if(Array.isArray(d)){let l=d.find(u=>u.type==="result");l&&typeof l.result=="string"&&(o=l.result)}else d&&typeof d=="object"&&(o=d.result||d.content||"")}catch{throw new Error(`claude CLI returned unexpected output:
`+c.slice(0,500))}if(!o)throw console.warn("[parallel-reader] claude CLI returned no result. Full stdout:",c),new Error(`claude CLI returned no result. Output:
`+c.slice(0,500));return S(o,e)}async function Pt(r,t,e,n){let i=L("codex",e.cliPath),a=`<<SYSTEM>>
${r}
<<USER>>
${t}
Output JSON directly with no explanation.`,s=["exec","--skip-git-repo-check","-"],{stdout:c}=await O(i,s,a,e.cliTimeoutMs,n);return S(c,e)}var Dt=require("obsidian");function Wt(r){return r==="en"?"Write title, gist, and bullets in English.":r==="auto"?"Write title, gist, and bullets in the main language of the source document.":"\u7528\u4E2D\u6587\u8F93\u51FA title\u3001gist \u548C bullets\u3002"}function Yt(r){return r==="en"?`{"cards":[
{"title":"U-shaped gains","anchor":"Who benefits from AI? Overall, it shifts the score from one to seven","gist":"AI productivity gains form a U shape, with both ends benefiting most","bullets":["Top-paid software managers benefit by accelerating existing work","Low-paid workers use AI to create new side income","Middle-layer specialists gain less because prompt precision is hard to trust","Average reported benefit is 5.1/7, with 42% describing gains as unclear"]}
]}`:`{"cards":[
{"title":"U \u578B\u6536\u76CA\u66F2\u7EBF","anchor":"\u90A3\u8C01\u53C8\u4F1A\u88AB AI \u6240\u53D7\u76CA\uFF1F\u6574\u4F53\u6765\u770B\uFF0C\u5B83\u628A\u6574\u4E2A\u5206\u6570\u53D8\u6210\u4E86\u4E00\u5206\u5230\u4E03\u5206","gist":"AI \u751F\u4EA7\u529B\u6536\u76CA\u5448 U \u578B\uFF0C\u4E24\u7AEF\u53D7\u76CA\u6700\u5927\u3001\u4E2D\u95F4\u5C42\u584C\u9677","bullets":["\u6700\u9AD8\u85AA\u5C97\u4F4D\uFF08\u8F6F\u4EF6\u7BA1\u7406\uFF09\u901A\u8FC7\u52A0\u901F\u65E2\u6709\u5DE5\u4F5C\u53D7\u76CA\u6700\u5927","\u6700\u4F4E\u85AA\u5C97\u4F4D\uFF08\u5916\u5356\u5458\u3001\u56ED\u827A\u5DE5\uFF09\u7528 AI \u5F00\u526F\u4E1A\u521B\u9020\u65B0\u6536\u5165","\u4E2D\u95F4\u5C42\u79D1\u5B66\u5BB6\u3001\u5F8B\u5E08\u6536\u76CA\u6700\u5C11\uFF0C\u90E8\u5206\u56E0\u5BF9 prompt \u7CBE\u5EA6\u4FE1\u4EFB\u4E0D\u8DB3","\u5168\u4F53\u5747\u5206 5.1/7\uFF0C42% \u62A5\u544A\u6536\u76CA\u6A21\u7CCA"]}
]}`}function Xt(r,t){return String(r||"").replace(/\{([a-zA-Z0-9_]+)\}/g,(e,n)=>Object.hasOwn(t,n)?String(t[n]):e)}function Zt(r,t,e,n,i,a){return r==="en"?`You are a long-form reading summary assistant. After reading the full document, split it into ${t}-${e} natural topic units. They do not need to match markdown headings; use a complete argument or topic as the unit, merging short sections and splitting long ones when needed.
Each card has one guiding sentence plus several bullets. Bullets carry details; gist is the lead-in.
Language:
- ${n}
For each unit, output:
- title: a concise 3-10 word heading that clearly states what the section is about; avoid vague labels like "Background" or "Introduction"
- anchor: a verbatim quote from the start of this unit, copied 1:1 from the source, 40-80 characters where possible, preserving punctuation, spaces, and line breaks; it is only used internally for positioning
- gist: one guiding sentence, 20-40 words, stating the core claim or conclusion
- bullets: 3-6 supporting bullets, each 20-50 words, carrying data, comparisons, mechanisms, examples, or counterintuitive observations. Gist and bullets must not repeat each other.
Rules:
- anchor must exact-substring-match the source. Never paraphrase, translate, summarize, or alter it.
- Choose the earliest sufficiently distinctive quote for each unit; avoid generic phrases.
- Every card must include both gist and bullets.
- Each bullet must be a standalone assertion; avoid sequencing phrases such as "first" or "then".
- Output strict JSON only: no markdown fence, no explanation, no tool call.
Output shape:
${i}
Example:
${a}`:`\u4F60\u662F\u4E00\u4E2A\u957F\u6587\u9605\u8BFB\u6458\u8981\u52A9\u624B\u3002\u9605\u8BFB\u5168\u6587\u540E\uFF0C\u628A\u6587\u7AE0\u5207\u6210 ${t}-${e} \u4E2A"\u81EA\u7136\u4E3B\u9898\u5355\u5143"\u2014\u2014\u4E0D\u5FC5\u5BF9\u5E94 markdown heading\uFF0C\u4EE5"\u4E00\u4E2A\u5B8C\u6574\u8BBA\u70B9\u6216\u8BDD\u9898"\u4E3A\u5355\u4F4D\u81EA\u884C\u5224\u65AD\u7C92\u5EA6\uFF1A\u77ED\u7AE0\u8282\u5408\u5E76\u3001\u957F\u7AE0\u8282\u62C6\u5206\u3002
**\u6BCF\u5F20\u5361\u7247\u7684\u7ED3\u6784\uFF1A\u4E00\u53E5\u8BDD\u9886\u8BFB + \u82E5\u5E72\u6761 bullet\u3002bullet \u627F\u8F7D\u7EC6\u8282\uFF0Cgist \u662F\u4E00\u53E5\u8BDD\u5BFC\u8BFB\u3002**
\u8BED\u8A00\uFF1A
- ${n}
\u5BF9\u6BCF\u4E2A\u5355\u5143\u8F93\u51FA\uFF1A
- title: 3-10 \u5B57\u7684\u77ED\u6807\u9898\uFF0C\u8981\u80FD\u72EC\u7ACB\u8BF4\u660E\u8FD9\u6BB5\u8BB2\u4EC0\u4E48\uFF0C\u907F\u514D"\u80CC\u666F""\u4ECB\u7ECD"\u8FD9\u7C7B\u7A7A\u6CDB\u8BCD
- anchor: \u8BE5\u5355\u5143\u5F00\u5934\u7684**\u9010\u5B57\u5F15\u7528**\uFF0C\u4ECE\u539F\u6587 1:1 \u590D\u5236 40-80 \u5B57\uFF0C\u4FDD\u7559\u539F\u59CB\u6807\u70B9/\u7A7A\u683C/\u6362\u884C\uFF1B\u4EC5\u4F9B\u63D2\u4EF6\u5185\u90E8\u5B9A\u4F4D\uFF0C\u7528\u6237\u4E0D\u53EF\u89C1
- gist: **\u4E00\u53E5\u8BDD\u9886\u8BFB**\uFF0820-40 \u5B57\uFF09\uFF0C\u70B9\u51FA\u8BE5\u5355\u5143\u7684\u6838\u5FC3\u7ACB\u573A\u6216\u7ED3\u8BBA\uFF0C\u4F5C\u4E3A bullets \u7684\u5BFC\u8BFB
- bullets: **3-6 \u6761**\u652F\u6491 bullet\uFF0C\u6BCF\u6761 20-50 \u5B57\u3002\u627F\u8F7D\u6570\u636E\u3001\u5BF9\u6BD4\u3001\u673A\u5236\u3001\u4F8B\u5B50\u3001\u53CD\u76F4\u89C9\u89C2\u5BDF\u3002gist \u662F\u7ACB\u573A\uFF0Cbullets \u662F\u5177\u4F53\u5185\u5BB9\uFF0C\u4E24\u8005\u4E0D\u5141\u8BB8\u91CD\u590D\u3002
\u89C4\u5219\uFF1A
- anchor \u5FC5\u987B\u80FD\u5728\u539F\u6587\u91CC exact substring match \u627E\u5230\u3002\u7EDD\u5BF9\u4E0D\u8981\u6539\u52A8\u3001\u603B\u7ED3\u3001\u7FFB\u8BD1\uFF0C\u5FC5\u987B\u539F\u6837\u590D\u5236
- anchor \u9009\u7528\u8BE5\u5355\u5143\u6700\u9760\u524D\u4E14\u8DB3\u591F\u72EC\u7279\u7684\u4E00\u6BB5\uFF08\u907F\u514D\u901A\u7528\u5957\u8BDD\u5982"\u7EFC\u4E0A\u6240\u8FF0"\uFF09
- \u6BCF\u5F20\u5361\u90FD\u5FC5\u987B\u540C\u65F6\u6709 gist \u548C bullets\u2014\u2014\u4E0D\u8981\u53EA\u6709 gist\uFF0C\u4E5F\u4E0D\u8981\u53EA\u6709 bullets
- bullet \u6BCF\u6761\u662F\u4E00\u4E2A\u5B8C\u6574\u72EC\u7ACB\u7684\u65AD\u8A00\uFF0C\u4E0D\u8981\u7528"\u9996\u5148""\u5176\u6B21"\u8FD9\u79CD\u987A\u5E8F\u8BCD
- \u4E25\u683C\u53EA\u8F93\u51FA JSON\uFF0C\u65E0 markdown fence\u3001\u65E0\u89E3\u91CA\u3001\u65E0 tool call
\u8F93\u51FA\u683C\u5F0F\uFF1A
${i}
\u793A\u4F8B\uFF1A
${a}`}function Qt(r,t,e,n,i){return r==="en"?`Non-overridable output contract:
- Must output ${t}-${e} cards.
- ${n}
- anchor must be copied verbatim from the source and exact-substring-match the source.
- Output strict JSON only: no markdown fence, no explanation, no tool call.
- JSON shape: ${i}`:`\u4E0D\u53EF\u8986\u76D6\u7684\u8F93\u51FA\u5951\u7EA6\uFF1A
- \u5FC5\u987B\u8F93\u51FA ${t}-${e} \u5F20 cards\u3002
- ${n}
- anchor \u5FC5\u987B\u4ECE\u539F\u6587\u9010\u5B57\u590D\u5236\uFF0C\u5FC5\u987B\u80FD\u5728\u539F\u6587 exact substring match \u627E\u5230\u3002
- \u4E25\u683C\u53EA\u8F93\u51FA JSON\uFF0C\u65E0 markdown fence\u3001\u65E0\u89E3\u91CA\u3001\u65E0 tool call\u3002
- JSON shape: ${i}`}function Ce(r,t){let e=Number(t.maxDocChars)||Me,n=K[t.promptLanguage]?t.promptLanguage:f.promptLanguage,i=Math.max(1,Number(t.minCards)||f.minCards),a=Math.max(i,Number(t.maxCards)||f.maxCards),s=Wt(n),c=r.length>e?r.slice(0,e)+(n==="en"?`
[Document truncated]`:`
[\u6587\u6863\u8FC7\u957F\uFF0C\u5DF2\u622A\u65AD]`):r,o='{"cards":[{"title":"...","anchor":"...","gist":"...","bullets":["...","..."]}]}',d=Yt(n),l={minCards:i,maxCards:a,languageInstruction:s,schema:o,example:d},u=Xt(t.customSystemPrompt,l).trim(),y=Qt(n,i,a,s,o),p=Zt(n,i,a,s,o,d),m=u?`${u}
${y}`:p,b=n==="en"?`Source document:
${c}`:`\u4EE5\u4E0B\u662F\u9700\u8981\u5904\u7406\u7684\u6587\u6863\u5168\u6587\uFF1A
${c}`;return{system:m,user:b}}function Qe(r){if(typeof r=="string")return r;if(Array.isArray(r))return r.map(t=>{if(typeof t=="string")return t;if(t&&typeof t=="object"){let e=t;return typeof e.text=="string"?e.text:typeof e.output_text=="string"?e.output_text:""}return""}).join("");if(r&&typeof r=="object"){let t=r;return typeof t.text=="string"?t.text:typeof t.output_text=="string"?t.output_text:""}return""}function St(r){if(typeof r.output_text=="string")return r.output_text;let t=[],e=n=>{if(n&&typeof n!="string"){if(Array.isArray(n)){n.forEach(e);return}if(typeof n=="object"){let i=n;typeof i.text=="string"&&t.push(i.text),typeof i.output_text=="string"&&t.push(i.output_text),i.type==="output_text"&&typeof i.content=="string"&&t.push(i.content),i.content&&e(i.content),i.output&&e(i.output)}}};return e(r.output),t.join("")}function Tt(r,t){let n=(Array.isArray(r?.content)?r.content:[]).find(i=>i&&i.type==="tool_use"&&i.name===X);return n?typeof n.input=="string"?S(n.input,t):n.input&&typeof n.input=="object"?H(n.input):[]:null}function kt(r){return(Array.isArray(r.content)?r.content:[]).map(e=>Qe(e)).join("").trim()}function Ft(r){let e=(Array.isArray(r.choices)?r.choices:[])[0]||{},n=e.message;return Qe(n?.content??e.text??"").trim()}function Et(r){let n=((Array.isArray(r.candidates)?r.candidates:[])[0]||{}).content;return(Array.isArray(n?.parts)?n.parts:[]).map(a=>Qe(a)).join("").trim()}function er(r){return r.choices?.[0]?.delta?.content||""}function tr(r){return r.type==="content_block_delta"&&r.delta?.text||""}function Q(r){switch(r){case"openai-chat":return er;case"anthropic-messages":return tr;default:return null}}function et(r,t){let e=[],n=r.replace(/\r\n/g,`
`),i=n.split(`
`),a=n.endsWith(`
`)?"":i.pop()??"",s=n.endsWith(`
`)?i.slice(0,-1):i;for(let c of s){let o=[];for(let l of c.split(`
`)){if(!l.startsWith("data:"))continue;let u=l.slice(l.startsWith("data: ")?6:5);o.push(u)}if(o.length===0)continue;let d=o.join(`
`);if(d.trim()!=="[DONE]")try{let l=JSON.parse(d),u=t(l);u&&e.push(u)}catch{}}return{deltas:e,rest:a}}async function rr(r,t,e,n,i,a,s){let c=await globalThis.fetch(r,{method:"POST",headers:t,body:JSON.stringify(e),signal:a});if(!c.ok){let y=await c.text();throw new Error(C(s||null,"errorProviderApiStatus",{label:"Streaming",status:c.status,excerpt:y.slice(0,500)}))}if(!c.body)throw new Error("Response has no body for streaming");let o=c.body.getReader(),d=new TextDecoder,l="",u="";try{for(;;){let{done:y,value:p}=await o.read();if(y)break;u+=d.decode(p,{stream:!0});let m=et(u,n);u=m.rest;for(let b of m.deltas)l+=b;m.deltas.length>0&&i?.({accumulated:l,done:!1})}}finally{o.releaseLock()}return i?.({accumulated:l,done:!0}),l}async function tt(r,t,e,n,i,a,s){if(typeof globalThis.fetch!="function")throw new Error("Streaming requires fetch API");let c=s?.streamingTimeoutMs??12e4,o=new AbortController,d=null;a&&(a.aborted?o.abort():(d=()=>o.abort(),a.addEventListener("abort",d,{once:!0})));let l=null,u=new Promise((y,p)=>{l=setTimeout(()=>{o.abort(),p(new Error(`Streaming timed out after ${c}ms`))},c)});try{return await Promise.race([rr(r,t,e,n,i,o.signal,s),u])}finally{l!==null&&clearTimeout(l),a&&d&&a.removeEventListener("abort",d)}}function Mt(r){let t=Q(r);if(!t)throw new Error(`Streaming not supported for format: ${r}`);return t}function re(r,t){let e=r.replace(/\/+$/,"");for(let n of t)if(e.endsWith(n))return e;return e+t[0]}function nr(r,t){let e=(r||"").trim();if(!e)return{};if(e.startsWith("{")){let i;try{i=JSON.parse(e)}catch(s){throw new Error(C(t||null,"errorCustomHeadersJsonParse",{error:s.message}))}if(!i||typeof i!="object"||Array.isArray(i))throw new Error(C(t||null,"errorCustomHeadersJsonObject"));let a={};for(let[s,c]of Object.entries(i))typeof c=="string"&&s.trim()&&(a[s.trim()]=c);return a}let n={};for(let i of e.split(/\r?\n/)){let a=i.trim();if(!a||a.startsWith("#"))continue;let s=a.indexOf(":");if(s<=0)throw new Error(C(t||null,"errorCustomHeadersLineFormat"));let c=a.slice(0,s).trim(),o=a.slice(s+1).trim();c&&(n[c]=o)}return n}function ir(r){let t=Le(r);if(t==="none")return{};let e=gt(r);if(!e){let n=(r.apiKeyEnvVar||x(r).envVar||"").trim(),i=n?C(r,"errorApiKeyEnvHint",{envVar:n}):"";throw new Error(C(r,"errorApiKeyMissing",{hint:i}))}return t==="bearer"?{authorization:`Bearer ${e}`}:t==="x-api-key"?{"x-api-key":e}:t==="x-goog-api-key"?{"x-goog-api-key":e}:t==="api-key"?{"api-key":e}:{authorization:`Bearer ${e}`}}function J(r,t){return{"content-type":"application/json",...ir(r),...t||{},...nr(r.apiHeaders,r)}}function ar(r,t,e){if(r.json&&typeof r.json=="object")return r.json;try{return JSON.parse(r.text||"{}")}catch{throw new Error(C(e||null,"errorProviderNonJson",{label:t,excerpt:(r.text||"").slice(0,500)}))}}async function Rt(r,t,e,n,i,a){let s;try{s=await r({url:e,method:"POST",headers:n,body:JSON.stringify(i),throw:!1})}catch(c){throw new Error(C(a||null,"errorProviderRequestFailed",{label:t,error:c.message||String(c)}))}if(s.status>=400)throw new Error(C(a||null,"errorProviderApiStatus",{label:t,status:s.status,excerpt:(s.text||"").slice(0,500)}));return ar(s,t,a)}function sr(r){let t=String(r?.message??r);return/(?:API (?:400|404|422):|API returned HTTP (?:400|404|422)|API 返回 HTTP (?:400|404|422))/.test(t)?/response_format|json_schema|responseJsonSchema|responseMimeType|tools?|tool_choice|unsupported|unrecognized|unknown|schema/i.test(t):!1}async function xe(r,t,e,n,i,a,s){try{return await Rt(r,t,e,n,i,s)}catch(c){if(!a||!sr(c))throw c;return console.warn(`[parallel-reader] ${t} structured output rejected; retrying without structured output`,c),Rt(r,t+" fallback",e,n,a,s)}}function rt(r){let t=x(r),e=T[P(r)];return t.tokenLimitField||e?.tokenLimitField||"max_tokens"}function ee(r,t,e,n){let i=!n||n.structured!==!1,a={model:D(e),max_tokens:Number(e.apiMaxTokens)||4096,system:r,messages:[{role:"user",content:t}]};return i&&(a.tools=[wt()],a.tool_choice={type:"tool",name:X}),a}function te(r,t,e,n){let i=!n||n.structured!==!1,a={model:D(e),messages:[{role:"system",content:r},{role:"user",content:t}]};return a[rt(e)]=Number(e.apiMaxTokens)||4096,i&&(a.response_format=bt()),a}function we(r,t,e,n){let i=!n||n.structured!==!1,a={model:D(e),instructions:r,input:t,max_output_tokens:Number(e.apiMaxTokens)||4096};return i&&(a.text=Ct()),a}function ve(r,t,e,n){let i=!n||n.structured!==!1,a={temperature:0,maxOutputTokens:Number(e.apiMaxTokens)||4096};return i&&(a.responseMimeType="application/json",a.responseJsonSchema=Z(!1)),{systemInstruction:{parts:[{text:r}]},contents:[{role:"user",parts:[{text:t}]}],generationConfig:a}}async function or(r,t,e,n){let i=re(R(n),["/messages"]),a=await xe(r,"Anthropic-compatible",i,J(n,{"anthropic-version":"2023-06-01"}),ee(t,e,n),ee(t,e,n,{structured:!1}),n),s=Tt(a,n);return s||S(kt(a),n)}async function cr(r,t,e,n){let i=re(R(n),["/chat/completions"]),a=await xe(r,"OpenAI-compatible Chat",i,J(n),te(t,e,n),te(t,e,n,{structured:!1}),n);return S(Ft(a),n)}async function lr(r,t,e,n){let i=re(R(n),["/responses"]),a=await xe(r,"OpenAI Responses",i,J(n),we(t,e,n),we(t,e,n,{structured:!1}),n);return S(St(a).trim(),n)}async function ur(r,t,e,n){let i=encodeURIComponent(D(n)),a=R(n);/:generateContent(?:\?|$)/.test(a)||(a=`${a.replace(/\/+$/,"")}/models/${i}:generateContent`);let s=J(n),c=await xe(r,"Google Gemini",a,s,ve(t,e,n),ve(t,e,n,{structured:!1}),n);return S(Et(c),n)}async function ne(r,t,e,n){switch(P(n)){case"openai-chat":return cr(r,t,e,n);case"openai-responses":return lr(r,t,e,n);case"google-generative-ai":return ur(r,t,e,n);default:return or(r,t,e,n)}}function Ae(r){if(!r.streaming)return!1;let t=P(r);return!!Q(t)}async function dr(r,t,e,n,i){let a=re(R(e),["/chat/completions"]),s=J(e),c=te(r,t,e,{structured:!1});c.stream=!0;let o=Mt("openai-chat"),d=await tt(a,s,c,o,n,i,e);return S(d.trim(),e)}async function pr(r,t,e,n,i){let a=re(R(e),["/messages"]),s=J(e,{"anthropic-version":"2023-06-01"}),c=ee(r,t,e,{structured:!1});c.stream=!0;let o=Mt("anthropic-messages"),d=await tt(a,s,c,o,n,i,e);return S(d.trim(),e)}async function Nt(r,t,e,n,i){let a=P(e);switch(a){case"openai-chat":return dr(r,t,e,n,i);case"anthropic-messages":return pr(r,t,e,n,i);default:throw new Error(`Streaming not supported for format: ${a}`)}}async function It(r,t){await ne(r,'\u53EA\u8F93\u51FA JSON\uFF1A{"cards":[]}','\u8FDE\u901A\u6027\u6D4B\u8BD5\uFF1A\u8BF7\u539F\u6837\u8F93\u51FA {"cards":[]}',t);let e=P(t);return`${x(t).label} / ${T[e].label}`}async function nt(r,t,e,n){let{system:i,user:a}=Ce(r,t),s;switch(t.backend){case"claude-code":s=await At(i,a,t,e);break;case"codex":s=await Pt(i,a,t,e);break;default:{if(Ae(t)){let d=new AbortController;e.onCancel(()=>d.abort()),s=await Nt(i,a,t,n,d.signal)}else s=await ne(Dt.requestUrl,i,a,t);break}}let c=s.map(o=>({title:o.title,level:2,anchor:o.anchor,gist:o.gist,startLine:$(r,o.anchor),bullets:o.bullets}));return c.sort((o,d)=>o.startLine<0&&d.startLine<0?0:o.startLine<0?1:d.startLine<0?-1:o.startLine-d.startLine),c}function it(r,t){return t?.phase==="generating"&&r&&De(r.backend)?"cancelRequestedApiInFlight":"cancelRequested"}function at(r){let t=[`## ${r.title}`];if(r.anchor){let e=r.anchor.replace(/\s+/g," ").trim();t.push(`> ${e}`)}return r.gist&&t.push(r.gist),r.bullets&&r.bullets.length>0&&t.push(r.bullets.map(e=>`- ${e}`).join(`
`)),t.join(`
`)}function Lt(r){return[r.title,r.gist||"",...(r.bullets||[]).map(t=>"\u2022 "+t)].filter(Boolean).join(`
`)}function ie(r,t){let e=[`# ${r||"\u5BF9\u7167\u7B14\u8BB0"}`];for(let n of t||[])e.push(at(n));return e.join(`
`)}function Pe(r,t,e){if(!Number.isFinite(t)||t<=0)return-1;let n=Math.floor(t),i=e<0?-1:1;return r<0||r>=n?i<0?n-1:0:Math.min(n-1,Math.max(0,r+i))}function Se(r,t){if(!Array.isArray(r)||t<0||t>=r.length)return-1;let e=Number(r[t]?.startLine);return Number.isFinite(e)&&e>=0?e:-1}function st(r,t=80,e=.1){let n=Number(r?.top)||0,i=Math.max(0,Number(r?.height)||0),a=Math.min(Number(t)||0,i*e);return n+Math.max(0,a)}function hr(r){return typeof requestAnimationFrame=="function"?requestAnimationFrame(r):setTimeout(()=>r(Date.now()),16)}function mr(r){if(typeof cancelAnimationFrame=="function"){cancelAnimationFrame(r);return}clearTimeout(r)}function ot(r,t=hr,e=mr){let n=null,i=()=>{n===null&&(n=t(()=>{n=null,r()}))};return i.cancel=()=>{n!==null&&(e(n),n=null)},i}var g=require("obsidian");async function gr(r){if(r.backend==="claude-code"){let t=L("claude",r.cliPath),{stdout:e}=await O(t,["--version"],"",1e4);return`claude @ ${t}
${e.trim()}`}if(r.backend==="codex"){let t=L("codex",r.cliPath),{stdout:e}=await O(t,["--version"],"",1e4);return`codex @ ${t}
${e.trim()}`}return It(g.requestUrl,r)}var Te=class extends g.PluginSettingTab{constructor(t,e){super(t,e),this.plugin=e}tr(t,e){return this.plugin.t(t,e)}display(){let{containerEl:t}=this;t.empty(),new g.Setting(t).setName(this.tr("settingsTitle")).setHeading(),this.renderGeneralSection(t);let e=this.plugin.settings.backend==="claude-code"||this.plugin.settings.backend==="codex";this.renderBackendSection(t,e),this.renderPromptSection(t,e),this.renderActionsSection(t,e),this.renderCacheSection(t)}renderGeneralSection(t){new g.Setting(t).setName(this.tr("settingUiLanguageName")).setDesc(this.tr("settingUiLanguageDesc")).addDropdown(e=>{for(let[n,i]of Object.entries(Ne))e.addOption(n,i);return e.setValue(this.plugin.settings.uiLanguage||f.uiLanguage).onChange(async n=>{this.plugin.settings.uiLanguage=n,await this.plugin.saveSettings(),this.display()})}),new g.Setting(t).setName(this.tr("settingBackendName")).setDesc(this.tr("settingBackendDesc")).addDropdown(e=>e.addOption("api","API / provider").addOption("claude-code","Claude code CLI").addOption("codex","Codex CLI").setValue(this.plugin.settings.backend).onChange(async n=>{this.plugin.settings.backend=n,n==="api"&&!this.plugin.settings.apiBaseUrl&&(this.plugin.settings=Oe(this.plugin.settings,this.plugin.settings.apiProvider||"anthropic")),await this.plugin.saveSettings(),this.display()}))}renderBackendSection(t,e){if(e){new g.Setting(t).setName(this.tr("settingCliPathName")).setDesc(this.tr("settingCliPathDesc")).addText(i=>i.setPlaceholder(this.tr("settingCliPathPlaceholder")).setValue(this.plugin.settings.cliPath).onChange(a=>{this.plugin.settings.cliPath=a.trim(),this.plugin.saveSettingsDebounced()}));return}let n=x(this.plugin.settings);new g.Setting(t).setName(this.tr("apiProviderHeader")).setHeading(),new g.Setting(t).setName(this.tr("settingProviderPresetName")).setDesc(this.tr("settingProviderPresetDesc")).addDropdown(i=>{for(let[a,s]of Object.entries(M))i.addOption(a,s.label);return i.setValue(this.plugin.settings.apiProvider).onChange(async a=>{this.plugin.settings=Oe(this.plugin.settings,a),await this.plugin.saveSettings(),this.display()})}),new g.Setting(t).setName(this.tr("settingApiFormatName")).setDesc(this.tr("settingApiFormatDesc")).addDropdown(i=>{for(let[a,s]of Object.entries(T))i.addOption(a,s.label);return i.setValue(P(this.plugin.settings)).onChange(async a=>{this.plugin.settings.apiFormat=a,await this.plugin.saveSettings(),this.display()})}),new g.Setting(t).setName(this.tr("settingBaseUrlName")).setDesc(this.tr("settingBaseUrlDesc")).addText(i=>i.setPlaceholder((this.plugin.settings.apiProvider||"").startsWith("custom-")?"https://your-provider.example/v1":n.baseUrl||T[P(this.plugin.settings)].defaultBaseUrl).setValue(this.plugin.settings.apiBaseUrl).onChange(a=>{this.plugin.settings.apiBaseUrl=a.trim(),this.plugin.saveSettingsDebounced()})),new g.Setting(t).setName(this.tr("settingApiKeyName")).setDesc(this.tr("settingApiKeyDesc")).addText(i=>(i.inputEl.type="password",i.setValue(this.plugin.settings.apiKey).onChange(a=>{this.plugin.settings.apiKey=a.trim(),this.plugin.saveSettingsDebounced()}))),new g.Setting(t).setName(this.tr("settingApiKeyEnvName")).setDesc(this.tr("settingApiKeyEnvDesc")).addText(i=>i.setPlaceholder(n.envVar||"OPENAI_API_KEY").setValue(this.plugin.settings.apiKeyEnvVar).onChange(a=>{this.plugin.settings.apiKeyEnvVar=a.trim(),this.plugin.saveSettingsDebounced()})),new g.Setting(t).setName(this.tr("settingAuthTypeName")).setDesc(this.tr("settingAuthTypeDesc")).addDropdown(i=>{for(let[a,s]of Object.entries(Ie))i.addOption(a,s);return i.setValue(this.plugin.settings.apiAuthType||"auto").onChange(async a=>{this.plugin.settings.apiAuthType=a,await this.plugin.saveSettings()})}),new g.Setting(t).setName(this.tr("settingHeadersName")).setDesc(this.tr("settingHeadersDesc")).addTextArea(i=>i.setValue(this.plugin.settings.apiHeaders).onChange(a=>{this.plugin.settings.apiHeaders=a,this.plugin.saveSettingsDebounced()})),new g.Setting(t).setName(this.tr("settingMaxTokensName")).addText(i=>i.setValue(String(this.plugin.settings.apiMaxTokens)).onChange(a=>{let s=parseInt(a,10);!Number.isNaN(s)&&s>0&&(this.plugin.settings.apiMaxTokens=s,this.plugin.saveSettingsDebounced())})),new g.Setting(t).setName(this.tr("settingStreamingName")).setDesc(this.tr("settingStreamingDesc")).addToggle(i=>i.setValue(this.plugin.settings.streaming??!0).onChange(async a=>{this.plugin.settings.streaming=a,await this.plugin.saveSettings()})),new g.Setting(t).setName(this.tr("settingStreamingTimeoutName")).setDesc(this.tr("settingStreamingTimeoutDesc")).addText(i=>i.setPlaceholder(String(f.streamingTimeoutMs)).setValue(String(this.plugin.settings.streamingTimeoutMs||f.streamingTimeoutMs)).onChange(a=>{this.plugin.settings.streamingTimeoutMs=q(a),this.plugin.saveSettingsDebounced()}))}renderPromptSection(t,e){new g.Setting(t).setName(this.tr("settingModelName")).setDesc(e?this.tr("settingModelDescCli"):this.tr("settingModelDescApi")).addText(n=>n.setPlaceholder(e?f.model:x(this.plugin.settings).model||"Model-id").setValue(this.plugin.settings.model).onChange(i=>{this.plugin.settings.model=i.trim()||(e?f.model:""),this.plugin.saveSettingsDebounced()})),new g.Setting(t).setName(this.tr("settingMaxInputName")).setDesc(this.tr("settingMaxInputDesc")).addText(n=>n.setValue(String(this.plugin.settings.maxDocChars||f.maxDocChars)).onChange(i=>{let a=parseInt(i,10);!Number.isNaN(a)&&a>=1e3&&(this.plugin.settings.maxDocChars=a,this.plugin.saveSettingsDebounced())})),new g.Setting(t).setName(this.tr("promptHeader")).setHeading(),new g.Setting(t).setName(this.tr("settingPromptLanguageName")).setDesc(this.tr("settingPromptLanguageDesc")).addDropdown(n=>{for(let[i,a]of Object.entries(K))n.addOption(i,a);return n.setValue(this.plugin.settings.promptLanguage||f.promptLanguage).onChange(async i=>{this.plugin.settings.promptLanguage=i,await this.plugin.saveSettings()})}),new g.Setting(t).setName(this.tr("settingCardRangeName")).setDesc(this.tr("settingCardRangeDesc")).addText(n=>n.setPlaceholder("Min").setValue(String(this.plugin.settings.minCards||f.minCards)).onChange(i=>{let a=parseInt(i,10);!Number.isNaN(a)&&a>0&&(this.plugin.settings.minCards=a,this.plugin.settings.maxCards<a&&(this.plugin.settings.maxCards=a),this.plugin.saveSettingsDebounced())})).addText(n=>n.setPlaceholder("Max").setValue(String(this.plugin.settings.maxCards||f.maxCards)).onChange(i=>{let a=parseInt(i,10);!Number.isNaN(a)&&a>0&&(this.plugin.settings.maxCards=Math.max(a,this.plugin.settings.minCards||f.minCards),this.plugin.saveSettingsDebounced())})),new g.Setting(t).setName(this.tr("settingCustomPromptName")).setDesc(this.tr("settingCustomPromptDesc")).addTextArea(n=>(n.inputEl.rows=8,n.setPlaceholder(this.tr("settingCustomPromptPlaceholder")).setValue(this.plugin.settings.customSystemPrompt||"").onChange(i=>{this.plugin.settings.customSystemPrompt=i,this.plugin.saveSettingsDebounced()})))}renderActionsSection(t,e){new g.Setting(t).setName(this.tr("settingTestBackendName")).setDesc(e?this.tr("settingTestBackendDescCli"):this.tr("settingTestBackendDescApi")).addButton(n=>n.setButtonText("Test").onClick(async()=>{try{let i=await gr(this.plugin.settings);new g.Notice(`\u2713 ${i.slice(0,180)}`,8e3)}catch(i){new g.Notice(this.tr("backendTestFailed",{error:i.message}),1e4)}})),new g.Setting(t).setName(this.tr("settingExportFolderName")).setDesc(this.tr("settingExportFolderDesc")).addText(n=>n.setValue(this.plugin.settings.exportFolder).onChange(i=>{this.plugin.settings.exportFolder=i.trim()||f.exportFolder,this.plugin.saveSettingsDebounced()}))}renderCacheSection(t){new g.Setting(t).setName(this.tr("cacheHeader")).setHeading(),new g.Setting(t).setName(this.tr("settingMaxCacheName")).setDesc(this.tr("settingMaxCacheDesc")).addText(n=>{n.setValue(String(this.plugin.settings.maxCacheEntries||G));let i=async()=>{let a=parseInt(n.getValue(),10);if(Number.isFinite(a)&&a>0){this.plugin.settings.maxCacheEntries=a,await this.plugin.saveSettings();let s=await this.plugin.pruneCacheIfNeeded();s.length>0&&new g.Notice(this.tr("cachePruned",{count:s.length})),this.display()}};return n.inputEl.addEventListener("change",()=>{i()}),n.inputEl.addEventListener("keydown",a=>{a.key==="Enter"&&n.inputEl.blur()}),n});let e=Object.keys(this.plugin.cache).length;new g.Setting(t).setName(this.tr("cachedNotesName",{count:e})).setDesc(this.tr("cachedNotesDesc")).addButton(n=>n.setButtonText(this.tr("clearAllCacheButton")).setWarning().onClick(async()=>{let i=Object.keys(this.plugin.cache).length;await this.plugin.cacheClear(),new g.Notice(this.tr("cacheClearedAll",{count:i})),this.display()}))}};var F=require("obsidian");function N(r,t,e,n){let i=r.createEl("button",{cls:"parallel-reader-icon-button",attr:{type:"button","aria-label":e}});return i.title=e,typeof F.setIcon=="function"?(0,F.setIcon)(i,t):i.textContent=e,i.addEventListener("click",a=>{a.preventDefault(),a.stopPropagation(),Promise.resolve(n()).catch(s=>{console.error(s),new F.Notice(`${e} failed: ${s instanceof Error?s.message:String(s)}`)})}),i}function E(r,t,e,n,i){let a=r.createEl("button",{cls:i||"parallel-reader-text-button",attr:{type:"button"}});return t&&typeof F.setIcon=="function"&&(0,F.setIcon)(a,t),a.createSpan({text:e}),a.addEventListener("click",s=>{s.preventDefault(),s.stopPropagation(),Promise.resolve(n()).catch(c=>{console.error(c),new F.Notice(`${e} failed: ${c instanceof Error?c.message:String(c)}`)})}),a}async function I(r,t){try{await navigator.clipboard.writeText(r),new F.Notice(t)}catch(e){new F.Notice(`Copy failed: ${e instanceof Error?e.message:String(e)}`)}}function ct(r){return String(r||"").split("/").map(t=>t.trim()).filter(t=>!!t&&t!==".."&&t!==".").join("/")}function lt(r){let t=ct(r);if(!t)return[];let e=t.split("/");return e.map((n,i)=>e.slice(0,i+1).join("/"))}async function Ot(r,t){for(let e of lt(t))if(!r.vault.getAbstractFileByPath(e))try{await r.vault.createFolder(e)}catch(n){if(!r.vault.getAbstractFileByPath(e))throw n}}var A=require("obsidian");var Bt=require("obsidian");var ke=class extends Bt.Modal{constructor(t,e,n,i){super(t),this.plugin=e,this.card=n||{},this.onSave=i}onOpen(){let{contentEl:t}=this;t.empty(),t.createEl("h2",{text:this.plugin.t("editCardTitle")});let e=this.createLabeledInput(t,this.plugin.t("editCardTitleField"),this.card.title||""),n=this.createLabeledTextarea(t,this.plugin.t("editCardGistField"),this.card.gist||"",3),i=this.createLabeledTextarea(t,this.plugin.t("editCardBulletsField"),(this.card.bullets||[]).join(`
`),8),a=t.createDiv({cls:"parallel-reader-modal-actions"});E(a,null,this.plugin.t("editCardCancel"),()=>this.close(),"parallel-reader-text-button"),E(a,null,this.plugin.t("editCardSave"),async()=>{await this.onSave({title:e.value.trim()||this.card.title||"",gist:n.value.trim(),bullets:i.value.split(/\r?\n/).map(s=>s.trim()).filter(Boolean)}),this.close()},"parallel-reader-text-button")}createLabeledInput(t,e,n){let i=t.createDiv({cls:"parallel-reader-modal-field"});i.createEl("label",{text:e});let a=i.createEl("input",{attr:{type:"text"}});return a.value=n,a}createLabeledTextarea(t,e,n,i){let a=t.createDiv({cls:"parallel-reader-modal-field"});a.createEl("label",{text:e});let s=a.createEl("textarea");return s.rows=i,s.value=n,s}};var B="parallel-reader-view",Fe=class extends A.ItemView{constructor(e,n){super(e);this.stale=!1;this.loadingMessage="";this.errorMessage="";this.plugin=n,this.sections=[],this.sourceFile=null,this.cards=[],this.activeIdx=-1}getViewType(){return B}getDisplayText(){return this.plugin.t("displayName")}getIcon(){return"book-open"}onOpen(){let e=this.containerEl.children[1];return e.empty(),e.addClass("parallel-reader-container"),e.setAttr("tabindex","0"),e.addEventListener("keydown",n=>this.handleKeydown(n)),this.renderEmpty(),this.focusSummaryPane(),Promise.resolve()}onClose(){return Promise.resolve()}renderEmpty(){this.sourceFile=null,this.sections=[],this.stale=!1,this.loadingMessage="",this.errorMessage="";let e=this.containerEl.children[1];e.empty();let n=e.createDiv({cls:"parallel-reader-empty"});n.createEl("h3",{text:this.plugin.t("appTitle")}),n.createEl("p",{text:this.plugin.t("emptyOpenNote")}),n.createEl("code",{text:this.plugin.t("commandGenerate")})}focusSummaryPane(){let e=this.containerEl.children[1];return!e||typeof e.focus!="function"?!1:(e.focus({preventScroll:!0}),!0)}loadFor(e,n,i){this.sourceFile=e,this.sections=n,this.stale=!!i,this.loadingMessage="",this.errorMessage="",this.render()}renderLoading(e,n){this.sourceFile=e,this.sections=[],this.stale=!1,this.loadingMessage=n||this.plugin.t("loadingDefault"),this.errorMessage="",this.render()}renderStreamingPreview(e,n){this.sourceFile?.path!==e.path&&(this.sourceFile=e);let i=this.containerEl.children[1],a=i.querySelector(".parallel-reader-streaming-preview");if(a){let y=a.querySelector("pre");y&&(y.textContent=n.slice(-2e3));let p=a.querySelector(".parallel-reader-stream-counter");p&&(p.textContent=`${n.length} chars`);return}i.empty();let c=i.createDiv({cls:"parallel-reader-header"}).createDiv({cls:"parallel-reader-header-row"});c.createEl("div",{text:e.basename,cls:"parallel-reader-title"});let o=c.createDiv({cls:"parallel-reader-actions"});N(o,"square",this.plugin.t("actionCancel"),()=>{this.plugin.cancelGenerationForFile(e)});let d=i.createDiv({cls:"parallel-reader-state parallel-reader-loading parallel-reader-streaming-preview"});d.createDiv({cls:"parallel-reader-spinner"});let l=d.createEl("div",{cls:"parallel-reader-state-title"});l.createSpan({text:this.plugin.t("loadingGenerating")+" "}),l.createSpan({cls:"parallel-reader-stream-counter",text:`${n.length} chars`});let u=d.createEl("pre",{cls:"parallel-reader-stream-text"});u.textContent=n.slice(-2e3)}renderError(e,n){this.sourceFile=e,this.sections=[],this.stale=!1,this.loadingMessage="",this.errorMessage=n||this.plugin.t("errorTitle"),this.render()}renderEmptyWithHint(e){this.sourceFile=e,this.sections=[],this.stale=!1,this.loadingMessage="",this.errorMessage="";let n=this.containerEl.children[1];n.empty();let i=n.createDiv({cls:"parallel-reader-empty"});i.createEl("h3",{text:e.basename}),i.createEl("p",{text:this.plugin.t("emptyNoCache")}),i.createEl("code",{text:this.plugin.t("commandGenerate")}),E(i,null,this.plugin.t("actionGenerate"),()=>{this.plugin.isGeneratingFile(e)||this.plugin.runForFile(e,!1)})}render(){let e=this.containerEl.children[1];e.empty();let i=e.createDiv({cls:"parallel-reader-header"}).createDiv({cls:"parallel-reader-header-row"});i.createEl("div",{text:this.sourceFile?.basename||"",cls:"parallel-reader-title"});let a=i.createDiv({cls:"parallel-reader-actions"});if(this.sourceFile&&(this.plugin.isGeneratingFile(this.sourceFile)?N(a,"square",this.plugin.t("actionCancel"),()=>{this.plugin.cancelGenerationForFile(this.sourceFile)}):N(a,"refresh-cw",this.plugin.t("actionRegenerate"),()=>this.plugin.runForFile(this.sourceFile,!0)),N(a,"copy",this.plugin.t("actionCopyAll"),()=>this.plugin.copyCurrentViewMarkdown()),N(a,"download",this.plugin.t("actionExport"),()=>this.exportToVault())),this.stale){let o=e.createDiv({cls:"parallel-reader-stale-banner"});o.createSpan({text:this.plugin.t("staleBanner")}),E(o,"refresh-cw",this.plugin.t("actionRegenerate"),()=>this.plugin.runForFile(this.sourceFile,!0),"parallel-reader-stale-button")}if(this.loadingMessage){let o=e.createDiv({cls:"parallel-reader-state parallel-reader-loading"});o.createDiv({cls:"parallel-reader-spinner"}),o.createEl("div",{text:this.loadingMessage,cls:"parallel-reader-state-title"}),o.createEl("div",{text:this.plugin.t("loadingSubtitle"),cls:"parallel-reader-state-subtitle"});return}if(this.errorMessage){let o=e.createDiv({cls:"parallel-reader-state parallel-reader-error"});o.createEl("div",{text:this.plugin.t("errorTitle"),cls:"parallel-reader-state-title"}),o.createEl("div",{text:this.errorMessage,cls:"parallel-reader-state-subtitle parallel-reader-selectable"});let d=o.createDiv({cls:"parallel-reader-error-actions"});E(d,"refresh-cw",this.plugin.t("actionRegenerate"),()=>this.plugin.runForFile(this.sourceFile,!0),"parallel-reader-text-button"),E(d,"copy",this.plugin.t("actionCopyError"),()=>I(this.errorMessage,this.plugin.t("actionCopyError")),"parallel-reader-text-button");return}let s=e.createDiv({cls:"parallel-reader-cards"});this.cards=[];let c=this.sourceFile?.path||"";this.sections.forEach((o,d)=>{let l=s.createDiv({cls:"parallel-reader-card"});l.dataset.idx=String(d),o.startLine<0&&l.addClass("parallel-reader-card-unanchored");let u=l.createEl("div",{cls:"parallel-reader-card-title"});if(u.createSpan({text:o.title}),o.startLine<0&&u.createEl("span",{text:" \u26A0",cls:"parallel-reader-warn",title:this.plugin.t("anchorMismatch")}),o.gist){let p=l.createEl("div",{cls:"parallel-reader-gist"});A.MarkdownRenderer.render(this.app,o.gist,p,c,this).catch(()=>{p.setText(o.gist)})}let y=o.bullets||[];if(y.length>0){let p=l.createEl("div",{cls:"parallel-reader-bullets-md"}),m=y.map(b=>`- ${b}`).join(`
`);A.MarkdownRenderer.render(this.app,m,p,c,this).catch(()=>{p.setText(m)})}else o.gist||l.createEl("div",{cls:"parallel-reader-empty-li",text:this.plugin.t("emptyCard")});l.addEventListener("click",p=>{let m=window.getSelection();if(m&&m.toString().length>0)return;let b=p.target;b&&b.tagName==="A"||o.startLine>=0&&this.plugin.scrollEditorToLine(o.startLine,this.sourceFile)}),l.addEventListener("contextmenu",p=>{p.preventDefault();let m=new A.Menu;m.addItem(b=>b.setTitle(this.plugin.t("menuCopyMarkdown")).setIcon("copy").onClick(()=>I(at(o),this.plugin.t("copiedMarkdown")))),m.addItem(b=>b.setTitle(this.plugin.t("menuCopyPlain")).setIcon("clipboard-copy").onClick(()=>I(Lt(o),this.plugin.t("copiedPlain")))),o.anchor&&m.addItem(b=>b.setTitle(this.plugin.t("menuCopyAnchor")).setIcon("quote-glyph").onClick(()=>I(o.anchor,this.plugin.t("copiedAnchor")))),m.addSeparator(),o.startLine>=0&&m.addItem(b=>b.setTitle(this.plugin.t("menuJumpSource")).setIcon("arrow-right").onClick(()=>this.plugin.scrollEditorToLine(o.startLine,this.sourceFile))),m.addSeparator(),m.addItem(b=>b.setTitle(this.plugin.t("menuEditCard")).setIcon("pencil").onClick(()=>this.openEditCardModal(d))),m.addItem(b=>b.setTitle(this.plugin.t("menuDeleteCard")).setIcon("trash").onClick(()=>this.deleteCard(d))),m.showAtMouseEvent(p)}),this.cards.push(l)}),this.activeIdx>=0&&this.cards[this.activeIdx]&&this.cards[this.activeIdx].addClass("is-active")}setActiveSection(e){e!==this.activeIdx&&(this.activeIdx>=0&&this.cards[this.activeIdx]&&this.cards[this.activeIdx].removeClass("is-active"),this.activeIdx=e,e>=0&&this.cards[e]&&(this.cards[e].addClass("is-active"),this.cards[e].scrollIntoView({block:"nearest",behavior:"smooth"})))}moveActiveSection(e){let n=Pe(this.activeIdx,this.sections.length,e);return this.setActiveSection(n),this.focusSummaryPane(),n}jumpToActiveSection(){let e=Se(this.sections,this.activeIdx);return e<0||!this.sourceFile?-1:(this.plugin.scrollEditorToLine(e,this.sourceFile),e)}handleKeydown(e){if(e.altKey&&e.key==="ArrowUp"){e.preventDefault(),this.moveActiveSection(-1);return}if(e.altKey&&e.key==="ArrowDown"){e.preventDefault(),this.moveActiveSection(1);return}!e.altKey&&!e.metaKey&&!e.ctrlKey&&!e.shiftKey&&e.key==="Enter"&&this.jumpToActiveSection()>=0&&e.preventDefault()}async deleteCard(e){if(!this.sourceFile)return!1;let n=ge(this.sections,e);if(n.length===this.sections.length)return!1;let i=this.sections.length;return this.sections=n,this.activeIdx=fe(e,i,this.activeIdx),await this.plugin.cacheReplaceCards(this.sourceFile.path,n),this.render(),new A.Notice(this.plugin.t("cardDeleted")),!0}openEditCardModal(e){return!this.sourceFile||!this.sections[e]?!1:(new ke(this.app,this.plugin,this.sections[e],async n=>{await this.updateCard(e,n)}).open(),!0)}async updateCard(e,n){if(!this.sourceFile)return!1;let i=ye(this.sections,e,n);return i.length!==this.sections.length?!1:(this.sections=i,await this.plugin.cacheReplaceCards(this.sourceFile.path,i),this.render(),new A.Notice(this.plugin.t("cardSaved")),!0)}async exportToVault(){if(!this.sourceFile)return;let e=ct(this.plugin.settings.exportFolder),n=`${this.sourceFile.basename} - ${this.plugin.t("displayName")}.md`,i=`${e}/${n}`,a=["---",`source: [[${this.sourceFile.basename}]]`,`generated: ${new Date().toISOString().slice(0,10)}`,"tool: parallel-reader","---","",ie(`${this.sourceFile.basename} \xB7 ${this.plugin.t("displayName")}`,this.sections),""].join(`
`),s=this.plugin.app;await Ot(s,e);let c=s.vault.getAbstractFileByPath(i);c instanceof A.TFile?await s.vault.modify(c,a):await s.vault.create(i,a),new A.Notice(this.plugin.t("exported",{path:i}))}};var ut=class extends h.Plugin{constructor(){super(...arguments);this.activeBatch=null;this._scrollDispose=null;this._settingsSaveTimer=null}get cache(){return this.cacheManager.cache}t(e,n){return C(this.settings||f,e,n)}async onload(){await this.loadSettings(),this.jobs=new Y,this.addRibbonIcon("book-open",this.t("ribbonOpen"),async()=>{let e=this.getActiveView();await this.ensureView()&&e?.file&&await this.syncViewToFile(e.file)}),this.registerView(B,e=>new Fe(e,this)),this.addCommand({id:"run",name:this.t("cmdRun"),callback:()=>this.runForActiveFile(!1)}),this.addCommand({id:"regen",name:this.t("cmdRegen"),callback:()=>this.runForActiveFile(!0)}),this.addCommand({id:"open-view",name:this.t("cmdOpenView"),callback:async()=>{let e=this.getActiveView();await this.ensureView()&&e?.file&&this.syncViewToFile(e.file)}}),this.addCommand({id:"export-current",name:this.t("cmdExport"),callback:()=>this.exportCurrentView()}),this.addCommand({id:"copy-current-markdown",name:this.t("cmdCopyMarkdown"),callback:()=>this.copyCurrentViewMarkdown()}),this.addCommand({id:"cancel-current",name:this.t("cmdCancel"),callback:()=>this.cancelActiveGeneration()}),this.addCommand({id:"clear-current",name:this.t("cmdClearCurrent"),callback:async()=>{let e=this.getActiveView();if(!e?.file){new h.Notice(this.t("noCurrentNote"));return}await this.cacheManager.delete(e.file.path),new h.Notice(this.t("cacheClearedFile",{name:e.file.basename}))}}),this.addCommand({id:"clear-all",name:this.t("cmdClearAll"),callback:async()=>{let e=Object.keys(this.cacheManager.cache).length;await this.cacheManager.clear(),new h.Notice(this.t("cacheClearedAll",{count:e}))}}),this.addCommand({id:"card-prev",name:this.t("cmdCardPrev"),callback:()=>this.moveActiveCard(-1)}),this.addCommand({id:"card-next",name:this.t("cmdCardNext"),callback:()=>this.moveActiveCard(1)}),this.addCommand({id:"card-jump",name:this.t("cmdCardJump"),callback:()=>this.jumpActiveCard()}),this.addCommand({id:"batch-generate",name:this.t("cmdBatchGenerate"),callback:()=>this.runBatchForFolder()}),this.addSettingTab(new Te(this.app,this)),this.registerEvent(this.app.workspace.on("active-leaf-change",()=>this.bindScrollSync())),this.registerEvent(this.app.workspace.on("file-open",e=>{e&&this.syncViewToFile(e)})),this.registerEvent(this.app.workspace.on("file-menu",(e,n)=>this.addFileMenuItems(e,n))),this.registerEvent(this.app.vault.on("rename",(e,n)=>{e instanceof h.TFile&&this.handleFileRename(e,n)})),this.registerEvent(this.app.vault.on("delete",e=>{e instanceof h.TFile&&this.handleFileDelete(e)})),this.bindScrollSync()}onunload(){this.flushSettingsSave(),this.flushCacheSave()}async loadSettings(){let n=(await this.loadData()||{}).settings||{};this.settings=le(Object.assign({},f,n)),this.cacheManager=new W(this.app.vault.adapter,this.app.vault.configDir,this.manifest?.id||"parallel-reader",()=>this.settings),await this.cacheManager.load()}async saveSettings(){this._settingsSaveTimer&&(clearTimeout(this._settingsSaveTimer),this._settingsSaveTimer=null),await this.saveData({settings:this.settings})}saveSettingsDebounced(e=400){this._settingsSaveTimer&&clearTimeout(this._settingsSaveTimer),this._settingsSaveTimer=setTimeout(()=>{this._settingsSaveTimer=null,this.saveSettings().catch(n=>console.error("[parallel-reader] failed to save settings",n))},e)}async flushSettingsSave(){this._settingsSaveTimer&&(clearTimeout(this._settingsSaveTimer),this._settingsSaveTimer=null,await this.saveSettings())}cacheTouch(e){return this.cacheManager.touch(e)}scheduleCacheSave(e=5e3){this.cacheManager.scheduleSave(e)}async flushCacheSave(){await this.cacheManager.flush()}async cacheReplaceCards(e,n){return this.cacheManager.replaceCards(e,n)}async cacheClear(){return this.cacheManager.clear()}async pruneCacheIfNeeded(){return this.cacheManager.pruneIfNeeded()}async ensureView(){let{workspace:e}=this.app,n=e.getLeavesOfType(B)[0];if(!n){let i=e.getRightLeaf(!1);if(!i)return new h.Notice(this.t("viewOpenFailed")),null;n=i,await n.setViewState({type:B,active:!0})}return await e.revealLeaf(n),n.view}getActiveView(){return this.app.workspace.getActiveViewOfType(h.MarkdownView)}getParallelView(){return this.app.workspace.getLeavesOfType(B)[0]?.view}moveActiveCard(e){let n=this.getParallelView();return n?.sections.length?n.moveActiveSection(e):(new h.Notice(this.t("noActiveCard")),-1)}jumpActiveCard(){let e=this.getParallelView();return!e||e.jumpToActiveSection()<0?(new h.Notice(this.t("noActiveCard")),!1):!0}isGeneratingFile(e){return!!e&&!!e.path&&this.jobs.isRunning(e.path)}cancelGenerationForFile(e){if(!e?.path)return new h.Notice(this.t("noCancelableJob")),!1;let n=this.jobs.get(e.path),i=it(this.settings,n),a=this.jobs.cancel(e.path);return a&&this.activeBatch?.currentPath===e.path&&pe(this.activeBatch),new h.Notice(a?this.t(i):this.t("noCancelableJob")),a}requestBatchCancellation(){return pe(this.activeBatch)}viewIsShowingFile(e,n){return!!e&&!!n&&e.sourceFile?.path===n.path}activeFileStillMatches(e){let n=this.getActiveView();return!n?.file||n.file.path===e.path}cancelActiveGeneration(){if(this.requestBatchCancellation()){let i=this.activeBatch?.currentPath;i&&this.jobs.cancel(i),new h.Notice(this.t("batchCancelRequested"));return}let e=this.getActiveView();if(e?.file&&this.cancelGenerationForFile(e.file))return;let n=this.getParallelView();n?.sourceFile?this.cancelGenerationForFile(n.sourceFile):new h.Notice(this.t("noCancelableJob"))}confirmRegenerateEditedCards(){return new Promise(e=>{let n=this.t("confirmRegenerateEditedCards"),i=new h.Modal(this.app);i.titleEl.setText(this.t("displayName")),i.contentEl.createEl("p",{text:n});let a=i.contentEl.createDiv({cls:"modal-button-container"});a.createEl("button",{text:"Cancel"}).addEventListener("click",()=>{i.close(),e(!1)}),a.createEl("button",{text:"OK",cls:"mod-cta"}).addEventListener("click",()=>{i.close(),e(!0)}),i.onClose=()=>e(!1),i.open()})}addFileMenuItems(e,n){!(n instanceof h.TFile)||!n.path.endsWith(".md")||(e.addSeparator(),e.addItem(i=>i.setTitle(this.t("fileMenuGenerate")).setIcon("book-open").onClick(()=>this.runForFile(n,!1))),e.addItem(i=>i.setTitle(this.t("fileMenuRegen")).setIcon("refresh-cw").onClick(()=>this.runForFile(n,!0))),this.cacheManager.get(n.path)&&e.addItem(i=>i.setTitle(this.t("fileMenuClear")).setIcon("trash").onClick(async()=>{await this.cacheManager.delete(n.path),new h.Notice(this.t("cacheClearedFile",{name:n.basename}))})))}async handleFileRename(e,n){if(!(e instanceof h.TFile)||!n)return;let i=n.endsWith(".md"),a=e.path.endsWith(".md");if(!i&&!a)return;if(i&&!a){await this.cacheManager.delete(n);let c=this.getParallelView();c&&c.sourceFile?.path===n&&c.renderEmpty();return}if(!i)return;await this.cacheManager.move(n,e.path);let s=this.getParallelView();s?.sourceFile&&(s.sourceFile.path===n||s.sourceFile.path===e.path)&&(s.sourceFile=e,await this.syncViewToFile(e))}async handleFileDelete(e){if(!(e instanceof h.TFile))return;await this.cacheManager.delete(e.path);let n=this.getParallelView();n?.sourceFile?.path===e.path&&n.renderEmpty()}async exportCurrentView(){let e=this.getActiveView(),n=await this.ensureView();if(n){if((!n.sourceFile||!n.sections.length)&&e?.file&&await this.syncViewToFile(e.file),!n.sourceFile||!n.sections.length){new h.Notice(this.t("noExportContent"));return}await n.exportToVault()}}async copyCurrentViewMarkdown(){let e=this.getActiveView(),n=await this.ensureView();if(n){if((!n.sourceFile||!n.sections.length)&&e?.file&&await this.syncViewToFile(e.file),!n.sourceFile||!n.sections.length){new h.Notice(this.t("noCopyContent"));return}await I(ie(`${n.sourceFile.basename} \xB7 ${this.t("displayName")}`,n.sections),this.t("copiedAllMarkdown"))}}async runForActiveFile(e){let n=this.getActiveView();if(!n?.file){new h.Notice(this.t("openNoteFirst"));return}return this.runForFile(n.file,e)}async runForFile(e,n){if(!e){new h.Notice(this.t("openNoteFirst"));return}if(this.jobs.isRunning(e.path)){new h.Notice(this.t("alreadyGenerating"));return}if(ze(this.cacheManager.get(e.path),n)&&!await this.confirmRegenerateEditedCards()){new h.Notice(this.t("regenerateCancelled"));return}let i=null;return this.jobs.start(e.path,async a=>{a.setPhase("reading");let s=await this.app.vault.read(e);if(a.throwIfCancelled(),!s.trim()){new h.Notice(this.t("emptyNote"));return}if(i=await this.ensureView(),!i)return;if(a.throwIfCancelled(),a.setPhase("cache-check"),!n){let p=this.cacheManager.get(e.path);if(p&&U(p,s,this.settings)){this.cacheTouch(e.path),this.activeFileStillMatches(e)&&i.loadFor(e,this.resolveCardAnchors(s,p.cards),!1);return}}i.renderLoading(e,this.t("loadingGenerating"));let c=Number(this.settings.maxDocChars)||f.maxDocChars;s.length>c&&new h.Notice(this.t("longNoteTruncated",{count:c})),new h.Notice(this.t("generatingNotice")),a.setPhase("generating");let o=i,d=o?p=>{!p.done&&this.viewIsShowingFile(o,e)&&o.renderStreamingPreview(e,p.accumulated)}:void 0,l=await nt(s,this.settings,a,d);if(a.throwIfCancelled(),l.length===0){new h.Notice(this.t("noCardsReturned"));return}let u=l.map(p=>({title:p.title,anchor:p.anchor,gist:p.gist,bullets:p.bullets}));a.setPhase("saving"),await this.cacheManager.put(e.path,s,u,this.settings),a.throwIfCancelled(),this.viewIsShowingFile(i,e)&&i.loadFor(e,l,!1);let y=l.filter(p=>p.startLine<0).length;new h.Notice(this.t("generationDone",{count:l.length,suffix:y?this.t("unanchoredSuffix",{count:y}):""}))}).catch(a=>{if(a instanceof j){new h.Notice(a.message);return}if(a instanceof k){i&&this.viewIsShowingFile(i,e)&&i.renderError(e,this.t("cancelledError")),new h.Notice(this.t("cancelled"));return}let s=Ye(a),c=a instanceof Error?a.message:String(a);console.error(a),i&&this.viewIsShowingFile(i,e)&&i.renderError(e,c),new h.Notice(this.t("generationFailed",{kind:s==="unknown"?"":` (${s})`,error:c}))})}async runBatchForFolder(){if(this.activeBatch){new h.Notice(this.t("batchAlreadyRunning"));return}let e=this.t("batchSelectFolder"),n=this.t("batchFolderPrompt"),i=await new Promise(l=>{let u=new h.Modal(this.app);u.onOpen=()=>{u.contentEl.createEl("p",{text:e});let p=u.contentEl.createDiv({cls:"parallel-reader-modal-field"}).createEl("input",{type:"text"});p.placeholder=n,p.addEventListener("keydown",m=>{m.key==="Enter"&&(l(p.value.trim()),u.close())}),u.contentEl.createEl("button",{text:"OK"}).addEventListener("click",()=>{l(p.value.trim()),u.close()})},u.onClose=()=>l(null),u.open()});if(i===null)return;let a=_e(i,l=>{let u=this.app.vault.getAbstractFileByPath(l);return!!u&&!(u instanceof h.TFile)});if(!a.valid){let l=a.reason==="unsafe"?"batchInvalidFolderInput":"batchFolderNotFound";new h.Notice(this.t(l,{path:a.folderPath||i}));return}let s=Ve(this.app.vault.getMarkdownFiles(),a.folderPath);if(s.length===0){new h.Notice(this.t("batchNoMarkdown"));return}let c=Ke();this.activeBatch=c;let o=Ue(s.length);try{for(let l=0;l<s.length&&!c.cancelled;l++){let u=s[l];qe(c,u.path),new h.Notice(this.t("batchProgress",Ge(l,s.length)));let y=await this.app.vault.read(u);if(c.cancelled)break;let p=this.cacheManager.get(u.path);if($e(p,y,this.settings)){o=He(o);continue}try{await this.runForFile(u,!1),o=je(o)}catch(m){o=Je(o),console.error("[parallel-reader] batch error for",u.path,m)}}}finally{this.activeBatch===c&&(this.activeBatch=null)}let d={processed:o.processed,skipped:o.skipped,errors:o.errors,total:o.total};c.cancelled?new h.Notice(this.t("batchCancelled",d)):new h.Notice(this.t("batchDone",d))}resolveCardAnchors(e,n){let i=(n||[]).map(a=>({title:a.title,level:2,anchor:a.anchor,gist:a.gist,startLine:$(e,a.anchor),bullets:a.bullets||[]}));return i.sort((a,s)=>a.startLine<0&&s.startLine<0?0:a.startLine<0?1:s.startLine<0?-1:a.startLine-s.startLine),i}async syncViewToFile(e){if(!e?.path?.endsWith(".md"))return;let n=this.app.workspace.getLeavesOfType(B);if(n.length===0)return;let i=n[0].view;if(!i||!this.activeFileStillMatches(e))return;let a=this.cacheManager.get(e.path);if(!a){i.loadFor(e,[],!1),i.renderEmptyWithHint(e);return}let s=await this.app.vault.read(e);if(!this.activeFileStillMatches(e))return;let c=!U(a,s,this.settings);this.cacheTouch(e.path),i.loadFor(e,this.resolveCardAnchors(s,a.cards),c)}bindScrollSync(){this._scrollDispose&&(this._scrollDispose(),this._scrollDispose=null);let e=this.getActiveView();if(!e)return;let n=e.editor,i=n&&n.cm,a=i?.scrollDOM?i.scrollDOM:e.contentEl.querySelector(".cm-scroller");if(!a)return;let s=ot(()=>this.handleEditorScroll(e));a.addEventListener("scroll",s,{passive:!0}),this._scrollDispose=()=>{s.cancel(),a.removeEventListener("scroll",s)}}handleEditorScroll(e){let n=this.getParallelView();if(!n||!e.file||n.sourceFile?.path!==e.file.path)return;let i=e.editor,a=i&&i.cm;if(!a?.scrollDOM)return;let s=a.scrollDOM.getBoundingClientRect(),c=st(s),o=0;try{let l=a.posAtCoords({x:s.left+20,y:c});l!=null&&(o=a.state.doc.lineAt(l).number-1)}catch{return}let d=-1;for(let l=0;l<n.sections.length;l++){let u=n.sections[l];if(!(u.startLine<0))if(u.startLine<=o)d=l;else break}n.setActiveSection(d)}findLeafForFile(e){if(!e)return null;for(let n of this.app.workspace.getLeavesOfType("markdown")){let i=n.view;if(i?.file&&i.file.path===e.path)return n}return null}async scrollEditorToLine(e,n){let i=n?this.findLeafForFile(n):null;if(!i&&n&&(i=this.app.workspace.getLeaf("tab"),await i.openFile(n,{active:!1})),!i){let s=this.getActiveView();s&&(i=s.leaf)}if(!i){new h.Notice(this.t("noEditor"));return}this.app.workspace.setActiveLeaf(i,{focus:!0});let a=i.view;if(a instanceof h.MarkdownView&&(a.setEphemeralState({line:e}),a.editor))try{a.editor.setCursor({line:e,ch:0}),a.editor.scrollIntoView({from:{line:e,ch:0},to:{line:e,ch:0}},!0)}catch{}}},fr=ut,yr={CACHE_SCHEMA_VERSION:V,GenerationJobAlreadyRunningError:j,GenerationJobCancelledError:k,GenerationJobManager:Y,addIconButton:N,addTextButton:E,activeIndexAfterCardDelete:fe,activeSectionLine:Se,buildAnthropicMessagesBody:ee,buildGeminiBody:ve,buildOpenAiChatBody:te,buildOpenAiResponsesBody:we,batchProgressVars:Ge,buildPrompts:Ce,cardsToMarkdown:ie,CacheManager:W,cacheEntryMatches:U,cancellationNoticeKey:it,classifyGenerationError:Ye,copyToClipboard:I,createRafThrottledHandler:ot,createBatchRunState:Ke,extractJson:Xe,repairTruncatedCardsJson:Ze,findLineForAnchor:$,folderPathsForTarget:lt,createBatchStats:Ue,generationFingerprint:z,getApiBaseUrl:R,hasUnsafeBatchFolderSegments:Be,markBatchFileRunning:qe,modelForApi:D,normalizeBatchFolderInput:de,normalizeCardsPayload:H,normalizeSettings:le,normalizeStreamingTimeoutMs:q,nextCardIndex:Pe,pruneCacheEntries:ue,recordBatchError:Je,recordBatchProcessed:je,recordBatchSkip:He,requestBatchCancel:pe,removeCardAt:ge,resolveCliPath:L,runCli:O,serializeCacheFile:me,shouldConfirmRegenerate:ze,shouldSkipBatchFile:$e,selectBatchFiles:Ve,summarizeDocument:nt,summarizeViaApi:ne,touchCacheEntry:he,translate:C,tokenLimitFieldForOpenAiChat:rt,updateCardAt:ye,validateBatchFolderInput:_e,visibleTopProbeY:st,supportsStreaming:Ae,deltaExtractorForFormat:Q,parseSseBuffer:et};0&&(module.exports={__test});