Findings from the original review (P2):
- streaming: flush unterminated final SSE event at EOF (some providers
close the stream without a trailing blank line, dropping the last delta)
- cache-manager: validate entry shape on load — drop entries where
cards is not an array, anchor is not a string, or bullets is not an
array. Tolerates missing optional fields (treated as cache miss).
- view: card edit/delete now check cacheReplaceCards return and surface
failures via a localized Notice instead of pretending success
- main: clear-current / clear-all / file-menu-clear refresh open view
via renderEmpty so stale UI does not display deleted data
- prompt + settings-tab: card count is normalized via a single helper
used by buildPrompts and onChange. Prompt and fingerprint stay in sync.
UI value is written back to the textbox after clamping.
- generation-job-manager: global concurrency limit (default 3) with a
cancellable wait queue. Race-safe slot accounting via a reserved
counter so resolved-but-not-yet-set waiters are visible to fast-path
start() callers.
- runForFile: now returns RunForFileResult; accepts preloadedContent +
silentView + skipEditConfirm options used by batch (and reflected on
the PluginHost interface).
- batch: avoid double file read, do not steal UI focus, classify
results correctly (generated / cached / already-running / empty / ...)
Follow-up from the 1.0.11 review:
- generationFingerprint: codex backend excludes settings.model from the
hash. Codex ignores --model; previously editing model spuriously
invalidated all codex cache.
Codex review pass:
- generation-job-manager: race fix — releaseSlot's resolve microtask
and a synchronous start() fast-path could briefly overshoot
maxConcurrent. Reserve the slot synchronously inside the wrapped
resolve to close the window.
- cache-manager: anchor type validation in addition to bullets.
NOTE: Codex backend users will see a one-time "stale cache" banner on
existing notes due to the fingerprint change; regenerate to refresh.
Change-Id: I7721c7dfe51dea3f51b0215764f721523c2f6806
P1:
- cli: pin codex --sandbox read-only (defeat prompt injection)
- settings: clear apiKey/apiHeaders on provider preset switch
- main/view: render error state when LLM returns empty cards
- schema/cli: do not log raw model output; UI errors expose length only
P2:
- cli: pass --model to Claude Code when settings.model set
- settings-tab: add CLI timeout input + normalizeCliTimeoutMs (min 1s)
- view: export source link uses [[path|basename]]
- view: export failures surface a localized Notice
P3:
- schema: cardUntitled fallback now respects uiLanguage
- generation-job-manager: error codes localized via main.ts
- batch: settled guard on promptForBatchFolder modal
- README: drop stale e2e validator install note
Codex review pass:
- provider-parsers: forward settings to normalizeCardsPayload
- generation-job-manager: classifyGenerationError regex covers new EN/zh
schema-error messages
- cli: do NOT pass --model to codex (DEFAULT_SETTINGS.model is a Claude
name and would break codex; codex relies on its own config)
Tests: cli (codex sandbox + claude --model + classify zh/en), settings
(applyApiProviderPreset isolation + normalizeCliTimeoutMs), schema
(language-aware fallback title), test-exports (new symbols).
Change-Id: I9f4c21f9299e1a9bf166f69f712859854482fe92
The Claude Code CLI doesn't support --max-tokens. This caused the CLI
backend to always fail with exit code 1. Also adds args validation tests
for both claude and codex CLI backends.
Change-Id: I57c5cc672ed08de291e3941511ce68ba56e5b4ff
- Create scripts/run-tests.mjs to auto-discover test files, replacing
the 900-char inline test command in package.json (P3-1)
- Add test:only script for CI to avoid duplicate build+typecheck (P2-1)
- Preserve original SyntaxError as cause in responseJson (P2-3)
Change-Id: I51d0c8c51d3b0b648ed5ff4ea282bda070b0d457
Extracts renderCliBackendSettings() and renderApiBackendSettings() from
the 144-line renderBackendSection(). The parent method is now a 5-line
dispatcher. CLI settings (14 lines) and API settings (128 lines) are
cleanly separated.
Change-Id: Ic866ba78d3b572f5f564760b248460584b0819c5
Replaces the 64-line __test manual export block in main.ts with a
single import from src/test-exports.ts. Also removes 30+ imports that
were only needed for __test re-export. main.ts reduced from 788 to
693 lines.
Change-Id: I029f127faf053135d04dba17b8c39c8c39ca8540
Moves RequestUrlFunction type, endpointUrl, responseJson, requestJsonBody,
shouldRetryWithoutStructuredOutput, and requestJsonBodyWithStructuredFallback
to a dedicated provider-request.ts module (103 lines). providers.ts reduced
from 377 to 277 lines.
Change-Id: I013d6a0b9565770c00e48eb416541fcf08d1c5e8
Decomposes the 76-line render() method into renderHeader(),
renderStaleBanner(), renderLoadingState(), renderErrorState(), and
renderCardList(). Each helper is under 22 lines. render() is now a
15-line orchestrator that delegates to the appropriate helper.
Change-Id: Iffcf31131fcf0bce882c1e9ee35aaf58d002b5fa
Moves 18 provider preset definitions (148 lines) from settings.ts into
a dedicated provider-presets.ts file. settings.ts reduced from 443 to
297 lines, now contains only utility functions and non-preset constants.
Change-Id: Ia9a1ef48854ab79cb405df9cd1f88d19826317d6
Moves the STRINGS object (330 lines of zh/en translations) from i18n.ts
into a separate i18n-strings.ts file. i18n.ts now contains only the
resolveUiLanguage and translate logic (28 lines).
Change-Id: I9ddea79bddb4e8313dc16aae2a7c8d4eeff96fe1
Add DEFAULT_MAX_OFFSET_PX (80), DEFAULT_PROBE_RATIO (0.1), and
FALLBACK_FRAME_MS (16) to document the purpose of each value.
Change-Id: Ie34d61c290384de81ae001f292e89f17b410e701
Fix 4 locations in providers.ts, cli.ts, and settings-tab.ts where error
objects were cast to Error without checking. Now uses proper instanceof
narrowing with String fallback for non-Error throwables.
Change-Id: Ib324380f5d56945672e32b9d3621855f6179186a
Move buildAnthropicMessagesBody, buildOpenAiChatBody, buildOpenAiResponsesBody,
buildGeminiBody, tokenLimitFieldForOpenAiChat and their type interfaces to a
new module. Reduces providers.ts from 494 to 367 lines (under 400 target).
Change-Id: Ib124d5cf5f2f66bac03acbf83e1a224cb6325d12
Replace fragile double-casts with a branded ScheduleId wrapper that
unifies RAF (returns number) and setTimeout (returns Timeout) IDs
without losing type safety. The wrapper is opaque to callers.
Change-Id: I304d68b562ff803d0b20ebcbfb71a3c3d9e1d881
Set noImplicitAnyLet to error in biome.json. Fix the violation in
parseCardsJson by typing the parsed variable as unknown. Widen
normalizeCardsPayload to accept unknown (it already handles non-object
input defensively). Remove now-unnecessary cast in provider-parsers.ts.
Change-Id: I57ee46d3179775d5d7c34f35803a44c45061b0ec
Split the 160-line render() method into three focused methods:
- render(): orchestrates header, state, and card list (now ~60 lines)
- renderCard(): handles single card DOM creation with content and events
- showCardContextMenu(): builds the right-click context menu
Change-Id: I46f94e75d6aef1043ac905f1dc33c13cf4ae8447
Move the inline Modal dialog for batch folder selection into a reusable
promptForBatchFolder function. Removes Modal import from main.ts.
main.ts now 775 lines.
Change-Id: I7a5c62b7df95635dcbe0ac814007838ff83eded4
Move resolveCardAnchors to src/cards.ts and confirmRegenerateEditedCards
to src/modal.ts to reduce main.ts from 835 to 796 lines (under 800 target).
Change-Id: If38ed4e45c61658b7cc52a6283f8e0e24458761e
The constructor always receives a validated ResolvedCard from the call
site (which guards with !this.sections[index]). The fallback to an
empty object cast as ResolvedCard was dead code that hid type safety.
Change-Id: I35c9731d9079b9aeea5eb0fda7eda46a740bc964
The previous code checked signal.aborted before adding the listener,
creating a timing window where the signal could abort between the check
and addEventListener. Now the listener is always registered first, then
signal.aborted is checked after, ensuring no abort event is missed.
Change-Id: I1abc3ad21e5bb93559d66922edf7c325a977bc65
normalizeSettings previously modified its input parameter in-place.
While callers already created copies before calling it, the function
signature was misleading. Now it creates a shallow copy internally and
operates on that, with a Readonly<PluginSettings> parameter type to
signal intent. Added a test verifying the original object is unchanged.
Change-Id: I7600ac37930bbcebb02aa7c84d8988cb7aa71196
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
- Add repairTruncatedCardsJson to recover complete cards when output
is cut off mid-card (e.g. token limit reached)
- Log raw LLM response to console on parse failure for debugging
- Make error panel text selectable and add "copy error" button
Change-Id: I4e76121138888234d42f84f3695cbbfd6beba886
- Fix CI to run all 4 test files (was missing direct-modules.test.js)
- Remove unused ESLint dependencies (eslint, @typescript-eslint/*, eslint-plugin-obsidianmd)
- Enable noImplicitReturns in tsconfig.json for stricter type safety
- Make applyApiProviderPreset return new object instead of mutating input
- Add per-file error handling in batch processing loop with error count in summary
- Narrow all catch clause types to unknown with proper instanceof narrowing
Change-Id: I76975dbd5ebdb5645d18c5858c8a52fd6da3405e
When a note has no cached parallel notes, the empty state now shows a
clickable "Generate" button so users can trigger generation directly
without going through the command palette. Closes#2.
Change-Id: I879897168ef77c44e0ab570e9c094fa9af9f66d4
- Remove unnecessary TFile cast (instanceof already narrows)
- Remove await on non-Promise view methods (loadFor, renderLoading, renderError)
- Remove async from CacheManager.touch() (no await expression)
- Replace this-aliasing with captured locals in batch modal
- Use CSS class instead of inline style for modal input width
- Fix sentence case in settings UI text
Change-Id: I2a222c6429eb7e4d69761cca8369956fef510054
- Remove `parallel-reader-` prefix from command IDs (Obsidian auto-namespaces)
- Remove default hotkeys to avoid conflicts with user keybindings
- Replace `as TFile` casts with `instanceof TFile` checks
- Make onunload sync, remove detachLeavesOfType (preserves leaf positions)
- Use `vault.configDir` instead of hardcoded `.obsidian`
- Replace `window.confirm` with Obsidian Modal dialog
- Fix unhandled promises with `void` or `await`
- Remove unnecessary `async` from methods without `await`
- Use `new Setting().setHeading()` instead of raw HTML headings
- Fix promise-returning callbacks in event listeners
- Fix error type narrowing with `instanceof Error`
- Apply sentence case to UI text labels
Change-Id: I6e850d8a13b458d5cf1ad91227bf1772636b56b9
Register parallel-reader-batch-generate command. It prompts the user for a
folder path via a Modal, finds all .md files in that folder (non-recursive),
skips files whose cache is still valid, and runs runForFile() sequentially
on the rest, showing per-file progress notices. Add i18n keys for the new
UI strings in both zh and en.
https://claude.ai/code/session_016QvEfqw6YZ3RjwBHrJ4w8S
Promote noExplicitAny from warn to error and enable noNonNullAssertion
at warn level. Fix the two resulting errors in src/schema.ts by introducing
a JsonSchema interface to replace the any-typed local variables.
https://claude.ai/code/session_016QvEfqw6YZ3RjwBHrJ4w8S