# https://github.com/ItzCrazyKns/Vane Project Manual

Generated at: 2026-06-22 13:15:59 UTC

## Table of Contents

- [Overview](#page-overview)
- [Src](#page-src)
- [Lib](#page-src-lib)
- [Models](#page-src-lib-models)

<a id='page-overview'></a>

## Overview

### Related Pages

Related topics: [Src](#page-src)

<details>
<summary>Related Source Files</summary>

The following source files were used to generate this page:

- [README.md](https://github.com/ItzCrazyKns/Vane/blob/main/README.md)
- [CONTRIBUTING.md](https://github.com/ItzCrazyKns/Vane/blob/main/CONTRIBUTING.md)
- [src/lib/agents/search/types.ts](https://github.com/ItzCrazyKns/Vane/blob/main/src/lib/agents/search/types.ts)
- [src/lib/config/index.ts](https://github.com/ItzCrazyKns/Vane/blob/main/src/lib/config/index.ts)
- [src/lib/prompts/search/classifier.ts](https://github.com/ItzCrazyKns/Vane/blob/main/src/lib/prompts/search/classifier.ts)
- [src/lib/prompts/search/researcher.ts](https://github.com/ItzCrazyKns/Vane/blob/main/src/lib/prompts/search/researcher.ts)
- [src/lib/prompts/search/writer.ts](https://github.com/ItzCrazyKns/Vane/blob/main/src/lib/prompts/search/writer.ts)
- [src/lib/agents/search/researcher/actions/plan.ts](https://github.com/ItzCrazyKns/Vane/blob/main/src/lib/agents/search/researcher/actions/plan.ts)
- [src/lib/agents/search/researcher/actions/search/webSearch.ts](https://github.com/ItzCrazyKns/Vane/blob/main/src/lib/agents/search/researcher/actions/search/webSearch.ts)
- [src/lib/agents/search/researcher/actions/scrapeURL.ts](https://github.com/ItzCrazyKns/Vane/blob/main/src/lib/agents/search/researcher/actions/scrapeURL.ts)
- [src/components/Navbar.tsx](https://github.com/ItzCrazyKns/Vane/blob/main/src/components/Navbar.tsx)
</details>

# Overview

Vane is a privacy-focused, open-source AI answering engine that combines large language models with web search, document understanding, and inline widgets to produce research-style responses. The project is a fork and rename of Perplexica and is built around a Next.js frontend with a custom (Langchain-free) backend pipeline that gives the maintainers low-level control over streaming, generation, and provider behavior — a deliberate architectural change introduced in the 1.12.0 release `Source: [README.md:1-30]()`.

This page provides a high-level tour of the system: what Vane is, how its search pipeline is organized, how the project is structured on disk, and the operational concerns that the community has surfaced around cost, stability, and security.

## Purpose and Capabilities

Vane positions itself as a drop-in, self-hostable alternative to commercial AI search products. Its feature set, as documented in the repository, includes:

- Multi-source web search backed by SearXNG, with support for discussions and academic engines `Source: [README.md:14-22]()`.
- Image and video search alongside text results.
- File uploads (PDF, text, images) that the assistant can read during research `Source: [README.md:18-26]()`.
- Domain-scoped search for limiting results to specific sites.
- Smart, inline UI widgets (weather, stocks, calculations, and other quick lookups) `Source: [README.md:16-18]()`.
- Local search history persisted on-device.

The frontend exposes this surface area through a small set of top-level routes: the landing/home page, the chat workspace at `/c`, a discover feed, and a library/history view `Source: [CONTRIBUTING.md:11-15]()`. Chat history can be exported to Markdown or PDF directly from the navigation bar `Source: [src/components/Navbar.tsx:30-60]()`.

## High-Level Architecture

Vane is a Next.js application whose backend code lives entirely under `src/lib`. The contributing guide splits the backend into well-defined subsystems: search agents, the database layer, model providers, prompt templates, SearXNG integration, and upload handling `Source: [CONTRIBUTING.md:11-23]()`. The search pipeline itself is further decomposed into four sequential stages: **classification**, **research**, **widgets**, and **writing** `Source: [CONTRIBUTING.md:15-19]()`.

```mermaid
flowchart LR
  User[User Query] --> Cls[Classifier]
  Cls -->|route to sources| Res[Researcher Agent]
  Res -->|tool calls| Web[Web / Academic / Social Search]
  Res -->|optional| Scrape[scrape_url]
  Res --> Wgt[Widgets]
  Wgt --> Wr[Writer]
  Wr --> Stream[Streamed Answer]
```

At the configuration layer, `Config` loads a JSON file from disk, merges it with environment variables, and persists user changes back to disk. The default schema declares client-visible model preferences (such as system instructions) and server-only settings (such as `SEARXNG_API_URL`) `Source: [src/lib/config/index.ts:1-60]()`. A key piece of the contract is the `SearchAgentConfig` type, which binds a query to a specific `BaseLLM`, a `BaseEmbedding`, a set of `sources` (`'web' | 'discussions' | 'academic'`), a `mode` (`'speed' | 'balanced' | 'quality'`), and any uploaded `fileIds` `Source: [src/lib/agents/search/types.ts:6-15]()`.

## The Search Pipeline

**Classification.** The first stage uses an LLM to inspect the query and produce a structured `ClassifierOutput` that flags whether a search is required, whether the user wants academic or discussion results, and whether a weather or stock widget is appropriate `Source: [src/lib/prompts/search/classifier.ts:1-30]()`. Per the contributing guide, the classifier is what decides whether research is needed at all `Source: [CONTRIBUTING.md:25-29]()`.

**Research.** When research is required, the researcher agent enters an iterative loop. The agent is required to call a `__reasoning_preamble` tool before every other action to state a short natural-language plan, then issue tool calls such as `web_search`, `scrape_url`, or a `done` signal `Source: [src/lib/agents/search/researcher/actions/plan.ts:1-40]()`. The quality-mode prompt instructs the agent to perform 5–6 iterations of searching unless the question is trivial, and to use all three query slots per call to maximize coverage `Source: [src/lib/agents/search/researcher/actions/search/webSearch.ts:1-30]()`. Specialized actions exist for academic sources (arxiv, google scholar, pubmed) and discussions (reddit) `Source: [src/lib/agents/search/researcher/actions/search/academicSearch.ts:1-25]()`. When the user explicitly references a URL, the `scrape_url` action fetches and extracts up to three pages in parallel `Source: [src/lib/agents/search/researcher/actions/scrapeURL.ts:1-30]()`.

**Widgets and Writing.** Widget actions run in parallel and can short-circuit the research path entirely when, for example, the user only wants a stock quote or the current weather. Results are then handed to the writer prompt, which instructs the model to produce a blog-style, well-cited Markdown response with inline numeric citations referencing the gathered context `Source: [src/lib/prompts/search/writer.ts:1-30]()`.

## Operational Concerns and Known Issues

Several community-reported issues map directly to components in the codebase and are worth flagging for operators:

- **Search hangs on "Brainstorming..."** — A streaming crash in the OpenAI-compatible provider when tool-call `function.arguments` is empty or partial has been reported; it surfaces as the UI being stuck mid-research `Source: community issue #1150`.
- **Cost spikes via OpenRouter** — Users have reported unexpectedly large OpenRouter charges (e.g. $3,000) tied to background features such as auto video search running expensive models; the LLM provider is selected via the same `SearchAgentConfig` path described above.
- **SearXNG returning zero results** — Reports of searches that "find" results but never produce a final answer point at fragile interaction between the researcher loop and SearXNG responses `Source: community issue #1143`.
- **Ollama embedding saturation** — Concurrent searches each spawn independent embedding calls with no global cap, which can 502 local Ollama servers under load `Source: community issue #1147`.
- **Unsafe shell execution** — A confirmed real-world RCE was traced to unsafe `child_process` usage; the 1.12.2 release notes call out validation and timeouts that mitigate hung requests, but operators should still sandbox the container.

For the latest mitigations, the 1.12.2 release notes record fixes for history double-conversion, validation/timeouts on hung requests, widget error isolation, and missing build-time dependencies.

## See Also

- Search Pipeline
- Configuration
- Model Providers
- LLM Prompts

---

<a id='page-src'></a>

## Src

### Related Pages

Related topics: [Overview](#page-overview), [Lib](#page-src-lib)

<details>
<summary>Related Source Files</summary>

The following source files were used to generate this page:

- [src/lib/prompts/search/writer.ts](https://github.com/ItzCrazyKns/Vane/blob/main/src/lib/prompts/search/writer.ts)
- [README.md](https://github.com/ItzCrazyKns/Vane/blob/main/README.md)
- [src/lib/prompts/search/researcher.ts](https://github.com/ItzCrazyKns/Vane/blob/main/src/lib/prompts/search/researcher.ts)
- [src/lib/agents/search/researcher/actions/search/socialSearch.ts](https://github.com/ItzCrazyKns/Vane/blob/main/src/lib/agents/search/researcher/actions/search/socialSearch.ts)
- [src/lib/prompts/search/classifier.ts](https://github.com/ItzCrazyKns/Vane/blob/main/src/lib/prompts/search/classifier.ts)
- [src/lib/agents/search/researcher/actions/plan.ts](https://github.com/ItzCrazyKns/Vane/blob/main/src/lib/agents/search/researcher/actions/plan.ts)
- [CONTRIBUTING.md](https://github.com/ItzCrazyKns/Vane/blob/main/CONTRIBUTING.md)
- [src/lib/agents/search/types.ts](https://github.com/ItzCrazyKns/Vane/blob/main/src/lib/agents/search/types.ts)
- [src/components/Navbar.tsx](https://github.com/ItzCrazyKns/Vane/blob/main/src/components/Navbar.tsx)
- [src/lib/agents/search/researcher/actions/search/academicSearch.ts](https://github.com/ItzCrazyKns/Vane/blob/main/src/lib/agents/search/researcher/actions/search/academicSearch.ts)
- [src/lib/agents/search/researcher/actions/search/webSearch.ts](https://github.com/ItzCrazyKns/Vane/blob/main/src/lib/agents/search/researcher/actions/search/webSearch.ts)
- [src/lib/agents/search/researcher/actions/search/baseSearch.ts](https://github.com/ItzCrazyKns/Vane/blob/main/src/lib/agents/search/researcher/actions/search/baseSearch.ts)
- [src/lib/config/index.ts](https://github.com/ItzCrazyKns/Vane/blob/main/src/lib/config/index.ts)
</details>

# Src

The `src/` directory is the application source for Vane, a privacy-focused AI answering engine that combines web search, research agents, and large language models (LLMs). The codebase is organized into a Next.js front end (`src/app`, `src/components`) and a backend library (`src/lib`) that houses the search pipeline, prompt templates, model providers, and configuration loader. The structure is documented in the contributor map, which identifies the search pipeline as the central subsystem alongside the model registry and configuration system. Source: [CONTRIBUTING.md](https://github.com/ItzCrazyKns/Vane/blob/main/CONTRIBUTING.md)

## High-Level Layout

Vane separates presentation from reasoning logic. The Next.js `app/` directory owns pages (`/`, `/c`, `/discover`, `/library`) and HTTP route handlers, while `src/lib` holds all of the AI and search infrastructure. According to the project map, the search system lives at `src/lib/agents/search`, the database layer sits at `src/lib/db`, the model registry at `src/lib/models/registry.ts`, the prompt templates at `src/lib/prompts`, the SearXNG client at `src/lib/searxng.ts`, and the uploaded-file search at `src/lib/uploads`. Source: [CONTRIBUTING.md](https://github.com/ItzCrazyKns/Vane/blob/main/CONTRIBUTING.md)

The top-level README states that Vane "combines knowledge from the vast internet" with local execution, exposing features such as widgets, image and video search, file uploads, domain-scoped search, and search history. The frontend in `src/components` (e.g., `Navbar.tsx`) is responsible for chat surface, export to Markdown/PDF, and discovery feeds. Source: [README.md](https://github.com/ItzCrazyKns/Vane/blob/main/README.md), Source: [src/components/Navbar.tsx](https://github.com/ItzCrazyKns/Vane/blob/main/src/components/Navbar.tsx)

## Search Agent Architecture

The search agent is the heart of `src/`. Its TypeScript contracts in `src/lib/agents/search/types.ts` define the inputs and outputs of the pipeline. `SearchAgentConfig` enumerates the supported `SearchSources` (`'web' | 'discussions' | 'academic'`) and the `mode` field, which can be `'speed' | 'balanced' | 'quality'`. Source: [src/lib/agents/search/types.ts](https://github.com/ItzCrazyKns/Vane/blob/main/src/lib/agents/search/types.ts)

```mermaid
flowchart LR
  A[User Query] --> B[Classifier]
  B -->|skipSearch=false| C[Researcher]
  B -->|widget| D[Widget Engine]
  C --> E[Web Search]
  C --> F[Social Search]
  C --> G[Academic Search]
  C --> H[Writer Prompt]
  H --> I[Final Answer]
```

The classifier at `src/lib/prompts/search/classifier.ts` is the first stage; it inspects the query and chat history to decide flags such as `skipSearch`, `personalSearch`, `academicSearch`, `discussionSearch`, `showWeatherWidget`, and `showStockWidget`. The widget fields are set to `true` when a query can be fully answered by a UI widget (e.g., a weather or stock card), in which case the classifier also sets `skipSearch` so the pipeline does not waste tool calls. Source: [src/lib/prompts/search/classifier.ts](https://github.com/ItzCrazyKns/Vane/blob/main/src/lib/prompts/search/classifier.ts)

The researcher runs a tool-calling loop. Its prompt template at `src/lib/prompts/search/researcher.ts` enforces a strict `__reasoning_preamble → tool call → ... → done` protocol and requires 4–7 information-gathering calls in the comprehensive mode, with explicit mistakes to avoid (over-assuming, verification obsession, endless loops, skipping the reasoning step). When the user has uploaded files, the prompt injects a `<user_uploaded_files>` block sourced from `UploadStore.getFileData(fileIds)`. Source: [src/lib/prompts/search/researcher.ts](https://github.com/ItzCrazyKns/Vane/blob/main/src/lib/prompts/search/researcher.ts)

The `__reasoning_preamble` action is defined in `src/lib/agents/search/researcher/actions/plan.ts`; it captures a one-paragraph natural-language plan using a Zod schema and is mandated to run before every other tool call. Source: [src/lib/agents/search/researcher/actions/plan.ts](https://github.com/ItzCrazyKns/Vane/blob/main/src/lib/agents/search/researcher/actions/plan.ts)

### Source-Specific Search Actions

Each search source is implemented as a self-contained action with a Zod schema, an `enabled` predicate, and an `execute` function. The web action (`webSearch.ts`) slices inputs to 3 queries and dispatches via the shared `executeSearch` helper, while prompting the model to run "at least 5–6 iterations of searches" in quality mode. Source: [src/lib/agents/search/researcher/actions/search/webSearch.ts](https://github.com/ItzCrazyKns/Vane/blob/main/src/lib/agents/search/researcher/actions/search/webSearch.ts)

The social action gates on `config.sources.includes('discussions')` and pins the SearXNG engines to `['reddit']`. Source: [src/lib/agents/search/researcher/actions/search/socialSearch.ts](https://github.com/ItzCrazyKns/Vane/blob/main/src/lib/agents/search/researcher/actions/search/socialSearch.ts)

The academic action gates on `config.sources.includes('academic')` and pins engines to `['arxiv', 'google scholar', 'pubmed']`. Both actions retrieve the live research block from the session and return `{ type: 'search_results', results }`. Source: [src/lib/agents/search/researcher/actions/search/academicSearch.ts](https://github.com/ItzCrazyKns/Vane/blob/main/src/lib/agents/search/researcher/actions/search/academicSearch.ts)

The shared `baseSearch.ts` defines the extraction rules applied to scraped pages: discard marketing fluff, merge duplicates, and preserve numerical data verbatim (e.g., "LiveCodeBench v6: 80.0%." rather than "Improved coding scores."). Source: [src/lib/agents/search/researcher/actions/search/baseSearch.ts](https://github.com/ItzCrazyKns/Vane/blob/main/src/lib/agents/search/researcher/actions/search/baseSearch.ts)

Finally, the writer prompt at `src/lib/prompts/search/writer.ts` produces the final blog-style response, demanding inline `[number]` citations, well-structured Markdown headings, and an engaging journalistic tone. It is parameterized by `context`, `systemInstructions`, and the same `mode` value passed through the pipeline. Source: [src/lib/prompts/search/writer.ts](https://github.com/ItzCrazyKns/Vane/blob/main/src/lib/prompts/search/writer.ts)

## Configuration and Provider Wiring

Runtime configuration is loaded by `src/lib/config/index.ts`. The config exposes three sections: `modelProviders`, a free-form `systemInstructions` string, and `search` options (currently just `searxngURL` mapped to the `SEARXNG_API_URL` env variable). Configuration is persisted to a JSON file at `this.configPath` and can be overridden by environment variables during `initialize()`. Source: [src/lib/config/index.ts](https://github.com/ItzCrazyKns/Vane/blob/main/src/lib/config/index.ts)

The `scope` field on each option (`'client'` vs `'server'`) determines where the value is consumed. This is how Vane wires SearXNG access into the agent loop without exposing secrets to the browser. Per the contribution map, model providers themselves are implemented under `src/lib/models/providers` and registered through `src/lib/models/registry.ts`. Source: [src/lib/config/index.ts](https://github.com/ItzCrazyKns/Vane/blob/main/src/lib/config/index.ts), Source: [CONTRIBUTING.md](https://github.com/ItzCrazyKns/Vane/blob/main/CONTRIBUTING.md)

## Community Notes Relevant to the Search Pipeline

Several high-engagement issues map directly onto modules under `src/`. The "Search is broken" report (SearXNG returning zero results) relates to the same `searxngURL` config option above. The OpenRouter streaming crash on empty `function.arguments` chunks lives in `src/lib/models/providers/openai/openaiLLM.ts`, while the Ollama embedding concurrency issue involves the embedding client called from the search actions. The "Vane charged $3000 via auto video search" report is tied to the `mode` and source configuration surfaced in `SearchAgentConfig`. These community findings highlight that the search pipeline in `src/lib/agents/search` is sensitive to provider-level streaming behavior, embedding-server load, and SearXNG availability.

## See Also

- Search agent types: [src/lib/agents/search/types.ts](https://github.com/ItzCrazyKns/Vane/blob/main/src/lib/agents/search/types.ts)
- Researcher prompt: [src/lib/prompts/search/researcher.ts](https://github.com/ItzCrazyKns/Vane/blob/main/src/lib/prompts/search/researcher.ts)
- Configuration loader: [src/lib/config/index.ts](https://github.com/ItzCrazyKns/Vane/blob/main/src/lib/config/index.ts)
- Contributing guide: [CONTRIBUTING.md](https://github.com/ItzCrazyKns/Vane/blob/main/CONTRIBUTING.md)

---

<a id='page-src-lib'></a>

## Lib

### Related Pages

Related topics: [Src](#page-src), [Models](#page-src-lib-models)

<details>
<summary>Related Source Files</summary>

The following source files were used to generate this page:

- [README.md](https://github.com/ItzCrazyKns/Vane/blob/main/README.md)
- [CONTRIBUTING.md](https://github.com/ItzCrazyKns/Vane/blob/main/CONTRIBUTING.md)
- [src/lib/agents/search/types.ts](https://github.com/ItzCrazyKns/Vane/blob/main/src/lib/agents/search/types.ts)
- [src/lib/prompts/search/classifier.ts](https://github.com/ItzCrazyKns/Vane/blob/main/src/lib/prompts/search/classifier.ts)
- [src/lib/prompts/search/researcher.ts](https://github.com/ItzCrazyKns/Vane/blob/main/src/lib/prompts/search/researcher.ts)
- [src/lib/prompts/search/writer.ts](https://github.com/ItzCrazyKns/Vane/blob/main/src/lib/prompts/search/writer.ts)
- [src/lib/agents/search/researcher/actions/plan.ts](https://github.com/ItzCrazyKns/Vane/blob/main/src/lib/agents/search/researcher/actions/plan.ts)
- [src/lib/agents/search/researcher/actions/scrapeURL.ts](https://github.com/ItzCrazyKns/Vane/blob/main/src/lib/agents/search/researcher/actions/scrapeURL.ts)
- [src/lib/agents/search/researcher/actions/search/baseSearch.ts](https://github.com/ItzCrazyKns/Vane/blob/main/src/lib/agents/search/researcher/actions/search/baseSearch.ts)
- [src/lib/agents/search/researcher/actions/search/webSearch.ts](https://github.com/ItzCrazyKns/Vane/blob/main/src/lib/agents/search/researcher/actions/search/webSearch.ts)
- [src/lib/agents/search/researcher/actions/search/socialSearch.ts](https://github.com/ItzCrazyKns/Vane/blob/main/src/lib/agents/search/researcher/actions/search/socialSearch.ts)
- [src/lib/agents/search/researcher/actions/search/academicSearch.ts](https://github.com/ItzCrazyKns/Vane/blob/main/src/lib/agents/search/researcher/actions/search/academicSearch.ts)
- [src/lib/agents/suggestions/index.ts](https://github.com/ItzCrazyKns/Vane/blob/main/src/lib/agents/suggestions/index.ts)
- [src/components/Navbar.tsx](https://github.com/ItzCrazyKns/Vane/blob/main/src/components/Navbar.tsx)
</details>

# Lib

## Overview and Scope

The `src/lib` directory is the **backend core** of Vane, a privacy-focused AI answering engine that combines LLM reasoning with web search [README.md:1-20](README.md). It houses every non-UI concern of the application: the search and chat agent pipeline, prompt templates, model provider abstractions, database access, SearXNG integration, and upload handling [CONTRIBUTING.md:9-23](CONTRIBUTING.md). In other words, while `src/app` and `src/components` render the Next.js frontend (home, `/c`, `/discover`, `/library`), `src/lib` is where requests are understood, classified, researched, and answered.

The v1.12.0 release marked a significant architectural change for this layer: the project was refactored to remove Langchain in favor of a custom implementation, providing low-level control over streaming, generation, and provider-specific features. This refactor is what makes the current `src/lib` shape possible — every model, prompt, and agent is purpose-built rather than wrapped around an external framework.

## Key Subsystems

The `src/lib` tree is organized into a small number of clearly-scoped subsystems. The `CONTRIBUTING.md` map is the canonical guide to where changes should be made [CONTRIBUTING.md:15-37](CONTRIBUTING.md).

| Subsystem | Path | Responsibility |
|---|---|---|
| Search pipeline | `src/lib/agents/search` | Chat + search pipeline (classifier → researcher → widgets → writer) |
| Database | `src/lib/db` | Persistence of chats, messages, and uploads |
| Model providers | `src/lib/models/providers` | LLM and embedding adapters, loaded via `src/lib/models/registry.ts` |
| Prompts | `src/lib/prompts` | Prompt templates for the agent loop |
| SearXNG client | `src/lib/searxng.ts` | Integration with the privacy-respecting meta search engine |
| Uploads | `src/lib/uploads` | File upload search across PDFs, text, and images |
| Suggestions | `src/lib/agents/suggestions` | "What should I ask next?" generator |

The model registry in `src/lib/models/registry.ts` is the single switchboard through which new chat and embedding providers are wired in; this is the recommended extension point when adding a backend such as Deepseek or another OpenAI-compatible service.

## The Search Agent Pipeline

The most complex subsystem under `src/lib` is the search agent, whose types are defined in `src/lib/agents/search/types.ts`. A `SearchAgentConfig` carries the enabled `SearchSources` (`'web' | 'discussions' | 'academic'`), the LLM, the embedding model, the operation mode (`'speed' | 'balanced' | 'quality'`), and any uploaded `fileIds` [src/lib/agents/search/types.ts:5-15](src/lib/agents/search/types.ts). The pipeline itself is divided into four stages, as documented in `CONTRIBUTING.md` [CONTRIBUTING.md:19-23](CONTRIBUTING.md).

```mermaid
flowchart LR
    U[User query] --> C[Classifier]
    C -->|needs research| R[Researcher loop]
    C -->|widget only| W[Widgets]
    R -->|webSearch / socialSearch / academicSearch| S[SearXNG + scraper]
    S -->|chunks| R
    R -->|done| WR[Writer]
    W --> WR
    WR --> A[Final answer + sources]
```

### Classifier

`src/lib/prompts/search/classifier.ts` instructs the LLM to decide what kind of response is needed. The classifier emits booleans such as `skipSearch`, `personalSearch`, `academicSearch`, `discussionSearch`, `showWeatherWidget`, and `showStockWidget` [src/lib/prompts/search/classifier.ts:1-40](src/lib/prompts/search/classifier.ts). Setting `skipSearch: true` short-circuits the rest of the pipeline and routes the query directly to the writer, which is also how widget-only requests (e.g. "What's the weather in Berlin?") are handled without burning tool calls on web search.

### Researcher

The researcher stage is an iterative agent loop driven by a set of typed `ResearchAction`s. The loop is mandated to start every turn with a `__reasoning_preamble` action that states the plan in natural language [src/lib/agents/search/researcher/actions/plan.ts:1-30](src/lib/agents/search/researcher/actions/plan.ts). The researcher prompt enforces a 4–7 information-gathering cadence with cross-referencing and explicit anti-patterns (over-assuming, verification obsession, endless loops) [src/lib/prompts/search/researcher.ts:1-60](src/lib/prompts/search/researcher.ts).

Search actions are gated by both the user's enabled sources and the classifier's booleans. For example, `socialSearch.ts` only runs when `'discussions'` is enabled and `discussionSearch === true`; it then calls the shared `executeSearch` helper with `engines: ['reddit']` [src/lib/agents/search/researcher/actions/search/socialSearch.ts:1-20](src/lib/agents/search/researcher/actions/search/socialSearch.ts). `academicSearch.ts` follows the same pattern but pins engines to `['arxiv', 'google scholar', 'pubmed']` [src/lib/agents/search/researcher/actions/search/academicSearch.ts:1-20](src/lib/agents/search/researcher/actions/search/academicSearch.ts), while `webSearch.ts` instructs the model to iterate 5–6 times in quality mode and to issue up to three queries per call [src/lib/agents/search/researcher/actions/search/webSearch.ts:1-40](src/lib/agents/search/researcher/actions/search/webSearch.ts). All of these delegate the actual retrieval+rerank+compression to the shared `baseSearch` action, which in turn is responsible for the high-density extraction rules used to compress scraped pages [src/lib/agents/search/researcher/actions/search/baseSearch.ts:1-20](src/lib/agents/search/researcher/actions/search/baseSearch.ts).

The `scrapeURL.ts` action exposes a separate tool that fetches a specific URL, splits it, and asks the LLM to extract telegram-style facts — discarding navigation chrome, marketing fluff, and duplicate facts while preserving numerical data verbatim [src/lib/agents/search/researcher/actions/scrapeURL.ts:1-20](src/lib/agents/search/researcher/actions/scrapeURL.ts).

### Writer

Once the researcher declares `done`, control passes to the writer. The writer prompt is a blog-style instruction set that asks Vane to produce a well-structured, Markdown-formatted response with inline `[number]` citations back to the retrieved context [src/lib/prompts/search/writer.ts:1-30](src/lib/prompts/search/writer.ts). The same citation tokens are later resolved in the UI; for example, the chat `Navbar` exposes Markdown and PDF export of the final sections [src/components/Navbar.tsx:1-20](src/components/Navbar.tsx).

## Suggestions, Models, and Extensibility

A small but important sibling to the search agent is the **suggestion generator** in `src/lib/agents/suggestions/index.ts`. After each turn, the LLM is called with the chat history to produce follow-up questions, which is also where the v1.12.2 fix for "history double-conversion" landed. The same `BaseLLM` abstraction used by the search agent is reused here, which keeps the model layer pluggable [src/lib/agents/suggestions/index.ts:1-25](src/lib/agents/suggestions/index.ts).

This pluggability is the most common community extension point: feature requests for additional LLM-optimized search providers (Tavily, Exa, Firecrawl, jina-ai, serpbase.dev) and additional chat providers (Deepseek, LM Studio) all resolve to the same architectural rule — add a new adapter under `src/lib/models/providers`, register it in `src/lib/models/registry.ts`, and surface it through the settings UI. Because the search pipeline's tool-calling, streaming, and JSON parsing are now handled by a custom implementation (post v1.12.0), providers can be added without inheriting Langchain-era quirks that historically caused "search is broken" or "Brainstorming forever" hangs.

## See Also

- Architecture overview
- Search agent pipeline deep-dive
- Model provider registry and adding a new provider
- SearXNG integration
- Upload search
- Contributing guide

---

<a id='page-src-lib-models'></a>

## Models

### Related Pages

Related topics: [Lib](#page-src-lib)

<details>
<summary>Related Source Files</summary>

The following source files were used to generate this page:

- [src/lib/models/providers/ollama/ollamaLLM.ts](https://github.com/ItzCrazyKns/Vane/blob/main/src/lib/models/providers/ollama/ollamaLLM.ts)
- [src/lib/agents/search/types.ts](https://github.com/ItzCrazyKns/Vane/blob/main/src/lib/agents/search/types.ts)
- [src/lib/config/index.ts](https://github.com/ItzCrazyKns/Vane/blob/main/src/lib/config/index.ts)
- [src/lib/agents/search/researcher/actions/search/baseSearch.ts](https://github.com/ItzCrazyKns/Vane/blob/main/src/lib/agents/search/researcher/actions/search/baseSearch.ts)
- [src/lib/agents/search/researcher/actions/search/webSearch.ts](https://github.com/ItzCrazyKns/Vane/blob/main/src/lib/agents/search/researcher/actions/search/webSearch.ts)
- [src/lib/agents/search/researcher/actions/scrapeURL.ts](https://github.com/ItzCrazyKns/Vane/blob/main/src/lib/agents/search/researcher/actions/scrapeURL.ts)
- [src/lib/agents/search/researcher/actions/plan.ts](https://github.com/ItzCrazyKns/Vane/blob/main/src/lib/agents/search/researcher/actions/plan.ts)
- [src/lib/prompts/search/classifier.ts](https://github.com/ItzCrazyKns/Vane/blob/main/src/lib/prompts/search/classifier.ts)
- [src/lib/prompts/search/researcher.ts](https://github.com/ItzCrazyKns/Vane/blob/main/src/lib/prompts/search/researcher.ts)
- [src/lib/prompts/search/writer.ts](https://github.com/ItzCrazyKns/Vane/blob/main/src/lib/prompts/search/writer.ts)
- [src/lib/agents/search/researcher/actions/search/academicSearch.ts](https://github.com/ItzCrazyKns/Vane/blob/main/src/lib/agents/search/researcher/actions/search/academicSearch.ts)
- [src/lib/agents/search/researcher/actions/search/socialSearch.ts](https://github.com/ItzCrazyKns/Vane/blob/main/src/lib/agents/search/researcher/actions/search/socialSearch.ts)
- [CONTRIBUTING.md](https://github.com/ItzCrazyKns/Vane/blob/main/CONTRIBUTING.md)
- [README.md](https://github.com/ItzCrazyKns/Vane/blob/main/README.md)
</details>

# Models

The Models subsystem supplies the generative and vector capabilities that power every stage of Vane's research pipeline. It abstracts chat-completion and embedding providers behind a common interface so that the classifier, researcher, writer, and search-ranking code can stay provider-agnostic.

## Purpose and Role in the Architecture

Vane's search pipeline is composed of cooperating agents that each consume language-model calls and (optionally) embedding-model calls. The `SearchAgentConfig` type in [src/lib/agents/search/types.ts](https://github.com/ItzCrazyKns/Vane/blob/main/src/lib/agents/search/types.ts) declares a `llm: BaseLLM<any>` and an `embedding: BaseEmbedding<any>` alongside a `mode` of `'speed' | 'balanced' | 'quality'`. These two model objects are passed into every action — from the initial classifier through to the final writer — meaning that changing a provider (for example, swapping Ollama for OpenRouter) is a configuration concern rather than a code change in the agent logic.

Per [CONTRIBUTING.md](https://github.com/ItzCrazyKns/Vane/blob/main/CONTRIBUTING.md), the project is organized so that "Chat model and embedding model providers are in `src/lib/models/providers`, and models are loaded via `src/lib/models/registry.ts`." This separation lets users self-host with local weights (Ollama) or route through hosted APIs without touching the search agents.

```mermaid
flowchart LR
    User[User Query] --> Classifier
    Classifier --> Researcher
    Researcher --> Search[SearXNG / Scraper]
    Search --> Embed[Embedding Model]
    Researcher --> Writer
    Writer --> Out[Final Answer]
    LLM[LLM Provider] -.feeds.-> Classifier
    LLM -.feeds.-> Researcher
    LLM -.feeds.-> Writer
    Embed -.feeds.-> Search
```

## Provider Architecture and the Ollama Implementation

Vane ships provider-specific subclasses of the base `LLM` and `Embedding` classes. The Ollama implementation in [src/lib/models/providers/ollama/ollamaLLM.ts](https://github.com/ItzCrazyKns/Vane/blob/main/src/lib/models/providers/ollama/ollamaLLM.ts) extends `BaseLLM` and instantiates a typed `Ollama` client whose host defaults to `http://localhost:11434` but can be overridden through `config.baseURL`. The class maintains an explicit allowlist of reasoning-capable models that require special handling:

```
gpt-oss, deepseek-r1, qwen3, deepseek-v3.1,
magistral, nemotron-3, nemotron-cascade-2, glm-4.7-flash
```

Source: [src/lib/models/providers/ollama/ollamaLLM.ts:13-21](https://github.com/ItzCrazyKns/Vane/blob/main/src/lib/models/providers/ollama/ollamaLLM.ts#L13-L21)

The constructor signature takes `{ baseURL, model, options? }`, exposing only the fields needed to talk to a local daemon. The model expects tool-calling output and supports a robust JSON-recovery path: it imports `parse` from `partial-json` and `repairJson` from `@toolsycc/json-repair`, which lets it tolerate partial or malformed streamed arguments that would otherwise crash the parser — the exact class of bug reported for OpenRouter-compatible streams in [issue #1150](https://github.com/ItzCrazyKns/Vane/issues/1150).

Provider configuration is surfaced through [src/lib/config/index.ts](https://github.com/ItzCrazyKns/Vane/blob/main/src/lib/config/index.ts). The default config defines a `searxngURL` server-scope option (env: `SEARXNG_API_URL`) and a generic `modelProviders: []` array, meaning additional providers can be appended without modifying the core config schema. The config file is created on first run, parsed lazily, and regenerated if it contains invalid JSON.

## How Models Drive Each Pipeline Stage

The classifier is the first consumer. The prompt in [src/lib/prompts/search/classifier.ts](https://github.com/ItzCrazyKns/Vane/blob/main/src/lib/prompts/search/classifier.ts) asks the LLM to emit structured booleans — `skipSearch`, `personalSearch`, `academicSearch`, `discussionSearch`, `showWeatherWidget`, `showStockWidget` — which gate the rest of the pipeline. Because the classifier only relies on the LLM's `generateObject` capability, swapping providers is transparent.

The researcher in [src/lib/prompts/search/researcher.ts](https://github.com/ItzCrazyKns/Vane/blob/main/src/lib/prompts/search/researcher.ts) is a tool-calling agent that loops through actions. Per the prompt, the agent "MUST call `__reasoning_preamble` before every tool call in this assistant turn" — a hard protocol enforced by [src/lib/agents/search/researcher/actions/plan.ts](https://github.com/ItzCrazyKns/Vane/blob/main/src/lib/agents/search/researcher/actions/plan.ts), whose action description states: "YOU CAN NEVER CALL ANY OTHER TOOL BEFORE CALLING THIS ONE FIRST, IF YOU DO, THAT CALL WOULD BE IGNORED." This depends on the LLM's tool-use capabilities, which is why v1.12.1 explicitly "Fixed issues with function calling with OpenAI compatible providers."

Search actions thread both the LLM and the embedding through their `execute` signatures. The base search action in [src/lib/agents/search/researcher/actions/search/baseSearch.ts](https://github.com/ItzCrazyKns/Vane/blob/main/src/lib/agents/search/researcher/actions/search/baseSearch.ts) instructs the LLM to extract high-density, telegram-style facts, prioritizing "Numerical Data Integrity" and discouraging "marketing fluff." Domain-specialized actions — [webSearch.ts](https://github.com/ItzCrazyKns/Vane/blob/main/src/lib/agents/search/researcher/actions/search/webSearch.ts) (broad-to-narrow web queries), [academicSearch.ts](https://github.com/ItzCrazyKns/Vane/blob/main/src/lib/agents/search/researcher/actions/search/academicSearch.ts) (arxiv, google scholar, pubmed), and [socialSearch.ts](https://github.com/ItzCrazyKns/Vane/blob/main/src/lib/agents/search/researcher/actions/search/socialSearch.ts) (reddit) — all cap their input to three queries and write results back into the `ResearchBlock` retrieved from the session. The scrape action in [src/lib/agents/search/researcher/actions/scrapeURL.ts](https://github.com/ItzCrazyKns/Vane/blob/main/src/lib/agents/search/researcher/actions/scrapeURL.ts) emits its content as `Chunk` objects, again feeding them through the session so the writer has the full evidence trail.

Finally, the writer prompt in [src/lib/prompts/search/writer.ts](https://github.com/ItzCrazyKns/Vane/blob/main/src/lib/prompts/search/writer.ts) is invoked with the gathered context, a system-instructions string, and a `mode` (speed/balanced/quality). The `mode` parameter corresponds to the same enum used in `SearchAgentConfig` and lets the user trade latency against answer depth.

## Known Failure Modes and Community Reports

Several issues map directly onto the model layer and are worth flagging:

- **Ollama embedding flood** ([#1147](https://github.com/ItzCrazyKns/Vane/issues/1147)) — each concurrent search creates a fresh `ollamaClient.embed()` call with no concurrency cap, causing 502s on the embedding server under 5–10 parallel searches.
- **OpenRouter stream crash on empty tool args** ([#1150](https://github.com/ItzCrazyKns/Vane/issues/1150)) — the OpenAI-compatible parser in `openaiLLM.ts` can throw on partial `function.arguments`, leaving the UI stuck on "Brainstorming…".
- **Unexpected OpenRouter charges** ([#1144](https://github.com/ItzCrazyKns/Vane/issues/1144)) — auto video search with an opus-class model was triggered without user action, illustrating that the researcher loop will keep calling paid models until it satisfies the `done` protocol.
- **v1.12.2 regression** ([#1154](https://github.com/ItzCrazyKns/Vane/issues/1154)) — the post-Perplexica-rename refactor leaves new containers "brainstorming forever," typically a classifier-or-tool-call failure rather than a SearXNG issue (compare with [#1143](https://github.com/ItzCrazyKns/Vane/issues/1143)).

The v1.12.2 release notes explicitly address some of this surface: "Fixed history double-conversion bugs… Added validation and timeouts to prevent hung search requests. Improved widget execution handling; errors no longer crash the entire research pipeline."

## See Also

- [Search Pipeline](search-pipeline.md) — the agents that consume these models
- [Configuration](configuration.md) — `src/lib/config/index.ts` and env-variable mapping
- [Providers](providers.md) — full list of supported LLM and embedding backends

---

<!-- evidence_pipeline_checked: true -->
<!-- evidence_injected: true -->

---

## Pitfall Log

Project: ItzCrazyKns/Vane

Summary: Found 16 structured pitfall item(s), including 2 high/blocking item(s). Top priority: Security or permission risk - Security or permission risk requires verification.

## 1. Security or permission risk - Security or permission risk requires verification

- Severity: high
- Evidence strength: source_linked
- Finding: Project evidence flags a security or permission risk. Review the linked source before relying on this workflow.
- User impact: May increase setup, validation, or first-run risk for the user.
- Evidence: community_evidence:github | https://github.com/ItzCrazyKns/Vane/issues/946

## 2. Security or permission risk - Security or permission risk requires verification

- Severity: high
- Evidence strength: source_linked
- Finding: Project evidence flags a security or permission risk. Review the linked source before relying on this workflow.
- User impact: May increase setup, validation, or first-run risk for the user.
- Evidence: community_evidence:github | https://github.com/ItzCrazyKns/Vane/issues/1144

## 3. Installation risk - Installation risk requires verification

- Severity: medium
- Evidence strength: runtime_trace
- Finding: Project evidence flags a installation risk. Review the linked source before relying on this workflow.
- User impact: May increase setup, validation, or first-run risk for the user.
- Repro command: `docker run -d -p 3000:3000 -v vane-data:/home/vane/data --name vane itzcrazykns1337/vane:latest`
- Evidence: identity.distribution | https://github.com/ItzCrazyKns/Vane

## 4. Installation risk - Installation risk requires verification

- Severity: medium
- Evidence strength: source_linked
- Finding: Project evidence flags a installation risk. Review the linked source before relying on this workflow.
- User impact: May increase setup, validation, or first-run risk for the user.
- Evidence: community_evidence:github | https://github.com/ItzCrazyKns/Vane/issues/1148

## 5. Installation risk - Installation risk requires verification

- Severity: medium
- Evidence strength: source_linked
- Finding: Project evidence flags a installation risk. Review the linked source before relying on this workflow.
- User impact: May increase setup, validation, or first-run risk for the user.
- Evidence: community_evidence:github | https://github.com/ItzCrazyKns/Vane/issues/1153

## 6. Installation risk - Installation risk requires verification

- Severity: medium
- Evidence strength: source_linked
- Finding: Project evidence flags a installation risk. Review the linked source before relying on this workflow.
- User impact: May increase setup, validation, or first-run risk for the user.
- Evidence: community_evidence:github | https://github.com/ItzCrazyKns/Vane/issues/1154

## 7. Configuration risk - Configuration risk requires verification

- Severity: medium
- Evidence strength: source_linked
- Finding: Project evidence flags a configuration risk. Review the linked source before relying on this workflow.
- User impact: May increase setup, validation, or first-run risk for the user.
- Evidence: capability.host_targets | https://github.com/ItzCrazyKns/Vane

## 8. Configuration risk - Configuration risk requires verification

- Severity: medium
- Evidence strength: source_linked
- Finding: Project evidence flags a configuration risk. Review the linked source before relying on this workflow.
- User impact: May increase setup, validation, or first-run risk for the user.
- Evidence: community_evidence:github | https://github.com/ItzCrazyKns/Vane/issues/1150

## 9. Capability evidence risk - Capability evidence risk requires verification

- Severity: medium
- Evidence strength: source_linked
- Finding: README/documentation is current enough for a first validation pass.
- User impact: May increase setup, validation, or first-run risk for the user.
- Evidence: capability.assumptions | https://github.com/ItzCrazyKns/Vane

## 10. Runtime risk - Runtime risk requires verification

- Severity: medium
- Evidence strength: source_linked
- Finding: Project evidence flags a runtime risk. Review the linked source before relying on this workflow.
- User impact: May increase setup, validation, or first-run risk for the user.
- Evidence: community_evidence:github | https://github.com/ItzCrazyKns/Vane/issues/1147

## 11. Maintenance risk - Maintenance risk requires verification

- Severity: medium
- Evidence strength: source_linked
- Finding: Project evidence flags a maintenance risk. Review the linked source before relying on this workflow.
- User impact: May increase setup, validation, or first-run risk for the user.
- Evidence: evidence.maintainer_signals | https://github.com/ItzCrazyKns/Vane

## 12. Security or permission risk - Security or permission risk requires verification

- Severity: medium
- Evidence strength: source_linked
- Finding: no_demo
- User impact: May increase setup, validation, or first-run risk for the user.
- Evidence: downstream_validation.risk_items | https://github.com/ItzCrazyKns/Vane

## 13. Security or permission risk - Security or permission risk requires verification

- Severity: medium
- Evidence strength: source_linked
- Finding: no_demo
- User impact: May increase setup, validation, or first-run risk for the user.
- Evidence: risks.scoring_risks | https://github.com/ItzCrazyKns/Vane

## 14. Security or permission risk - Security or permission risk requires verification

- Severity: medium
- Evidence strength: source_linked
- Finding: Project evidence flags a security or permission risk. Review the linked source before relying on this workflow.
- User impact: May increase setup, validation, or first-run risk for the user.
- Evidence: community_evidence:github | https://github.com/ItzCrazyKns/Vane/issues/1143

## 15. Maintenance risk - Maintenance risk requires verification

- Severity: low
- Evidence strength: source_linked
- Finding: issue_or_pr_quality=unknown。
- User impact: May increase setup, validation, or first-run risk for the user.
- Evidence: evidence.maintainer_signals | https://github.com/ItzCrazyKns/Vane

## 16. Maintenance risk - Maintenance risk requires verification

- Severity: low
- Evidence strength: source_linked
- Finding: release_recency=unknown。
- User impact: May increase setup, validation, or first-run risk for the user.
- Evidence: evidence.maintainer_signals | https://github.com/ItzCrazyKns/Vane

<!-- canonical_name: ItzCrazyKns/Vane; human_manual_source: deepwiki_human_wiki -->
