Plugin: AI chat over the vault — keyword RAG V1 (#70)#145
Merged
Conversation
Ships a v1.2 plugin that opens a fullscreen chat panel, runs a keyword BM25-lite retrieval pass over the vault, and streams an OpenAI or Anthropic completion back into the modal. Bring-your-own-key only; nothing leaves the browser until the user enters a key and hits Send. Key lives in the per-plugin settings namespace, displayed masked, and is never recorded in the audit trail (which logs vault writes only). V1 RAG is keyword-only — extract bag-of-words from the prompt, score each note with `Σ idf × tf/(tf+1)` (title hits weigh 2×), inject the top 5 bodies (truncated to ~500 chars) as a system message. Embeddings are a V2 roadmap item documented in the plugin README. Tests cover the pure surface (keyword extraction, scoring, request shape per provider, SSE parsing for both shapes, key masking, markdown serialisation). No real API calls in tests.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #70.
Summary
Adds
noteser-ai-chatas a reference plugin underpublic/plugins/,built on the v1.2 plugin API (fullscreen view +
vault.read.all+vault.write+ VNode events). Brings noteser its first conversationalRAG surface without touching core.
Provider choice
Bring-your-own-key for both OpenAI (
gpt-4o-minidefault,gpt-4oopt-in) and Anthropic (
claude-sonnet-4-6default,claude-haiku-4-5opt-in). The plugin posts directly toapi.openai.com/v1/chat/completionsandapi.anthropic.com/v1/messagesfrom the Worker via the ambient
fetchglobal. No noteser-hostedinference; nothing routes through any noteser server. Aligns with the
positioning note on #70 ("private, opt-in, bring-your-own-key" — the
issue's defining constraint).
Streaming is Server-Sent Events for both providers. The Worker
consumes the
ReadableStreamfromresponse.body, decodes thedata: …\n\nevents, and pushes onesetFullscreenContentper tokendelta so the user watches the response render in real time.
RAG approach
Keyword BM25-lite for V1. The flow on each Send:
extractKeywords).Lowercase, strip punctuation, drop ~50 inline stopwords, dedupe.
ctx.vault.read.getAllNotes(), cachedper-session for 30 seconds.
Σ idf(term) × tf / (tf + 1). Title hitsweigh 2× body hits.
get stitched into a system prompt asking the model to cite by
title in
[brackets].Toggle in Settings to disable RAG; off means a plain LLM call with
no vault content sent.
V2 roadmap (in README): swap keyword scoring for embeddings via the
existing
src/utils/embeddings.ts+src/utils/aiClient.tsonce aplugin-side embedding capability lands.
Key storage caveat
API key lives unencrypted in localStorage via the plugin's
per-plugin settings namespace (
ctx.setSetting('apiKey', …)). Displaymasks all but the last 4 chars. The audit trail (Settings → Plugins
→ Audit log) records
vault.writecalls only — it never sees thekey, the prompt, or the response. README ships an explicit warning:
"Do not paste a key on a shared machine."
V2 roadmap
embeddings.ts/aiClient.ts).linknodes back to source notes.network.fetchpermission once v1.3 surfaces it, so the installmodal can list
api.openai.com/api.anthropic.comexplicitly.Test plan
extractKeywordsunit tests (stopwords, dedupe, unicode, length floor)scoreNotesBM25-lite ranking on a fixture vaultbuildOpenAIRequestURL + headers + body shapebuildAnthropicRequestURL + headers (x-api-key,anthropic-version) + top-levelsystemfieldparseSseDeltasfor both providers (including malformed JSON tolerance)maskKeynever reveals more than last 4 charsconversationToMarkdown"save chat as note" shapenpm run lintclean,npx tsc --noEmitzero errorsnpm test -- --cigreen (208 / 208 suites)npm run devat/plugins/noteser-ai-chat/manifest.json