fancive_obsidian-parallel-r.../main.js
wujunchen 9e369ae1fa refactor: remove CLI backends, add Chinese README
Remove Claude Code CLI and Codex CLI backends — they depend on
unstable CLI flags and macOS Keychain ACLs. API backend is now the
only path, default provider is Anthropic.

Replace English README with Chinese version focused on API usage.
Add .agent/ to .gitignore.

Change-Id: I7b2488d9bca23e753cc3d461f5f7bc39052dcbef
2026-04-26 09:57:30 +08:00

92 lines
81 KiB
JavaScript

'use strict';
"use strict";var ot=Object.create;var W=Object.defineProperty;var lt=Object.getOwnPropertyDescriptor;var ct=Object.getOwnPropertyNames;var ut=Object.getPrototypeOf,pt=Object.prototype.hasOwnProperty;var dt=(t,n)=>{for(var e in n)W(t,e,{get:n[e],enumerable:!0})},je=(t,n,e,r)=>{if(n&&typeof n=="object"||typeof n=="function")for(let a of ct(n))!pt.call(t,a)&&a!==e&&W(t,a,{get:()=>n[a],enumerable:!(r=lt(n,a))||r.enumerable});return t};var Y=(t,n,e)=>(e=t!=null?ot(ut(t)):{},je(n||!t||!t.__esModule?W(e,"default",{value:t,enumerable:!0}):e,t)),ht=t=>je(W({},"__esModule",{value:!0}),t);var Ht={};dt(Ht,{__test:()=>Gt,default:()=>jt});module.exports=ht(Ht);var d=require("obsidian");function X(t,n){if(!n)return-1;let e=u=>u.replace(/\s+/g," ").trim(),r=u=>{let h=[],C=[],m=!1;for(let f=0;f<u.length;f++){let Ue=u[f];if(/\s/.test(Ue)){m=h.length>0;continue}m&&(h.push(" "),C.push(f),m=!1),h.push(Ue),C.push(f)}return{text:h.join(""),map:C}},a=u=>{if(!u)return-1;let h=t.indexOf(u);if(h===-1)return-1;let C=0;for(let m=0;m<h;m++)t[m]===`
`&&C++;return C},i=a(n);if(i>=0||(i=a(n.trim()),i>=0))return i;for(let u of[60,40,25,15]){let h=n.trim().slice(0,u);if(i=a(h),i>=0)return i}let s=r(t),o=e(n).slice(0,30);if(!o)return-1;let l=s.text.indexOf(o);if(l===-1)return-1;let p=s.map[l];if(p==null)return-1;let c=0;for(let u=0;u<p;u++)t[u]===`
`&&c++;return c}function me(t,n){return t?(t.lastAccessedAt=n||new Date().toISOString(),t):null}function ge(t){return JSON.stringify({version:1,entries:t||{}})}function fe(t,n){return!!n&&!!t&&typeof t.updatedAt=="string"&&t.updatedAt.trim().length>0}function Z(t,n){let e=Array.isArray(t)?t.slice():[];return!Number.isInteger(n)||n<0||n>=e.length||e.splice(n,1),e}function Q(t,n,e){if(!Number.isInteger(t)||!Number.isInteger(n)||n<=0||!Number.isInteger(e)||e<0||t<0||t>=n)return e;let r=n-1;return r<=0?-1:t<e?Math.max(0,e-1):t===e?Math.min(e,r-1):e}function ee(t,n,e){let r=Array.isArray(t)?t.slice():[];return!Number.isInteger(n)||n<0||n>=r.length||(r[n]=Object.assign({},r[n],e||{})),r}var ft=require("child_process"),Ke=Y(require("fs")),$e=Y(require("os")),F=Y(require("path"));var L=class extends Error{constructor(n){super("\u8BE5\u7B14\u8BB0\u6B63\u5728\u751F\u6210\u5BF9\u7167\u7B14\u8BB0"),this.name="GenerationJobAlreadyRunningError",this.code="already-running",this.key=n}},P=class extends Error{constructor(n){super("\u751F\u6210\u5DF2\u53D6\u6D88"),this.name="GenerationJobCancelledError",this.code="cancelled",this.key=n}},ye=class{constructor(n){this.key=n,this.phase="queued",this.cancelled=!1,this.startedAt=new Date().toISOString(),this.updatedAt=this.startedAt,this._cancelHandlers=[]}setPhase(n){this.phase=n,this.updatedAt=new Date().toISOString()}onCancel(n){if(typeof n=="function"){if(this.cancelled){n();return}this._cancelHandlers.push(n)}}cancel(){if(this.cancelled)return!1;this.cancelled=!0,this.setPhase("cancelled");for(let n of this._cancelHandlers.splice(0))try{n()}catch{}return!0}throwIfCancelled(){if(this.cancelled)throw new P(this.key)}},U=class{constructor(){this.jobs=new Map}get(n){return this.jobs.get(n)||null}isRunning(n){return this.jobs.has(n)}async start(n,e){if(this.jobs.has(n))throw new L(n);let r=new ye(n);this.jobs.set(n,r);try{r.setPhase("running");let a=await e(r);return r.throwIfCancelled(),a}catch(a){throw r.cancelled&&!(a instanceof P)?new P(n):a}finally{this.jobs.delete(n)}}cancel(n){let e=this.jobs.get(n);return e?e.cancel():!1}};function Ce(t){if(t instanceof P)return"cancelled";let n=t;if(n?.code==="cancelled")return"cancelled";let e=String(n?.message||t);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 te={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",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",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",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"},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",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.",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",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)"}};function mt(t){let n=t?.uiLanguage;return n==="zh"||n==="en"?n:String((typeof navigator<"u"?navigator:null)?.language||"").toLowerCase().startsWith("zh")?"zh":"en"}function b(t,n,e){let r=mt(t),a=te[r]||te.en,i=te.en[n]||te.zh[n]||n,s=a[n]||i;return String(s).replace(/\{([a-zA-Z0-9_]+)\}/g,(o,l)=>e&&Object.hasOwn(e,l)?String(e[l]):o)}var re="record_parallel_reader_cards";function gt(t){let n=[],e=-1,r=0,a=!1,i=!1;for(let s=0;s<t.length;s++){let o=t[s];if(a){i?i=!1:o==="\\"?i=!0:o==='"'&&(a=!1);continue}o==='"'?a=!0:o==="{"?(r===0&&(e=s),r++):o==="}"&&(r>0&&r--,r===0&&e>=0&&(n.push(t.slice(e,s+1)),e=-1))}return n}function be(t){let n=(t||"").trim();if(!n)return n;try{return JSON.parse(n),n}catch{}let e=n.match(/```(?:json)?\s*([\s\S]*?)```/);if(e){let a=e[1].trim();try{return JSON.parse(a),a}catch{}}let r=gt(n);r.sort((a,i)=>i.length-a.length);for(let a of r)try{return JSON.parse(a),a}catch{}return n}function T(t,n){let e=be(t),r;try{r=JSON.parse(e)}catch{throw new Error(b(n||null,"errorLlmNonJson",{excerpt:(t||"").slice(0,500)}))}return j(r)}function j(t){return(t&&Array.isArray(t.cards)?t.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(r=>typeof r=="string"):[]}))}function G(t){let n={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:n}},required:["cards"]};return t&&(n.additionalProperties=!1,e.additionalProperties=!1),e}function Ge(){return{type:"json_schema",json_schema:{name:"parallel_reader_cards",strict:!0,schema:G(!0)}}}function He(){return{format:{type:"json_schema",name:"parallel_reader_cards",strict:!0,schema:G(!0)}}}function Je(){return{name:re,description:"Return the generated Parallel Reader summary cards.",input_schema:G(!0)}}function ze(t,n){if(n?.trim())return n.trim();let e=$e.default.homedir(),r=[F.default.join(e,"bin",t),F.default.join(e,".local/bin",t),F.default.join(e,".claude/local",t),F.default.join(e,".codex/bin",t),F.default.join(e,".bun/bin",t),F.default.join(e,".npm-global/bin",t),F.default.join(e,".cargo/bin",t),"/opt/homebrew/bin/"+t,"/usr/local/bin/"+t];for(let a of r)try{if(Ke.default.existsSync(a))return a}catch{}return t}function we(t){let n=[`## ${t.title}`];if(t.anchor){let e=t.anchor.replace(/\s+/g," ").trim();n.push(`> ${e}`)}return t.gist&&n.push(t.gist),t.bullets&&t.bullets.length>0&&n.push(t.bullets.map(e=>`- ${e}`).join(`
`)),n.join(`
`)}function qe(t){return[t.title,t.gist||"",...(t.bullets||[]).map(n=>"\u2022 "+n)].filter(Boolean).join(`
`)}function H(t,n){let e=[`# ${t||"\u5BF9\u7167\u7B14\u8BB0"}`];for(let r of n||[])e.push(we(r));return e.join(`
`)}function ne(t,n,e){if(!Number.isFinite(n)||n<=0)return-1;let r=Math.floor(n),a=e<0?-1:1;return t<0||t>=r?a<0?r-1:0:Math.min(r-1,Math.max(0,t+a))}function ae(t,n){if(!Array.isArray(t)||n<0||n>=t.length)return-1;let e=Number(t[n]?.startLine);return Number.isFinite(e)&&e>=0?e:-1}var Xe=Y(require("crypto"));var Ae=2e4,yt=2,J=2,_=100,K={zh:"\u4E2D\u6587",en:"English",auto:"Auto-detect"},xe={auto:"Auto",zh:"\u4E2D\u6587",en:"English"},y={uiLanguage:"auto",backend:"api",cliPath:"",apiProvider:"anthropic",apiFormat:"anthropic-messages",apiBaseUrl:"",apiKey:"",apiKeyEnvVar:"",apiAuthType:"auto",apiHeaders:"",apiMaxTokens:4096,maxDocChars:Ae,maxCacheEntries:_,promptLanguage:"zh",minCards:5,maxCards:15,customSystemPrompt:"",model:"claude-sonnet-4-6",exportFolder:"Reading/Articles",cliTimeoutMs:12e4,streaming:!0},x={"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"}},Pe={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"},k={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 O(t){return Xe.default.createHash("sha1").update(t,"utf8").digest("hex")}function ve(t){return Array.isArray(t)?"["+t.map(ve).join(",")+"]":t&&typeof t=="object"?"{"+Object.keys(t).sort().map(n=>JSON.stringify(n)+":"+ve(t[n])).join(",")+"}":JSON.stringify(t)}function Se(t){return t==="api"||t==="anthropic-api"}function w(t){return k[t.apiProvider]||k.anthropic}function A(t){let n=w(t),e=(t.apiFormat||n.format||"").trim();return x[e]?e:n.format}function E(t){let n=A(t),e=w(t),r=(t.apiBaseUrl||"").trim();if(r)return r.replace(/\/+$/,"");if((t.apiProvider||"").startsWith("custom-"))throw new Error(b(t,"errorCustomProviderBaseUrlRequired"));let a=(e.baseUrl||x[n].defaultBaseUrl||"").trim();if(!a)throw new Error(b(t,"errorApiBaseUrlMissing"));return a.replace(/\/+$/,"")}function Te(t){let n=(t.apiAuthType||"auto").trim();if(n&&n!=="auto")return n;let e=w(t),r=A(t);return e.authType||x[r].defaultAuthType||"bearer"}function Ze(t){let n=(t.apiKey||"").trim();if(n)return n;let e=(t.apiKeyEnvVar||w(t).envVar||"").trim();return e&&process.env?.[e]?String(process.env[e]).trim():""}function M(t){let n=(t.model||"").trim();if(!n)throw new Error(b(t,"errorModelMissing"));let e=w(t),r=[t.apiProvider,e.modelPrefix].map(i=>(i||"").trim()).filter(Boolean),a=n.toLowerCase();for(let i of r){let s=i.toLowerCase();if(a.startsWith(s+"/"))return n.slice(i.length+1).trim()}return n}function Qe(t,n){let e=w(t),r=k[n]||k.anthropic,a=(t.model||"").trim(),i=!a||a===y.model||!!e.model&&a===e.model;t.apiProvider=n,t.apiFormat=r.format,t.apiBaseUrl=r.baseUrl,t.apiAuthType=r.authType||"auto",t.apiKeyEnvVar=r.envVar||"",i&&(t.model=r.model||"")}function Ee(t){xe[t.uiLanguage]||(t.uiLanguage=y.uiLanguage),(!t.apiProvider||!k[t.apiProvider])&&(t.apiProvider="anthropic");let n=w(t);(!t.apiFormat||!x[t.apiFormat])&&(t.apiFormat=n.format),(!t.apiAuthType||!Pe[t.apiAuthType])&&(t.apiAuthType="auto"),t.backend==="anthropic-api"&&(t.apiProvider=t.apiProvider||"anthropic",t.apiFormat=t.apiFormat||"anthropic-messages",t.apiBaseUrl=t.apiBaseUrl||k.anthropic.baseUrl,t.apiAuthType=t.apiAuthType||"x-api-key",t.apiKeyEnvVar=t.apiKeyEnvVar||"ANTHROPIC_API_KEY");let e=Number(t.apiMaxTokens);(!Number.isFinite(e)||e<=0)&&(t.apiMaxTokens=y.apiMaxTokens);let r=Number(t.maxDocChars);return(!Number.isFinite(r)||r<1e3)&&(t.maxDocChars=y.maxDocChars),t.maxCacheEntries=et(t.maxCacheEntries),K[t.promptLanguage]||(t.promptLanguage=y.promptLanguage),t.minCards=We(t.minCards,y.minCards),t.maxCards=We(t.maxCards,y.maxCards),t.maxCards<t.minCards&&(t.maxCards=t.minCards),typeof t.customSystemPrompt!="string"&&(t.customSystemPrompt=""),t}function We(t,n){let e=Math.floor(Number(t));return Number.isFinite(e)?Math.min(30,Math.max(1,e)):n}function et(t){let n=Math.floor(Number(t));return!Number.isFinite(n)||n<=0?_:n}function Ye(t){let n=t&&(t.lastAccessedAt||t.generatedAt||t.updatedAt),e=Date.parse(n||"");return Number.isFinite(e)?e:0}function Fe(t,n){if(!t||typeof t!="object")return[];let e=et(n),r=Object.entries(t);if(r.length<=e)return[];let a=r.sort(([i,s],[o,l])=>Ye(s)-Ye(l)||i.localeCompare(o)).slice(0,r.length-e).map(([i])=>i);for(let i of a)delete t[i];return a}function ie(t){let n=Ee(Object.assign({},y,t||{})),e=Se(n.backend),r=w(n),a=A(n),i=e?(n.apiBaseUrl||r.baseUrl||x[a]?.defaultBaseUrl||"").trim().replace(/\/+$/,""):"";return O(ve({cacheSchemaVersion:J,promptVersion:yt,maxDocChars:Number(n.maxDocChars)||y.maxDocChars,promptLanguage:n.promptLanguage,minCards:n.minCards,maxCards:n.maxCards,customSystemPromptHash:O(n.customSystemPrompt||""),backend:n.backend,model:n.model,apiProvider:e?n.apiProvider:"",apiFormat:e?a:"",apiBaseUrl:i,apiAuthType:e?Te(n):"",apiHeadersHash:e?O(n.apiHeaders||""):"",apiMaxTokens:e?Number(n.apiMaxTokens)||y.apiMaxTokens:0,structuredOutputVersion:1}))}function se(t,n,e){return!!t&&t.schemaVersion===J&&t.contentHash===O(n)&&t.settingsHash===ie(e)}function Ct(t){return t==="en"?"Write title, gist, and bullets in English.":t==="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 bt(t){return t==="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 wt(t,n){return String(t||"").replace(/\{([a-zA-Z0-9_]+)\}/g,(e,r)=>Object.hasOwn(n,r)?String(n[r]):e)}function vt(t,n,e,r,a,i){return t==="en"?`You are a long-form reading summary assistant. After reading the full document, split it into ${n}-${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:
- ${r}
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:
${a}
Example:
${i}`:`\u4F60\u662F\u4E00\u4E2A\u957F\u6587\u9605\u8BFB\u6458\u8981\u52A9\u624B\u3002\u9605\u8BFB\u5168\u6587\u540E\uFF0C\u628A\u6587\u7AE0\u5207\u6210 ${n}-${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
- ${r}
\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
${a}
\u793A\u4F8B\uFF1A
${i}`}function At(t,n,e,r,a){return t==="en"?`Non-overridable output contract:
- Must output ${n}-${e} cards.
- ${r}
- 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: ${a}`:`\u4E0D\u53EF\u8986\u76D6\u7684\u8F93\u51FA\u5951\u7EA6\uFF1A
- \u5FC5\u987B\u8F93\u51FA ${n}-${e} \u5F20 cards\u3002
- ${r}
- 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: ${a}`}function ke(t,n){let e=Number(n.maxDocChars)||Ae,r=K[n.promptLanguage]?n.promptLanguage:y.promptLanguage,a=Math.max(1,Number(n.minCards)||y.minCards),i=Math.max(a,Number(n.maxCards)||y.maxCards),s=Ct(r),o=t.length>e?t.slice(0,e)+(r==="en"?`
[Document truncated]`:`
[\u6587\u6863\u8FC7\u957F\uFF0C\u5DF2\u622A\u65AD]`):t,l='{"cards":[{"title":"...","anchor":"...","gist":"...","bullets":["...","..."]}]}',p=bt(r),c={minCards:a,maxCards:i,languageInstruction:s,schema:l,example:p},u=wt(n.customSystemPrompt,c).trim(),h=At(r,a,i,s,l),C=vt(r,a,i,s,l,p),m=u?`${u}
${h}`:C,f=r==="en"?`Source document:
${o}`:`\u4EE5\u4E0B\u662F\u9700\u8981\u5904\u7406\u7684\u6587\u6863\u5168\u6587\uFF1A
${o}`;return{system:m,user:f}}function xt(t){return t.choices?.[0]?.delta?.content||""}function Pt(t){return t.type==="content_block_delta"&&t.delta?.text||""}function V(t){switch(t){case"openai-chat":return xt;case"anthropic-messages":return Pt;default:return null}}function Ne(t,n){let e=[],r=t.split(`
`),a=r.pop();for(let i of r){let s=i.trim();if(!s||s==="data: [DONE]"||s.startsWith("event:")||!s.startsWith("data:"))continue;let o=s.slice(s.startsWith("data: ")?6:5);try{let l=JSON.parse(o),p=n(l);p&&e.push(p)}catch{}}return{deltas:e,rest:a}}async function De(t,n,e,r,a,i,s){if(typeof globalThis.fetch!="function")throw new Error("Streaming requires fetch API");let o=await globalThis.fetch(t,{method:"POST",headers:n,body:JSON.stringify(e),signal:i});if(!o.ok){let h=await o.text();throw new Error(b(s||null,"errorProviderApiStatus",{label:"Streaming",status:o.status,excerpt:h.slice(0,500)}))}if(!o.body)throw new Error("Response has no body for streaming");let l=o.body.getReader(),p=new TextDecoder,c="",u="";try{for(;;){let{done:h,value:C}=await l.read();if(h)break;u+=p.decode(C,{stream:!0});let m=Ne(u,r);u=m.rest;for(let f of m.deltas)c+=f;m.deltas.length>0&&a?.({accumulated:c,done:!1})}}finally{l.releaseLock()}return a?.({accumulated:c,done:!0}),c}function q(t,n){let e=t.replace(/\/+$/,"");for(let r of n)if(e.endsWith(r))return e;return e+n[0]}function St(t,n){let e=(t||"").trim();if(!e)return{};if(e.startsWith("{")){let a;try{a=JSON.parse(e)}catch(s){throw new Error(b(n||null,"errorCustomHeadersJsonParse",{error:s.message}))}if(!a||typeof a!="object"||Array.isArray(a))throw new Error(b(n||null,"errorCustomHeadersJsonObject"));let i={};for(let[s,o]of Object.entries(a))typeof o=="string"&&s.trim()&&(i[s.trim()]=o);return i}let r={};for(let a of e.split(/\r?\n/)){let i=a.trim();if(!i||i.startsWith("#"))continue;let s=i.indexOf(":");if(s<=0)throw new Error(b(n||null,"errorCustomHeadersLineFormat"));let o=i.slice(0,s).trim(),l=i.slice(s+1).trim();o&&(r[o]=l)}return r}function Tt(t){let n=Te(t);if(n==="none")return{};let e=Ze(t);if(!e){let r=(t.apiKeyEnvVar||w(t).envVar||"").trim(),a=r?b(t,"errorApiKeyEnvHint",{envVar:r}):"";throw new Error(b(t,"errorApiKeyMissing",{hint:a}))}return n==="bearer"?{authorization:`Bearer ${e}`}:n==="x-api-key"?{"x-api-key":e}:n==="x-goog-api-key"?{"x-goog-api-key":e}:n==="api-key"?{"api-key":e}:{authorization:`Bearer ${e}`}}function B(t,n){return{"content-type":"application/json",...Tt(t),...n||{},...St(t.apiHeaders,t)}}function Et(t,n,e){if(t.json&&typeof t.json=="object")return t.json;try{return JSON.parse(t.text||"{}")}catch{throw new Error(b(e||null,"errorProviderNonJson",{label:n,excerpt:(t.text||"").slice(0,500)}))}}async function tt(t,n,e,r,a,i){let s;try{s=await t({url:e,method:"POST",headers:r,body:JSON.stringify(a),throw:!1})}catch(o){throw new Error(b(i||null,"errorProviderRequestFailed",{label:n,error:o.message||o}))}if(s.status>=400)throw new Error(b(i||null,"errorProviderApiStatus",{label:n,status:s.status,excerpt:(s.text||"").slice(0,500)}));return Et(s,n,i)}function Ft(t){let n=String(t?.message?t.message:t);return/(?:API (?:400|404|422):|API returned HTTP (?:400|404|422)|API 返回 HTTP (?:400|404|422))/.test(n)?/response_format|json_schema|responseJsonSchema|responseMimeType|tools?|tool_choice|unsupported|unrecognized|unknown|schema/i.test(n):!1}async function ce(t,n,e,r,a,i,s){try{return await tt(t,n,e,r,a,s)}catch(o){if(!i||!Ft(o))throw o;return console.warn(`[parallel-reader] ${n} structured output rejected; retrying without structured output`,o),tt(t,n+" fallback",e,r,i,s)}}function Re(t){return typeof t=="string"?t:Array.isArray(t)?t.map(n=>typeof n=="string"?n:n&&typeof n=="object"&&(n.text||n.output_text)||"").join(""):t&&typeof t=="object"&&(t.text||t.output_text)||""}function kt(t){if(typeof t.output_text=="string")return t.output_text;let n=[],e=r=>{if(r&&typeof r!="string"){if(Array.isArray(r)){r.forEach(e);return}typeof r=="object"&&(typeof r.text=="string"&&n.push(r.text),typeof r.output_text=="string"&&n.push(r.output_text),r.type==="output_text"&&typeof r.content=="string"&&n.push(r.content),r.content&&e(r.content),r.output&&e(r.output))}};return e(t.output),n.join("")}function Me(t){let n=w(t),e=x[A(t)];return n.tokenLimitField||e?.tokenLimitField||"max_tokens"}function $(t,n,e,r){let a=!r||r.structured!==!1,i={model:M(e),max_tokens:Number(e.apiMaxTokens)||4096,system:t,messages:[{role:"user",content:n}]};return a&&(i.tools=[Je()],i.tool_choice={type:"tool",name:re}),i}function z(t,n,e,r){let a=!r||r.structured!==!1,i={model:M(e),messages:[{role:"system",content:t},{role:"user",content:n}]};return i[Me(e)]=Number(e.apiMaxTokens)||4096,a&&(i.response_format=Ge()),i}function oe(t,n,e,r){let a=!r||r.structured!==!1,i={model:M(e),instructions:t,input:n,max_output_tokens:Number(e.apiMaxTokens)||4096};return a&&(i.text=He()),i}function le(t,n,e,r){let a=!r||r.structured!==!1,i={temperature:0,maxOutputTokens:Number(e.apiMaxTokens)||4096};return a&&(i.responseMimeType="application/json",i.responseJsonSchema=G(!1)),{systemInstruction:{parts:[{text:t}]},contents:[{role:"user",parts:[{text:n}]}],generationConfig:i}}function Nt(t,n){let r=(Array.isArray(t?.content)?t.content:[]).find(a=>a&&a.type==="tool_use"&&a.name===re);return r?typeof r.input=="string"?T(r.input,n):r.input&&typeof r.input=="object"?j(r.input):[]:null}async function Dt(t,n,e,r){let a=q(E(r),["/messages"]),i=await ce(t,"Anthropic-compatible",a,B(r,{"anthropic-version":"2023-06-01"}),$(n,e,r),$(n,e,r,{structured:!1}),r),s=Nt(i,r);if(s)return s;let o=(i.content||[]).map(l=>Re(l)).join("").trim();return T(o,r)}async function Rt(t,n,e,r){let a=q(E(r),["/chat/completions"]),s=((await ce(t,"OpenAI-compatible Chat",a,B(r),z(n,e,r),z(n,e,r,{structured:!1}),r)).choices||[])[0]||{},o=Re(s.message?.content||s.text||"").trim();return T(o,r)}async function Mt(t,n,e,r){let a=q(E(r),["/responses"]),i=await ce(t,"OpenAI Responses",a,B(r),oe(n,e,r),oe(n,e,r,{structured:!1}),r);return T(kt(i).trim(),r)}async function It(t,n,e,r){let a=encodeURIComponent(M(r)),i=E(r);/:generateContent(?:\?|$)/.test(i)||(i=`${i.replace(/\/+$/,"")}/models/${a}:generateContent`);let s=B(r),c=((((await ce(t,"Google Gemini",i,s,le(n,e,r),le(n,e,r,{structured:!1}),r)).candidates||[])[0]||{}).content?.parts||[]).map(u=>Re(u)).join("").trim();return T(c,r)}async function ue(t,n,e,r){switch(A(r)){case"openai-chat":return Rt(t,n,e,r);case"openai-responses":return Mt(t,n,e,r);case"google-generative-ai":return It(t,n,e,r);default:return Dt(t,n,e,r)}}function Ie(t){if(!t.streaming)return!1;let n=A(t);return!!V(n)}async function Lt(t,n,e,r,a){let i=q(E(e),["/chat/completions"]),s=B(e),o=z(t,n,e,{structured:!1});o.stream=!0;let l=V("openai-chat"),p=await De(i,s,o,l,r,a,e);return T(p.trim(),e)}async function Ot(t,n,e,r,a){let i=q(E(e),["/messages"]),s=B(e,{"anthropic-version":"2023-06-01"}),o=$(t,n,e,{structured:!1});o.stream=!0;let l=V("anthropic-messages"),p=await De(i,s,o,l,r,a,e);return T(p.trim(),e)}async function rt(t,n,e,r,a){let i=A(e);switch(i){case"openai-chat":return Lt(t,n,e,r,a);case"anthropic-messages":return Ot(t,n,e,r,a);default:throw new Error(`Streaming not supported for format: ${i}`)}}async function nt(t,n){await ue(t,'\u53EA\u8F93\u51FA JSON\uFF1A{"cards":[]}','\u8FDE\u901A\u6027\u6D4B\u8BD5\uFF1A\u8BF7\u539F\u6837\u8F93\u51FA {"cards":[]}',n);let e=A(n);return`${w(n).label} / ${x[e].label}`}function Le(t,n=80,e=.1){let r=Number(t?.top)||0,a=Math.max(0,Number(t?.height)||0),i=Math.min(Number(n)||0,a*e);return r+Math.max(0,i)}function _t(t){return typeof requestAnimationFrame=="function"?requestAnimationFrame(t):setTimeout(()=>t(Date.now()),16)}function Vt(t){if(typeof cancelAnimationFrame=="function"){cancelAnimationFrame(t);return}clearTimeout(t)}function Oe(t,n=_t,e=Vt){let r=null,a=()=>{r===null&&(r=n(()=>{r=null,t()}))};return a.cancel=()=>{r!==null&&(e(r),r=null)},a}var g=require("obsidian");async function Bt(t){return nt(g.requestUrl,t)}var pe=class extends g.PluginSettingTab{constructor(n,e){super(n,e),this.plugin=e}display(){let{containerEl:n}=this,e=(a,i)=>this.plugin.t(a,i);n.empty(),n.createEl("h2",{text:e("settingsTitle")}),new g.Setting(n).setName(e("settingUiLanguageName")).setDesc(e("settingUiLanguageDesc")).addDropdown(a=>{for(let[i,s]of Object.entries(xe))a.addOption(i,s);return a.setValue(this.plugin.settings.uiLanguage||y.uiLanguage).onChange(async i=>{this.plugin.settings.uiLanguage=i,await this.plugin.saveSettings(),this.display()})}),n.createEl("h3",{text:e("apiProviderHeader")});{let a=w(this.plugin.settings);new g.Setting(n).setName(e("settingProviderPresetName")).setDesc(e("settingProviderPresetDesc")).addDropdown(i=>{for(let[s,o]of Object.entries(k))i.addOption(s,o.label);return i.setValue(this.plugin.settings.apiProvider).onChange(async s=>{Qe(this.plugin.settings,s),await this.plugin.saveSettings(),this.display()})}),new g.Setting(n).setName(e("settingApiFormatName")).setDesc(e("settingApiFormatDesc")).addDropdown(i=>{for(let[s,o]of Object.entries(x))i.addOption(s,o.label);return i.setValue(A(this.plugin.settings)).onChange(async s=>{this.plugin.settings.apiFormat=s,await this.plugin.saveSettings(),this.display()})}),new g.Setting(n).setName(e("settingBaseUrlName")).setDesc(e("settingBaseUrlDesc")).addText(i=>i.setPlaceholder((this.plugin.settings.apiProvider||"").startsWith("custom-")?"https://your-provider.example/v1":a.baseUrl||x[A(this.plugin.settings)].defaultBaseUrl).setValue(this.plugin.settings.apiBaseUrl).onChange(async s=>{this.plugin.settings.apiBaseUrl=s.trim(),this.plugin.saveSettingsDebounced()})),new g.Setting(n).setName(e("settingApiKeyName")).setDesc(e("settingApiKeyDesc")).addText(i=>(i.inputEl.type="password",i.setPlaceholder("sk-...").setValue(this.plugin.settings.apiKey).onChange(async s=>{this.plugin.settings.apiKey=s.trim(),this.plugin.saveSettingsDebounced()}))),new g.Setting(n).setName(e("settingApiKeyEnvName")).setDesc(e("settingApiKeyEnvDesc")).addText(i=>i.setPlaceholder(a.envVar||"OPENAI_API_KEY").setValue(this.plugin.settings.apiKeyEnvVar).onChange(async s=>{this.plugin.settings.apiKeyEnvVar=s.trim(),this.plugin.saveSettingsDebounced()})),new g.Setting(n).setName(e("settingAuthTypeName")).setDesc(e("settingAuthTypeDesc")).addDropdown(i=>{for(let[s,o]of Object.entries(Pe))i.addOption(s,o);return i.setValue(this.plugin.settings.apiAuthType||"auto").onChange(async s=>{this.plugin.settings.apiAuthType=s,await this.plugin.saveSettings()})}),new g.Setting(n).setName(e("settingHeadersName")).setDesc(e("settingHeadersDesc")).addTextArea(i=>i.setPlaceholder("cf-aig-authorization: Bearer ...").setValue(this.plugin.settings.apiHeaders).onChange(async s=>{this.plugin.settings.apiHeaders=s,this.plugin.saveSettingsDebounced()})),new g.Setting(n).setName(e("settingMaxTokensName")).addText(i=>i.setValue(String(this.plugin.settings.apiMaxTokens)).onChange(async s=>{let o=parseInt(s,10);!Number.isNaN(o)&&o>0&&(this.plugin.settings.apiMaxTokens=o,this.plugin.saveSettingsDebounced())})),new g.Setting(n).setName(e("settingStreamingName")).setDesc(e("settingStreamingDesc")).addToggle(i=>i.setValue(this.plugin.settings.streaming??!0).onChange(async s=>{this.plugin.settings.streaming=s,await this.plugin.saveSettings()}))}new g.Setting(n).setName(e("settingModelName")).setDesc(e("settingModelDescApi")).addText(a=>a.setPlaceholder(w(this.plugin.settings).model||"model-id").setValue(this.plugin.settings.model).onChange(async i=>{this.plugin.settings.model=i.trim(),this.plugin.saveSettingsDebounced()})),new g.Setting(n).setName(e("settingMaxInputName")).setDesc(e("settingMaxInputDesc")).addText(a=>a.setValue(String(this.plugin.settings.maxDocChars||y.maxDocChars)).onChange(async i=>{let s=parseInt(i,10);!Number.isNaN(s)&&s>=1e3&&(this.plugin.settings.maxDocChars=s,this.plugin.saveSettingsDebounced())})),n.createEl("h3",{text:e("promptHeader")}),new g.Setting(n).setName(e("settingPromptLanguageName")).setDesc(e("settingPromptLanguageDesc")).addDropdown(a=>{for(let[i,s]of Object.entries(K))a.addOption(i,s);return a.setValue(this.plugin.settings.promptLanguage||y.promptLanguage).onChange(async i=>{this.plugin.settings.promptLanguage=i,await this.plugin.saveSettings()})}),new g.Setting(n).setName(e("settingCardRangeName")).setDesc(e("settingCardRangeDesc")).addText(a=>a.setPlaceholder("min").setValue(String(this.plugin.settings.minCards||y.minCards)).onChange(async i=>{let s=parseInt(i,10);!Number.isNaN(s)&&s>0&&(this.plugin.settings.minCards=s,this.plugin.settings.maxCards<s&&(this.plugin.settings.maxCards=s),this.plugin.saveSettingsDebounced())})).addText(a=>a.setPlaceholder("max").setValue(String(this.plugin.settings.maxCards||y.maxCards)).onChange(async i=>{let s=parseInt(i,10);!Number.isNaN(s)&&s>0&&(this.plugin.settings.maxCards=Math.max(s,this.plugin.settings.minCards||y.minCards),this.plugin.saveSettingsDebounced())})),new g.Setting(n).setName(e("settingCustomPromptName")).setDesc(e("settingCustomPromptDesc")).addTextArea(a=>(a.inputEl.rows=8,a.setPlaceholder(e("settingCustomPromptPlaceholder")).setValue(this.plugin.settings.customSystemPrompt||"").onChange(async i=>{this.plugin.settings.customSystemPrompt=i,this.plugin.saveSettingsDebounced()}))),new g.Setting(n).setName(e("settingTestBackendName")).setDesc(e("settingTestBackendDescApi")).addButton(a=>a.setButtonText("Test").onClick(async()=>{try{let i=await Bt(this.plugin.settings);new g.Notice(`\u2713 ${i.slice(0,180)}`,8e3)}catch(i){new g.Notice(e("backendTestFailed",{error:i.message}),1e4)}})),new g.Setting(n).setName(e("settingExportFolderName")).setDesc(e("settingExportFolderDesc")).addText(a=>a.setValue(this.plugin.settings.exportFolder).onChange(async i=>{this.plugin.settings.exportFolder=i.trim()||y.exportFolder,this.plugin.saveSettingsDebounced()})),n.createEl("h3",{text:e("cacheHeader")}),new g.Setting(n).setName(e("settingMaxCacheName")).setDesc(e("settingMaxCacheDesc")).addText(a=>{a.setValue(String(this.plugin.settings.maxCacheEntries||_));let i=async()=>{let s=parseInt(a.getValue(),10);if(Number.isFinite(s)&&s>0){this.plugin.settings.maxCacheEntries=s,await this.plugin.saveSettings();let o=await this.plugin.pruneCacheIfNeeded();o.length>0&&new g.Notice(e("cachePruned",{count:o.length})),this.display()}};return a.inputEl.addEventListener("change",i),a.inputEl.addEventListener("keydown",s=>{s.key==="Enter"&&a.inputEl.blur()}),a});let r=Object.keys(this.plugin.cache).length;new g.Setting(n).setName(e("cachedNotesName",{count:r})).setDesc(e("cachedNotesDesc")).addButton(a=>a.setButtonText(e("clearAllCacheButton")).setWarning().onClick(async()=>{let i=Object.keys(this.plugin.cache).length;await this.plugin.cacheClear(),new g.Notice(e("cacheClearedAll",{count:i})),this.display()}))}};var S=require("obsidian");function N(t,n,e,r){let a=t.createEl("button",{cls:"parallel-reader-icon-button",attr:{type:"button","aria-label":e}});return a.title=e,typeof S.setIcon=="function"?(0,S.setIcon)(a,n):a.textContent=e,a.addEventListener("click",async i=>{i.preventDefault(),i.stopPropagation();try{await r()}catch(s){console.error(s),new S.Notice(`${e} failed: `+(s.message||s))}}),a}function D(t,n,e,r,a){let i=t.createEl("button",{cls:a||"parallel-reader-text-button",attr:{type:"button"}});return n&&typeof S.setIcon=="function"&&(0,S.setIcon)(i,n),i.createSpan({text:e}),i.addEventListener("click",async s=>{s.preventDefault(),s.stopPropagation();try{await r()}catch(o){console.error(o),new S.Notice(`${e} failed: `+(o.message||o))}}),i}async function I(t,n){try{await navigator.clipboard.writeText(t),new S.Notice(n)}catch(e){new S.Notice("Copy failed: "+(e.message||e))}}function _e(t){return String(t||"").split("/").map(n=>n.trim()).filter(n=>!!n&&n!==".."&&n!==".").join("/")}function Ve(t){let n=_e(t);if(!n)return[];let e=n.split("/");return e.map((r,a)=>e.slice(0,a+1).join("/"))}async function at(t,n){for(let e of Ve(n))if(!t.vault.getAbstractFileByPath(e))try{await t.vault.createFolder(e)}catch(r){if(!t.vault.getAbstractFileByPath(e))throw r}}var v=require("obsidian");var it=require("obsidian");var de=class extends it.Modal{constructor(n,e,r,a){super(n),this.plugin=e,this.card=r||{},this.onSave=a}onOpen(){let{contentEl:n}=this;n.empty(),n.createEl("h2",{text:this.plugin.t("editCardTitle")});let e=this.createLabeledInput(n,this.plugin.t("editCardTitleField"),this.card.title||""),r=this.createLabeledTextarea(n,this.plugin.t("editCardGistField"),this.card.gist||"",3),a=this.createLabeledTextarea(n,this.plugin.t("editCardBulletsField"),(this.card.bullets||[]).join(`
`),8),i=n.createDiv({cls:"parallel-reader-modal-actions"});D(i,null,this.plugin.t("editCardCancel"),()=>this.close(),"parallel-reader-text-button"),D(i,null,this.plugin.t("editCardSave"),async()=>{await this.onSave({title:e.value.trim()||this.card.title||"",gist:r.value.trim(),bullets:a.value.split(/\r?\n/).map(s=>s.trim()).filter(Boolean)}),this.close()},"parallel-reader-text-button")}createLabeledInput(n,e,r){let a=n.createDiv({cls:"parallel-reader-modal-field"});a.createEl("label",{text:e});let i=a.createEl("input",{attr:{type:"text"}});return i.value=r,i}createLabeledTextarea(n,e,r,a){let i=n.createDiv({cls:"parallel-reader-modal-field"});i.createEl("label",{text:e});let s=i.createEl("textarea");return s.rows=a,s.value=r,s}};var R="parallel-reader-view",he=class extends v.ItemView{constructor(e,r){super(e);this.stale=!1;this.loadingMessage="";this.errorMessage="";this.plugin=r,this.sections=[],this.sourceFile=null,this.cards=[],this.activeIdx=-1}getViewType(){return R}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",r=>this.handleKeydown(r)),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 r=e.createDiv({cls:"parallel-reader-empty"});r.createEl("h3",{text:this.plugin.t("appTitle")}),r.createEl("p",{text:this.plugin.t("emptyOpenNote")}),r.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)}async loadFor(e,r,a){this.sourceFile=e,this.sections=r,this.stale=!!a,this.loadingMessage="",this.errorMessage="",this.render()}async renderLoading(e,r){this.sourceFile=e,this.sections=[],this.stale=!1,this.loadingMessage=r||this.plugin.t("loadingDefault"),this.errorMessage="",this.render()}renderStreamingPreview(e,r){this.sourceFile?.path!==e.path&&(this.sourceFile=e);let a=this.containerEl.children[1],i=a.querySelector(".parallel-reader-streaming-preview");if(i){let h=i.querySelector("pre");h&&(h.textContent=r.slice(-2e3));let C=i.querySelector(".parallel-reader-stream-counter");C&&(C.textContent=`${r.length} chars`);return}a.empty();let o=a.createDiv({cls:"parallel-reader-header"}).createDiv({cls:"parallel-reader-header-row"});o.createEl("div",{text:e.basename,cls:"parallel-reader-title"});let l=o.createDiv({cls:"parallel-reader-actions"});N(l,"square",this.plugin.t("actionCancel"),()=>{this.plugin.cancelGenerationForFile(e)});let p=a.createDiv({cls:"parallel-reader-state parallel-reader-loading parallel-reader-streaming-preview"});p.createDiv({cls:"parallel-reader-spinner"});let c=p.createEl("div",{cls:"parallel-reader-state-title"});c.createSpan({text:this.plugin.t("loadingGenerating")+" "}),c.createSpan({cls:"parallel-reader-stream-counter",text:`${r.length} chars`});let u=p.createEl("pre",{cls:"parallel-reader-stream-text"});u.textContent=r.slice(-2e3)}async renderError(e,r){this.sourceFile=e,this.sections=[],this.stale=!1,this.loadingMessage="",this.errorMessage=r||this.plugin.t("errorTitle"),this.render()}renderEmptyWithHint(e){this.sourceFile=e,this.sections=[],this.stale=!1,this.loadingMessage="",this.errorMessage="";let r=this.containerEl.children[1];r.empty();let a=r.createDiv({cls:"parallel-reader-empty"});a.createEl("h3",{text:e.basename}),a.createEl("p",{text:this.plugin.t("emptyNoCache")}),a.createEl("code",{text:this.plugin.t("commandGenerate")})}render(){let e=this.containerEl.children[1];e.empty();let a=e.createDiv({cls:"parallel-reader-header"}).createDiv({cls:"parallel-reader-header-row"});a.createEl("div",{text:this.sourceFile?.basename||"",cls:"parallel-reader-title"});let i=a.createDiv({cls:"parallel-reader-actions"});if(this.sourceFile&&(this.plugin.isGeneratingFile(this.sourceFile)?N(i,"square",this.plugin.t("actionCancel"),()=>{this.plugin.cancelGenerationForFile(this.sourceFile)}):N(i,"refresh-cw",this.plugin.t("actionRegenerate"),()=>this.plugin.runForFile(this.sourceFile,!0)),N(i,"copy",this.plugin.t("actionCopyAll"),()=>this.plugin.copyCurrentViewMarkdown()),N(i,"download",this.plugin.t("actionExport"),()=>this.exportToVault())),this.stale){let l=e.createDiv({cls:"parallel-reader-stale-banner"});l.createSpan({text:this.plugin.t("staleBanner")}),D(l,"refresh-cw",this.plugin.t("actionRegenerate"),()=>this.plugin.runForFile(this.sourceFile,!0),"parallel-reader-stale-button")}if(this.loadingMessage){let l=e.createDiv({cls:"parallel-reader-state parallel-reader-loading"});l.createDiv({cls:"parallel-reader-spinner"}),l.createEl("div",{text:this.loadingMessage,cls:"parallel-reader-state-title"}),l.createEl("div",{text:this.plugin.t("loadingSubtitle"),cls:"parallel-reader-state-subtitle"});return}if(this.errorMessage){let l=e.createDiv({cls:"parallel-reader-state parallel-reader-error"});l.createEl("div",{text:this.plugin.t("errorTitle"),cls:"parallel-reader-state-title"}),l.createEl("div",{text:this.errorMessage,cls:"parallel-reader-state-subtitle"}),D(l,"refresh-cw",this.plugin.t("actionRegenerate"),()=>this.plugin.runForFile(this.sourceFile,!0),"parallel-reader-text-button");return}let s=e.createDiv({cls:"parallel-reader-cards"});this.cards=[];let o=this.sourceFile?.path||"";this.sections.forEach((l,p)=>{let c=s.createDiv({cls:"parallel-reader-card"});c.dataset.idx=String(p),l.startLine<0&&c.addClass("parallel-reader-card-unanchored");let u=c.createEl("div",{cls:"parallel-reader-card-title"});if(u.createSpan({text:l.title}),l.startLine<0&&u.createEl("span",{text:" \u26A0",cls:"parallel-reader-warn",title:this.plugin.t("anchorMismatch")}),l.gist){let C=c.createEl("div",{cls:"parallel-reader-gist"});v.MarkdownRenderer.render(this.app,l.gist,C,o,this).catch(()=>{C.setText(l.gist)})}let h=l.bullets||[];if(h.length>0){let C=c.createEl("div",{cls:"parallel-reader-bullets-md"}),m=h.map(f=>`- ${f}`).join(`
`);v.MarkdownRenderer.render(this.app,m,C,o,this).catch(()=>{C.setText(m)})}else l.gist||c.createEl("div",{cls:"parallel-reader-empty-li",text:this.plugin.t("emptyCard")});c.addEventListener("click",C=>{let m=window.getSelection();if(m&&m.toString().length>0)return;let f=C.target;f&&f.tagName==="A"||l.startLine>=0&&this.plugin.scrollEditorToLine(l.startLine,this.sourceFile)}),c.addEventListener("contextmenu",C=>{C.preventDefault();let m=new v.Menu;m.addItem(f=>f.setTitle(this.plugin.t("menuCopyMarkdown")).setIcon("copy").onClick(()=>I(we(l),this.plugin.t("copiedMarkdown")))),m.addItem(f=>f.setTitle(this.plugin.t("menuCopyPlain")).setIcon("clipboard-copy").onClick(()=>I(qe(l),this.plugin.t("copiedPlain")))),l.anchor&&m.addItem(f=>f.setTitle(this.plugin.t("menuCopyAnchor")).setIcon("quote-glyph").onClick(()=>I(l.anchor,this.plugin.t("copiedAnchor")))),m.addSeparator(),l.startLine>=0&&m.addItem(f=>f.setTitle(this.plugin.t("menuJumpSource")).setIcon("arrow-right").onClick(()=>this.plugin.scrollEditorToLine(l.startLine,this.sourceFile))),m.addSeparator(),m.addItem(f=>f.setTitle(this.plugin.t("menuEditCard")).setIcon("pencil").onClick(()=>this.openEditCardModal(p))),m.addItem(f=>f.setTitle(this.plugin.t("menuDeleteCard")).setIcon("trash").onClick(()=>this.deleteCard(p))),m.showAtMouseEvent(C)}),this.cards.push(c)}),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 r=ne(this.activeIdx,this.sections.length,e);return this.setActiveSection(r),this.focusSummaryPane(),r}jumpToActiveSection(){let e=ae(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 r=Z(this.sections,e);if(r.length===this.sections.length)return!1;let a=this.sections.length;return this.sections=r,this.activeIdx=Q(e,a,this.activeIdx),await this.plugin.cacheReplaceCards(this.sourceFile.path,r),this.render(),new v.Notice(this.plugin.t("cardDeleted")),!0}openEditCardModal(e){return!this.sourceFile||!this.sections[e]?!1:(new de(this.app,this.plugin,this.sections[e],async r=>{await this.updateCard(e,r)}).open(),!0)}async updateCard(e,r){if(!this.sourceFile)return!1;let a=ee(this.sections,e,r);return a.length!==this.sections.length?!1:(this.sections=a,await this.plugin.cacheReplaceCards(this.sourceFile.path,a),this.render(),new v.Notice(this.plugin.t("cardSaved")),!0)}async exportToVault(){if(!this.sourceFile)return;let e=_e(this.plugin.settings.exportFolder),r=`${this.sourceFile.basename} - ${this.plugin.t("displayName")}.md`,a=`${e}/${r}`,i=["---",`source: [[${this.sourceFile.basename}]]`,`generated: ${new Date().toISOString().slice(0,10)}`,"tool: parallel-reader","---","",H(`${this.sourceFile.basename} \xB7 ${this.plugin.t("displayName")}`,this.sections),""].join(`
`),s=this.plugin.app;await at(s,e);let o=s.vault.getAbstractFileByPath(a);o instanceof v.TFile?await s.vault.modify(o,i):await s.vault.create(a,i),new v.Notice(this.plugin.t("exported",{path:a}))}};async function Ut(t,n,e,r){let{system:a,user:i}=ke(t,n),s,o=Ie(n),l=o?new AbortController:null;l&&e.onCancel(()=>l.abort()),o?s=await rt(a,i,n,r,l.signal):s=await ue(d.requestUrl,a,i,n);let p=s.map(c=>({title:c.title,level:2,anchor:c.anchor,gist:c.gist,startLine:X(t,c.anchor),bullets:c.bullets}));return p.sort((c,u)=>c.startLine<0&&u.startLine<0?0:c.startLine<0?1:u.startLine<0?-1:c.startLine-u.startLine),p}function st(t,n){return n?.phase==="generating"&&t&&Se(t.backend)?"cancelRequestedApiInFlight":"cancelRequested"}var Be=class extends d.Plugin{constructor(){super(...arguments);this._scrollDispose=null;this._settingsSaveTimer=null;this._cacheSaveTimer=null;this._cacheDirty=!1}t(e,r){return b(this.settings||y,e,r)}async onload(){await this.loadSettings(),this.jobs=new U,this._cacheSaveTimer=null,this._cacheDirty=!1,this.addRibbonIcon("book-open",this.t("ribbonOpen"),async()=>{let e=this.getActiveView();await this.ensureView(),e?.file&&await this.syncViewToFile(e.file)}),this.registerView(R,e=>new he(e,this)),this.addCommand({id:"parallel-reader-run",name:this.t("cmdRun"),callback:()=>this.runForActiveFile(!1)}),this.addCommand({id:"parallel-reader-regen",name:this.t("cmdRegen"),callback:()=>this.runForActiveFile(!0)}),this.addCommand({id:"parallel-reader-open-view",name:this.t("cmdOpenView"),callback:async()=>{let e=this.getActiveView();await this.ensureView(),e?.file&&this.syncViewToFile(e.file)}}),this.addCommand({id:"parallel-reader-export-current",name:this.t("cmdExport"),callback:()=>this.exportCurrentView()}),this.addCommand({id:"parallel-reader-copy-current-markdown",name:this.t("cmdCopyMarkdown"),callback:()=>this.copyCurrentViewMarkdown()}),this.addCommand({id:"parallel-reader-cancel-current",name:this.t("cmdCancel"),callback:()=>this.cancelActiveGeneration()}),this.addCommand({id:"parallel-reader-clear-current",name:this.t("cmdClearCurrent"),callback:async()=>{let e=this.getActiveView();if(!e?.file)return new d.Notice(this.t("noCurrentNote"));await this.cacheDelete(e.file.path),new d.Notice(this.t("cacheClearedFile",{name:e.file.basename}))}}),this.addCommand({id:"parallel-reader-clear-all",name:this.t("cmdClearAll"),callback:async()=>{let e=Object.keys(this.cache).length;await this.cacheClear(),new d.Notice(this.t("cacheClearedAll",{count:e}))}}),this.addCommand({id:"parallel-reader-card-prev",name:this.t("cmdCardPrev"),hotkeys:[{modifiers:["Alt"],key:"ArrowUp"}],callback:()=>this.moveActiveCard(-1)}),this.addCommand({id:"parallel-reader-card-next",name:this.t("cmdCardNext"),hotkeys:[{modifiers:["Alt"],key:"ArrowDown"}],callback:()=>this.moveActiveCard(1)}),this.addCommand({id:"parallel-reader-card-jump",name:this.t("cmdCardJump"),callback:()=>this.jumpActiveCard()}),this.addSettingTab(new pe(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,r)=>this.addFileMenuItems(e,r))),this.registerEvent(this.app.vault.on("rename",(e,r)=>this.handleFileRename(e,r))),this.registerEvent(this.app.vault.on("delete",e=>this.handleFileDelete(e))),this.bindScrollSync()}async onunload(){await this.flushSettingsSave(),await this.flushCacheSave(),this.app.workspace.detachLeavesOfType(R)}async loadSettings(){let r=(await this.loadData()||{}).settings||{};this.settings=Ee(Object.assign({},y,r)),await this.loadCache()}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(r=>console.error("[parallel-reader] failed to save settings",r))},e)}async flushSettingsSave(){this._settingsSaveTimer&&(clearTimeout(this._settingsSaveTimer),this._settingsSaveTimer=null,await this.saveSettings())}async saveCache(){this._cacheSaveTimer&&(clearTimeout(this._cacheSaveTimer),this._cacheSaveTimer=null),this.pruneCache(),await this.writeCacheFile(),this._cacheDirty=!1}scheduleCacheSave(e=5e3){this._cacheDirty=!0,!this._cacheSaveTimer&&(this._cacheSaveTimer=setTimeout(()=>{this._cacheSaveTimer=null,this._cacheDirty&&this.saveCache().catch(r=>console.error("[parallel-reader] failed to save cache",r))},e))}async flushCacheSave(){this._cacheSaveTimer&&(clearTimeout(this._cacheSaveTimer),this._cacheSaveTimer=null),this._cacheDirty&&await this.saveCache()}cacheFilePath(){let e=this.app.vault.configDir||".obsidian",r=this.manifest?.id||"parallel-reader";return`${e}/plugins/${r}/cache.json`}async ensurePluginDataDir(){let e=this.app.vault.adapter,r=this.app.vault.configDir||".obsidian",a=this.manifest?.id||"parallel-reader",i=`${r}/plugins/${a}`;try{if(typeof e.exists=="function"&&await e.exists(i))return;await e.mkdir(i)}catch{}}async readCacheFile(){let e=this.app.vault.adapter;try{let r=await e.read(this.cacheFilePath()),a=JSON.parse(r);if(a&&typeof a=="object"&&a.entries&&typeof a.entries=="object")return a.entries}catch(r){let a=String(r?.message||r||"");/not found|does not exist|ENOENT/i.test(a)||console.warn("[parallel-reader] failed to read cache.json",r)}return{}}async writeCacheFile(){await this.ensurePluginDataDir(),await this.app.vault.adapter.write(this.cacheFilePath(),ge(this.cache))}async loadCache(){this.cache=await this.readCacheFile(),this.pruneCache().length>0&&await this.writeCacheFile()}pruneCache(){return Fe(this.cache,this.settings?.maxCacheEntries||_)}async pruneCacheIfNeeded(){let e=this.pruneCache();return e.length>0&&await this.saveCache(),e}cacheGet(e){return this.cache[e]||null}async cacheTouch(e){let r=me(this.cache[e]||null);return r?(this.scheduleCacheSave(),r):null}async cachePut(e,r,a,i){let s=new Date().toISOString();this.cache[e]={schemaVersion:J,contentHash:O(r),settingsHash:ie(i||this.settings),cards:a,generatedAt:s,lastAccessedAt:s},await this.saveCache()}async cacheReplaceCards(e,r){let a=this.cache[e];if(!a)return!1;let i=new Date().toISOString();return a.cards=(r||[]).map(s=>({title:s.title,anchor:s.anchor,gist:s.gist,bullets:s.bullets||[]})),a.updatedAt=i,a.lastAccessedAt=i,await this.saveCache(),!0}async cacheDelete(e){this.cache[e]&&(delete this.cache[e],await this.saveCache())}async cacheClear(){this.cache={},await this.saveCache()}async ensureView(){let{workspace:e}=this.app,r=e.getLeavesOfType(R)[0];return r||(r=e.getRightLeaf(!1),await r.setViewState({type:R,active:!0})),e.revealLeaf(r),r.view}getActiveView(){return this.app.workspace.getActiveViewOfType(d.MarkdownView)}getParallelView(){return this.app.workspace.getLeavesOfType(R)[0]?.view}moveActiveCard(e){let r=this.getParallelView();return r?.sections.length?r.moveActiveSection(e):(new d.Notice(this.t("noActiveCard")),-1)}jumpActiveCard(){let e=this.getParallelView();return!e||e.jumpToActiveSection()<0?(new d.Notice(this.t("noActiveCard")),!1):!0}isGeneratingFile(e){return!!e&&!!e.path&&this.jobs.isRunning(e.path)}cancelGenerationForFile(e){if(!e?.path)return new d.Notice(this.t("noCancelableJob")),!1;let r=this.jobs.get(e.path),a=st(this.settings,r),i=this.jobs.cancel(e.path);return new d.Notice(i?this.t(a):this.t("noCancelableJob")),i}viewIsShowingFile(e,r){return!!e&&!!r&&e.sourceFile?.path===r.path}activeFileStillMatches(e){let r=this.getActiveView();return!r?.file||r.file.path===e.path}cancelActiveGeneration(){let e=this.getActiveView();if(e?.file&&this.cancelGenerationForFile(e.file))return;let r=this.getParallelView();r?.sourceFile?this.cancelGenerationForFile(r.sourceFile):new d.Notice(this.t("noCancelableJob"))}confirmRegenerateEditedCards(){let e=this.t("confirmRegenerateEditedCards");return typeof window<"u"&&typeof window.confirm=="function"?window.confirm(e):!0}addFileMenuItems(e,r){!(r instanceof d.TFile)||!r.path.endsWith(".md")||(e.addSeparator(),e.addItem(a=>a.setTitle(this.t("fileMenuGenerate")).setIcon("book-open").onClick(()=>this.runForFile(r,!1))),e.addItem(a=>a.setTitle(this.t("fileMenuRegen")).setIcon("refresh-cw").onClick(()=>this.runForFile(r,!0))),this.cacheGet(r.path)&&e.addItem(a=>a.setTitle(this.t("fileMenuClear")).setIcon("trash").onClick(async()=>{await this.cacheDelete(r.path),new d.Notice(this.t("cacheClearedFile",{name:r.basename}))})))}async handleFileRename(e,r){if(!(e instanceof d.TFile)||!r)return;let a=r.endsWith(".md"),i=e.path.endsWith(".md");if(!a&&!i)return;if(a&&!i){this.cache[r]&&(delete this.cache[r],await this.saveCache());let o=this.getParallelView();o&&o.sourceFile?.path===r&&o.renderEmpty();return}if(!a)return;this.cache[r]&&(this.cache[e.path]=this.cache[r],delete this.cache[r],await this.saveCache());let s=this.getParallelView();s?.sourceFile&&(s.sourceFile.path===r||s.sourceFile.path===e.path)&&(s.sourceFile=e,await this.syncViewToFile(e))}async handleFileDelete(e){if(!(e instanceof d.TFile))return;this.cache[e.path]&&(delete this.cache[e.path],await this.saveCache());let r=this.getParallelView();r?.sourceFile?.path===e.path&&r.renderEmpty()}async exportCurrentView(){let e=this.getActiveView(),r=await this.ensureView();if((!r.sourceFile||!r.sections.length)&&e?.file&&await this.syncViewToFile(e.file),!r.sourceFile||!r.sections.length){new d.Notice(this.t("noExportContent"));return}await r.exportToVault()}async copyCurrentViewMarkdown(){let e=this.getActiveView(),r=await this.ensureView();if((!r.sourceFile||!r.sections.length)&&e?.file&&await this.syncViewToFile(e.file),!r.sourceFile||!r.sections.length){new d.Notice(this.t("noCopyContent"));return}await I(H(`${r.sourceFile.basename} \xB7 ${this.t("displayName")}`,r.sections),this.t("copiedAllMarkdown"))}async runForActiveFile(e){let r=this.getActiveView();if(!r?.file){new d.Notice(this.t("openNoteFirst"));return}return this.runForFile(r.file,e)}async runForFile(e,r){if(!e){new d.Notice(this.t("openNoteFirst"));return}if(this.jobs.isRunning(e.path)){new d.Notice(this.t("alreadyGenerating"));return}if(fe(this.cacheGet(e.path),r)&&!this.confirmRegenerateEditedCards()){new d.Notice(this.t("regenerateCancelled"));return}let a=null;return this.jobs.start(e.path,async i=>{i.setPhase("reading");let s=await this.app.vault.read(e);if(i.throwIfCancelled(),!s.trim()){new d.Notice(this.t("emptyNote"));return}if(a=await this.ensureView(),i.throwIfCancelled(),i.setPhase("cache-check"),!r){let h=this.cacheGet(e.path);if(se(h,s,this.settings)){await this.cacheTouch(e.path),this.activeFileStillMatches(e)&&await a.loadFor(e,this.resolveCardAnchors(s,h.cards),!1);return}}await a.renderLoading(e,this.t("loadingGenerating"));let o=Number(this.settings.maxDocChars)||y.maxDocChars;s.length>o&&new d.Notice(this.t("longNoteTruncated",{count:o})),new d.Notice(this.t("generatingNotice")),i.setPhase("generating");let l=a?h=>{!h.done&&this.viewIsShowingFile(a,e)&&a.renderStreamingPreview(e,h.accumulated)}:void 0,p=await Ut(s,this.settings,i,l);if(i.throwIfCancelled(),p.length===0){new d.Notice(this.t("noCardsReturned"));return}let c=p.map(h=>({title:h.title,anchor:h.anchor,gist:h.gist,bullets:h.bullets}));i.setPhase("saving"),await this.cachePut(e.path,s,c,this.settings),i.throwIfCancelled(),this.viewIsShowingFile(a,e)&&await a.loadFor(e,p,!1);let u=p.filter(h=>h.startLine<0).length;new d.Notice(this.t("generationDone",{count:p.length,suffix:u?this.t("unanchoredSuffix",{count:u}):""}))}).catch(async i=>{if(i instanceof L){new d.Notice(i.message);return}if(i instanceof P){a&&this.viewIsShowingFile(a,e)&&await a.renderError(e,this.t("cancelledError")),new d.Notice(this.t("cancelled"));return}let s=Ce(i);console.error(i),a&&this.viewIsShowingFile(a,e)&&await a.renderError(e,i.message||String(i)),new d.Notice(this.t("generationFailed",{kind:s==="unknown"?"":` (${s})`,error:i.message||i}))})}resolveCardAnchors(e,r){let a=(r||[]).map(i=>({title:i.title,level:2,anchor:i.anchor,gist:i.gist,startLine:X(e,i.anchor),bullets:i.bullets||[]}));return a.sort((i,s)=>i.startLine<0&&s.startLine<0?0:i.startLine<0?1:s.startLine<0?-1:i.startLine-s.startLine),a}async syncViewToFile(e){if(!e?.path?.endsWith(".md"))return;let r=this.app.workspace.getLeavesOfType(R);if(r.length===0)return;let a=r[0].view;if(!a||!this.activeFileStillMatches(e))return;let i=this.cacheGet(e.path);if(!i){await a.loadFor(e,[],!1),a.renderEmptyWithHint(e);return}let s=await this.app.vault.read(e);if(!this.activeFileStillMatches(e))return;let o=!se(i,s,this.settings);await this.cacheTouch(e.path),await a.loadFor(e,this.resolveCardAnchors(s,i.cards),o)}bindScrollSync(){this._scrollDispose&&(this._scrollDispose(),this._scrollDispose=null);let e=this.getActiveView();if(!e)return;let r=e.editor,a=r&&r.cm,i=a?.scrollDOM?a.scrollDOM:e.contentEl.querySelector(".cm-scroller");if(!i)return;let s=Oe(()=>this.handleEditorScroll(e));i.addEventListener("scroll",s,{passive:!0}),this._scrollDispose=()=>{s.cancel(),i.removeEventListener("scroll",s)}}handleEditorScroll(e){let r=this.getParallelView();if(!r||!e.file||r.sourceFile?.path!==e.file.path)return;let a=e.editor,i=a&&a.cm;if(!i?.scrollDOM)return;let s=i.scrollDOM.getBoundingClientRect(),o=Le(s),l=0;try{let c=i.posAtCoords({x:s.left+20,y:o});c!=null&&(l=i.state.doc.lineAt(c).number-1)}catch{return}let p=-1;for(let c=0;c<r.sections.length;c++){let u=r.sections[c];if(!(u.startLine<0))if(u.startLine<=l)p=c;else break}r.setActiveSection(p)}findLeafForFile(e){if(!e)return null;for(let r of this.app.workspace.getLeavesOfType("markdown")){let a=r.view;if(a?.file&&a.file.path===e.path)return r}return null}async scrollEditorToLine(e,r){let a=r?this.findLeafForFile(r):null;if(!a&&r&&(a=this.app.workspace.getLeaf("tab"),await a.openFile(r,{active:!1})),!a){let s=this.getActiveView();s&&(a=s.leaf)}if(!a){new d.Notice(this.t("noEditor"));return}this.app.workspace.setActiveLeaf(a,{focus:!0});let i=a.view;if(i instanceof d.MarkdownView&&(i.setEphemeralState({line:e}),i.editor))try{i.editor.setCursor({line:e,ch:0}),i.editor.scrollIntoView({from:{line:e,ch:0},to:{line:e,ch:0}},!0)}catch{}}},jt=Be,Gt={CACHE_SCHEMA_VERSION:J,GenerationJobAlreadyRunningError:L,GenerationJobCancelledError:P,GenerationJobManager:U,addIconButton:N,addTextButton:D,activeIndexAfterCardDelete:Q,activeSectionLine:ae,buildAnthropicMessagesBody:$,buildGeminiBody:le,buildOpenAiChatBody:z,buildOpenAiResponsesBody:oe,buildPrompts:ke,cardsToMarkdown:H,cacheEntryMatches:se,cancellationNoticeKey:st,classifyGenerationError:Ce,copyToClipboard:I,createRafThrottledHandler:Oe,extractJson:be,findLineForAnchor:X,folderPathsForTarget:Ve,generationFingerprint:ie,getApiBaseUrl:E,modelForApi:M,normalizeCardsPayload:j,nextCardIndex:ne,pruneCacheEntries:Fe,removeCardAt:Z,resolveCliPath:ze,serializeCacheFile:ge,shouldConfirmRegenerate:fe,summarizeViaApi:ue,touchCacheEntry:me,translate:b,tokenLimitFieldForOpenAiChat:Me,updateCardAt:ee,visibleTopProbeY:Le,supportsStreaming:Ie,deltaExtractorForFormat:V,parseSseBuffer:Ne};0&&(module.exports={__test});