Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Search Plugin (@lapis-notes/search)

Source: packages/plugins/plugin-search/src/

Manifest: id search, version 0.0.1, min app version 1.7.7.

The search package owns the search sidebar, indexing controls, result rendering, semantic-search status affordance, and the plugin-level settings that shape lexical and vector retrieval. Heavy indexing and query execution are routed through AppDatabase instead of running SQLite or embedding work directly in the renderer.

View, Commands, And Settings

  • View type: SearchViewType in the left sidebar.
  • Commands: search-all-files, search-selected-text, open-search-left-sidebar, rebuild-search-index, refresh-semantic-search.
  • open-search-left-sidebar accepts an optional query argument and seeds the Search view when called by other plugins.
  • Settings: semantic provider, embedding model id, remote/local model policy, explicit embedding rebuild, chunk target size, breakpoint search window, breakpoint decay, result limit, snippet length, match-case mode, recent searches, sidebar presentation options, plus a disabled-by-default Electron-only query-enhancement contract that is persisted for future local expansion/reranking but is not yet exposed in the UI.

Search State

File-level records include path, name, extension, checksum, tags, tag parts, tag hierarchy, and serialized frontmatter metadata text.

Chunk records include stable chunk id, source path, ordinal, source offsets, nearest heading or section label, chunk content, and optional embedding state. Ready embeddings are mirrored into the SQLite vec table in SQLite-backed sessions.

Key Behaviors

  • Derives markdown-aware chunks from cached headings, sections, and frontmatter-aware source positions.
  • Listens to metadata cache changed and deleted events for reactive updates and background embedding invalidation.
  • Indexes visible JSON Canvas node and edge text from .canvas files during refresh and canvas vault create/modify/delete events.
  • Retries startup embedding backfill when provider configuration lags initial layout so persisted semantic-search state eventually resumes without a manual refresh.
  • Starts provider warmup as soon as an embedding provider is configured, but treats startup provider configuration as best-effort post-mount work so proxy-session database delegation cannot block the rest of app boot.
  • Refreshes searchable markdown files even when metadata cache entries are still unavailable by indexing them with empty source-metadata snapshots until later metadata events enrich the stored search document.
  • Vault-driven semantic refresh also prunes stale generated search documents whose paths are no longer present in the current vault file list, so footer status and pending-chunk counts can recover from missed delete events or older failed runs.
  • Debounces metadata-cache changed and deleted events by source path so rapid edits collapse into bounded search-index updates and the latest content wins before the write reaches AppDatabase.
  • Wraps vault refresh indexing in AppDatabase search batches when the active backend supports them and yields to the UI thread between refresh items so long-running semantic refreshes do not monopolize the renderer event loop.
  • Delegates rebuild and query execution to AppDatabase.
  • Supports quoted property filters for exact and nested metadata paths, including nested object and array values such as ["project.name"] and ["items.name"].
  • Reports search index rebuilds and semantic-refresh backfills through app.notifications so long-running background work appears in the shared status-bar progress item and notification center. Errors are persisted as app notifications.
  • On Electron, simple lexical candidate selection can be served by the native SQLite FTS path behind AppDatabase; the search UI and query syntax do not fork by runtime.
  • SQLite-backed candidate builders quote generated prefix terms and split punctuation-heavy input such as hyphenated or underscored words before passing it to MATCH, avoiding FTS syntax errors while leaving final result semantics to the shared evaluator.
  • SQLite-backed candidate queries use deterministic rank/path ordering before the shared evaluator performs final scoring.
  • Electron native search keeps structured, case-sensitive, vector, and hybrid modes on the shared evaluator over mirrored documents, with native smoke coverage for those parity paths.
  • Electron vector and hybrid searches use native sqlite-vec candidates when a compatible extension is available, then fall back to the shared in-memory vector scorer when it is not.
  • The plugin now persists an Electron-only local query-enhancement request contract and forwards it to AppDatabase.searchDocuments() only when it is explicitly enabled and the runtime is Electron. The current implementation still keeps UI controls hidden and reports enhancement as unavailable until a runnable local model/reranker provider exists; strong lexical or hybrid RRF results are treated as an automatic skip condition.
  • Registers embedded markdown query code-block rendering backed by the same search manager.
  • Returns grouped file results with snippet text, explicit highlight ranges, chunk offsets, backend provenance, lexical-versus-semantic mode, and explainable RRF score breakdowns for hybrid ranking.

UI Ownership

The search view uses a CodeMirror query editor backed by the shared API search-query language, focus-time search option help, wrapper-click focus forwarding that keeps the query caret visible on first focus, operator autocomplete, vault-backed path:, file:, and tag: value autocomplete, fixed query controls, a scrolling results area, a copyable total-result summary, result sorting with responsive trigger truncation, match-case control, recent-search recall from the empty-query sidebar and with ArrowUp / ArrowDown when the caret is at the start of the query, inline presentation settings, explicit snippet highlighting, and click-to-open result navigation.

The semantic-search status-bar item remains a search-specific diagnostics surface for provider readiness, chunk counts, model download status, and embedding health. Status reads now prefer incremental app-database search stats instead of rescanning the full stored search corpus on every poll while indexing is active. Generic active-work visibility belongs to the shared notifications plugin.

The package follows the Plugin CSS Contract with workspace dist/app.css, standalone dist/styles.css, search-view__..., search-status..., and search-highlight selectors.