LocalLens

Request trace

Two flow diagrams — one through the CLI, one through the browser.

The clearest way to see how the eight files interact is to trace a single question through both entry points.

CLI question trace

CLI question
  → cli.ts            (parse argv, instantiate LocalLensApp)
  → locallens.ts      (createBrainFromFolder)
  →   files.ts        (discoverTextDocuments)
  →   rag.ts          (chunkDocuments → ragChunk)
  →   qvac.ts         (ingestChunks → ragIngest)
  →   store.ts        (saveBrain, saveChunks)
  → locallens.ts      (askBrain)
  →   qvac.ts         (search → ragSearch)
  →   rag.ts          (buildGroundedHistory)
  →   qvac.ts         (answer → completion stream)
  → locallens.ts      (assemble ChatAnswer)
  → cli.ts            (print answer + sources, deleteBrain, close)

Two things to notice:

  • The trace fans out from locallens.ts into the gateways and comes back. Every internal-to-internal call routes through the workflow class.
  • domain.ts doesn't appear in the trace. That's by design. Types don't participate in the runtime — they only constrain it.

Browser question trace

Browser question
  → ui/app.js         (event handler, fetch POST /api/brains/:id/chat)
  → server.ts         (route match, JSON parse)
  → locallens.ts      (askBrain)
  →   qvac.ts         (search)
  →   rag.ts          (buildGroundedHistory)
  →   qvac.ts         (answer)
  → locallens.ts      (assemble ChatAnswer)
  → server.ts         (JSON serialize, write response)
  → ui/app.js         (render markdown, append to chat thread)

The browser trace is the CLI trace plus an HTTP hop on each end. Once the request reaches locallens.ts, the path is identical to the CLI path.

Why this shape matters

Three properties fall out of one workflow class with thin entry points:

  1. One place to add a feature. LocalLensApp.askBrain is the single answer-the-question method. The CLI and the browser both benefit the moment you add to it.
  2. Stable error surface. Errors flow up through LocalLensApp, reach cli.ts or server.ts as AppError or generic Error, and get formatted by one helper at the edge.
  3. Easy to test. LocalLensApp can be unit-tested without spinning up a server or shell. The store swaps out for a temp-directory variant; the QVAC gateway can be stubbed.

Where it would break

If a feature needed a different workflow on the browser path than on the CLI path, the symmetry would crack. The right move then is to add a new method on LocalLensApp (or a new helper that consumes it), not to push logic into server.ts. Keep the entry points thin.

On this page